设计模式:责任链模式的动态配置
设计模式:责任链模式的动态配置
在Spring Boot项目中,责任链模式可以通过各种方式实现,其中之一是通过配置动态责任链的顺序。以下是一个示例,展示如何在Spring Boot中实现动态可配置的责任链模式。
1. 责任链模式简介
责任链模式是一种行为设计模式,允许多个对象依次处理请求,直到有对象处理该请求为止。请求沿着责任链传递,每个对象有机会处理该请求或将其传递给链中的下一个对象。但是往往在实际开发过程中,需求是多变的,按照传统的写法流程比较固定,不能灵活的增加或减少流程节点,亦不能调整处理的顺序。以下通过一个请假申请的例子展示如何实现流程动态可配。
2. 设计思路
在Spring Boot项目中,可以使用Spring的依赖注入机制和配置文件来实现动态责任链。具体思路如下:
- 定义处理器接口:定义一个处理请求的处理器接口。
- 实现多个处理器:实现多个处理器类,每个处理器负责处理不同的逻辑。
- 配置处理器顺序:通过Spring的配置文件或数据库配置处理器的顺序。
- 动态构建责任链:根据配置动态构建责任链。
3. 示例实现
一般请假需要通过团队负责人和部门领导的同意,级别高一些的需要经过老板的同意。甚至也有跳过下级领导直接让上级领导审批的情况,也有专门的人负责请假审核的情况。所以这个请假流程最好可以动态的配置业务处理的顺序或增加减少人员的审批。
3.1 定义处理器接口
首先,定义一个处理器抽象类,每个请假审批节点都继承这个抽象类,并实现handRequest
方法处理每一类审批人自己的逻辑,这儿为了抽离处理下一个流程的公共代码handNextRequest
。
public abstract class Handler {
protected Handler nextHandler = null;
void setNextHandler(Handler handler) {
this.nextHandler = handler;
}
protected abstract void handRequest(RequestParam param);
protected void handNextRequest(RequestParam param) {
if (nextHandler != null) {
nextHandler.handRequest(param);
}
}
}
3.2 实现多个处理器
接下来,实现多个请假审批环节的处理器类,可在其中实现自己的业务处理逻辑。
@Slf4j
@Service("teamLeaderHandler")
public class TeamLeaderHandler extends Handler {
@Override
public void handRequest(RequestParam param) {
log.info( "{}提交请假申请,请假事由为:{}", param.getName(), param.getReason());
log.info("团队负责人同意,其工作已经交接");
super.handNextRequest(param);
}
}
@Slf4j
@Service("departmentLeaderHandler")
public class DepartmentLeaderHandler extends Handler {
@Override
public void handRequest(RequestParam param) {
log.info( "{}提交请假申请,请假事由为:{}", param.getName(), param.getReason());
log.info("部门领导同意,请假时长合适");
super.handNextRequest(param);
}
}
@Slf4j
@Service("boosHandler")
public class BoosHandler extends Handler {
@Override
public void handRequest(RequestParam param) {
log.info( "{}提交请假申请,请假事由为:{}", param.getName(), param.getReason());
log.info("老板同意,摸鱼快乐~");
super.handNextRequest(param);
}
}
3.3 定义请求类
定义一个简单的请求类:
@Setter
@Getter
@AllArgsConstructor
public class RequestParam {
// 请假人姓名
private String name;
// 原因
private String reason;
}
3.4 配置处理器顺序
在Spring Boot的配置文件(application.yml或application.properties)中配置请假的流程处理器,按所需执行先后顺序配置;
handlers:
order:
- departmentLeaderHandler
- teamLeaderHandler
- boosHandler
3.5 配置类
定义一个配置类,用于读取配置文件中的处理器顺序:
@Setter
@Getter
@Configuration
@ConfigurationProperties(prefix = "handlers")
public class HandlerProperties {
private List<String> order;
}
3.6 动态构建责任链
使用Spring来动态构建责任链,根据配置的顺序和内容构建任务链;并提供一个handle
方法用于执行;
@Component
public class HandlerChain {
@Autowired
private HandlerProperties handlerProperties;
@Autowired
private ApplicationContext context;
private Handler headHandler;
@PostConstruct
public void init() {
List<String> orderList = handlerProperties.getOrder();
Handler nextHandler = null;
for (String handlerName : orderList) {
Handler handler = (Handler) context.getBean(handlerName);
if (nextHandler == null) {
headHandler = handler;
} else {
nextHandler.setNextHandler(handler);
}
nextHandler = handler;
}
}
public void handle(RequestParam param) {
this.headHandler.handRequest(param);
}
}
4. 使用责任链
4.1 配置测试
使用单元测试,来测试责任链来处理请求:
@Autowired
private HandlerChain handlerChain;
/**
* 责任链动态配置测试
*/
@Test
void chain() {
RequestParam requestParam = new RequestParam("pujiho", "摸鱼");
handlerChain.handle(requestParam);
}
执行结果:
2024-06-18 17:15:02.383 INFO 3432 --- [ main] c.p.p.p.xw.zrl.impl.TeamLeaderHandler : pujiho提交请假申请,请假事由为:摸鱼
2024-06-18 17:15:02.384 INFO 3432 --- [ main] c.p.p.p.xw.zrl.impl.TeamLeaderHandler : 团队负责人同意,其工作已经交接
2024-06-18 17:15:02.384 INFO 3432 --- [ main] c.p.p.p.x.z.i.DepartmentLeaderHandler : pujiho提交请假申请,请假事由为:摸鱼
2024-06-18 17:15:02.384 INFO 3432 --- [ main] c.p.p.p.x.z.i.DepartmentLeaderHandler : 部门领导同意,请假时长合适
2024-06-18 17:15:02.384 INFO 3432 --- [ main] c.p.p.patterns.xw.zrl.impl.BoosHandler : pujiho提交请假申请,请假事由为:摸鱼
2024-06-18 17:15:02.384 INFO 3432 --- [ main] c.p.p.patterns.xw.zrl.impl.BoosHandler : 老板同意,摸鱼快乐~
我们试试修改配置:
handlers:
order:
# - teamLeaderHandler
# - departmentLeaderHandler
- boosHandler
执行结果:
2024-06-18 17:18:31.711 INFO 30364 --- [ main] c.p.p.patterns.xw.zrl.impl.BoosHandler: pujiho提交请假申请,请假事由为:摸鱼
2024-06-18 17:18:31.712 INFO 30364 --- [ main] c.p.p.patterns.xw.zrl.impl.BoosHandler: 老板同意,摸鱼快乐~
4.2 增加流程
如果我们需要新增一个流程,请假通过后,需要人事处理考勤等信息。
新增一个PersonnelHandler
继承Handler
:
@Slf4j
@Service("personnelHandler")
public class PersonnelHandler extends Handler {
@Override
public void handRequest(RequestParam param) {
log.info( "{}提交请假申请,请假事由为:{}", param.getName(), param.getReason());
log.info("人事部门同意,已处理考勤等相关信息");
super.handNextRequest(param);
}
}
修改配置:
handlers:
order:
# - teamLeaderHandler
# - departmentLeaderHandler
- boosHandler
- personnelHandler
执行结果:
2024-06-18 17:30:06.907 INFO 30492 --- [ main] c.p.p.patterns.xw.zrl.impl.BoosHandler: pujiho提交请假申请,请假事由为:摸鱼
2024-06-18 17:30:06.908 INFO 30492 --- [ main] c.p.p.patterns.xw.zrl.impl.BoosHandler: 老板同意,摸鱼快乐~
2024-06-18 17:30:06.908 INFO 30492 --- [ main] c.p.p.p.xw.zrl.impl.PersonnelHandler : pujiho提交请假申请,请假事由为:摸鱼
2024-06-18 17:30:06.908 INFO 30492 --- [ main] c.p.p.p.xw.zrl.impl.PersonnelHandler : 人事部门同意,已处理考勤等相关信息
总结
通过上述步骤,我们在Spring Boot项目中实现了责任链模式,并且可以通过配置文件动态配置责任链的顺序以及增加和减少任务。这种方式结合了Spring的依赖注入和配置管理能力,使得责任链的维护更加灵活和易于管理。
转载自:https://juejin.cn/post/7381649927145472040