责任链模式是一种行为设计模式,它允许构建一个由多个对象组成的链,每个对象都有机会处理请求,或者将请求传递给链中的下一个对象。这种模式的使用场景主要包括但不限于:日志处理、权限验证、资源分配、异常处理等
我个人使用的场景为:下单接口的验证,当一个商品下单时,要对当前订单进行一系列的校验,并且不同的校验涉及到不同的服务和逻辑,当其中任意一个校验不通过时,都会返回失败,所以将每一个校验当做每一个链,每一个链执行完后指向下一个链。
1.定义处理接口
public interface ContextHandler {
void setNext(ContextHandler handler);
void setPre(ContextHandler handler);
void handle(GlobalContext param);
void rollback(GlobalContext param);
}
2.定义全局上下文参数
@Data
public class GlobalContext {
private String orderId;
private String payFee;
}
3.定义处理器抽象类
public abstract class AbstractContextHandler implements ContextHandler {
protected ContextHandler pre;
protected ContextHandler next;
@Override
public void handle(GlobalContext param) {
try {
this.doHandler(param);
if (next != null) {
next.handle(param);
}
} catch (Exception e) {
if (pre != null) {
pre.rollback(param);
}
}
}
@Override
public void rollback(GlobalContext param) {
this.doRollback(param);
}
abstract void doHandler(GlobalContext param);
abstract void doRollback(GlobalContext param);
@Override
public void setNext(ContextHandler handler) {
this.next = handler;
}
@Override
public void setPre(ContextHandler handler) {
this.pre = handler;
}
}
4.定义每个执行单元业务处理handler,(order从小到大执行)
@Component
@Order(2)
public class BuniessPayHandler extends AbstractContextHandler {
@Override
void doHandler(GlobalContext param) {
System.out.println("BuniessPayHandler业务处理doHandler");
}
@Override
void doRollback(GlobalContext param) {
}
}
@Component
@Order(1)
public class BuniessProductHandler extends AbstractContextHandler {
@Override
void doHandler(GlobalContext param) {
System.out.println("BuniessProductHandler业务处理doHandler");
}
@Override
void doRollback(GlobalContext param) {
}
}
5.定义责任链配置(项目启动时初始化执行顺序,以及调用执行入口)
@Component
public class Chain {
@Resource
private List<ContextHandler> handlerList;
private ContextHandler header;
@PostConstruct
public void init() {
if (CollectionUtils.isEmpty(handlerList)) {
return;
}
ContextHandler pre = null;
ListIterator<ContextHandler> iterator = handlerList.listIterator();
while (iterator.hasNext()) {
ContextHandler handler = iterator.next();
if (header == null) {
header = handler;
}
handler.setPre(pre);
pre = handler;
if (iterator.hasNext()) {
handler.setNext(iterator.next());
iterator.previous();
}
}
}
public void handler(GlobalContext param) {
if (header == null) {
return;
}
header.handle(param);
}
}
6.单元测试
@Autowired
private Chain chain;
@GetMapping("/test")
public WebResponse<BrandRelationResult> test(GlobalContext param) {
chain.handler(param);
return null;
}