枚举实现责任链

责任链允许请求沿着处理者链进行处理,类似于拦截器

责任链由三部分组成

  • 抽象处理者(Handler):定义一个处理请求的抽象类,包含处理方法和一个 next 指针
  • 具体处理者:实现抽象处理者方法
  • 客户端

抽象处理者

1
2
3
4
5
6
7
8
9
public abstract class GatewayHandler {
protected GatewayHandler next;

public void setNext(GatewayHandler next){
this.next = next;
}

public abstract int handler();
}

具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class ApiLimitGatewayHandler extends GatewayHandler {
private static final Logger log = LoggerFactory.getLogger(ApiLimitGatewayHandler.class);

@Override
public int handler() {
log.info("Api 限流网关处理器执行中...");
// ... 这里判断是否满足这个责任链
// 如果满足,看是否有下一个责任链,
if (next != null){
return next.handler();
}
return 0;
}
}

public class BlackListGatewayHandler extends GatewayHandler {
private static final Logger log = LoggerFactory.getLogger(BlackListGatewayHandler.class);

@Override
public int handler() {
log.info("黑名单处理器执行中...");
if (next != null) {
return next.handler();
}
return 0;
}
}

public class SessionGatewayHandler extends GatewayHandler {
private static final Logger log = LoggerFactory.getLogger(SessionGatewayHandler.class);

@Override
public int handler() {
log.info("Session 处理器执行中...");
if (next != null){
return next.handler();
}
return 0;
}
}

接下来用枚举进行责任链的配置

目录结构:

  1. 定义一个实体类,存放责任链的实体信息
1
2
3
4
5
6
7
8
9
10
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GatewayEntity {
private String name;
private String conference; // 全限定类名
private Integer handlerId;
private Integer preHandlerId;
private Integer nextHandlerId;
}
  1. 定义一个枚举,里面存储 GatewayEntity (枚举本质上也是一个类,里面的枚举对象是用一个数组存储的)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public enum GatewayEnum {
API_HANDLER(new GatewayEntity("API 限流", "com.dong.demo.design.chain.impl.ApiLimitGatewayHandler",
1, null, 2)),
BLACKLIST_HANDLER(new GatewayEntity("黑名単限流", "com.dong.demo.design.chain.impl.BlackListGatewayHandler",
2, 1, 3)),
SESSION_HANDLER(new GatewayEntity("用户会话限流", "com.dong.demo.design.chain.impl.SessionGatewayHandler",
3, 2, null));

private GatewayEntity gatewayEntity;

GatewayEnum(GatewayEntity gatewayEntity){
this.gatewayEntity = gatewayEntity;
}

public GatewayEntity getGatewayEntity() {
return gatewayEntity;
}
}
  1. 一个接口,获取第一个 GatewayEntity 和指定的 GatewayEntity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public interface GatewayEntityService {
/**
* 根据 handlerId 获取配置项
* @param handlerId
* @return
*/
GatewayEntity getGatewayEntity(Integer handlerId);

/**
* 获取第一个 handler
* @return
*/
GatewayEntity getFirstGatewayEntity();
}

public class GatewayEntityServiceImpl implements GatewayService{
private static Map<Integer, GatewayEntity> gatewayEntityMap = new HashMap<>();
static {
GatewayEnum[] values = GatewayEnum.values();
for (GatewayEnum value : values) {
GatewayEntity gatewayEntity = value.getGatewayEntity();
gatewayEntityMap.put(gatewayEntity.getHandlerId(), gatewayEntity);
}
}

@Override
public GatewayEntity getGatewayEntity(Integer handlerId) {
return gatewayEntityMap.get(handlerId);
}

@Override
public GatewayEntity getFirstGatewayEntity() {
for (Map.Entry<Integer, GatewayEntity> entity : gatewayEntityMap.entrySet()) {
GatewayEntity value = entity.getValue();
if (value.getPreHandlerId() == null) return value;
}
return null;
}

}
  1. 一个工厂类,获取第一个 handler 并把其他的 handler 串联起来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class GatewayHandlerEnumFactory {
private static GatewayEntityService gatewayService = new GatewayEntityServiceImpl();

/**
* 获取第一个 handler
* @return
*/
public static GatewayHandler getFirstGatewayHandler(){
GatewayEntity firstGatewayEntity = gatewayService.getFirstGatewayEntity();
GatewayHandler firstGatewayHandler = newGatewayHandler(firstGatewayEntity);
if (firstGatewayHandler == null) {
return null;
}

GatewayEntity curGatewayEntity = firstGatewayEntity;
GatewayHandler curGatewayHandler = firstGatewayHandler;
Integer nextHandlerId = null;
while ((nextHandlerId = curGatewayEntity.getNextHandlerId()) != null){
GatewayEntity gatewayEntity = gatewayService.getGatewayEntity(nextHandlerId);
GatewayHandler gatewayHandler = newGatewayHandler(gatewayEntity);
curGatewayHandler.setNext(gatewayHandler);
curGatewayEntity = gatewayEntity;
curGatewayHandler = gatewayHandler;
}
return firstGatewayHandler;
}

/**
* 反射实例化具体的处理者
* @param gatewayEntity
* @return
*/
private static GatewayHandler newGatewayHandler(GatewayEntity gatewayEntity){
String className = gatewayEntity.getConference();
try {
Class<?> clazz = Class.forName(className);
return (GatewayHandler) clazz.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
  1. 一个客户端进行测试
1
2
3
4
5
6
public class GatewayClient {
public static void main(String[] args) {
GatewayHandler firstGatewayHandler = GatewayHandlerEnumFactory.getFirstGatewayHandler();
firstGatewayHandler.handler();
}
}

枚举实现责任链
http://showyoubug.cn/2024/06/26/枚举实现责任链/
作者
Dong Su
发布于
2024年6月26日
许可协议