Handler接口是用来规范所有的责任链节点都要实现 处理数据的方法 AbstractSchHandlerContains
是责任链节点保存的抽象类 ScheduleHandlerContains
子类可以覆盖责任链节点保存容器实现自定义遍历责任链节点容器方法设置自定义容器
一. 创建责任链节点接口 用于规范责任链的处理方法
public interface Handler {
void doHandler(List<Schedule> schedules, Integer cursor,
AbstractSchHandlerContains abstractSchHandler);
}
二. 创建具体责任链节点
- 拉取erp业务数据节点
public class PullSchDataHandler implements Handler {
public final ExecutorService executor = Executors.newFixedThreadPool(9);
@BeanField(beanName = "xxxService",beanType = xxxService.class)
private PullScheduleMetadataService pullScheduleMetadataService;
@Override
public void doHandler(List<Schedule> schedules, Integer cursor,
AbstractSchHandlerContains abstractSchHandler) {
//使用executor拉取WMS的仓储信息 并且保存在schedules集合中
schedules.addAll('erp业务详情');
//传递到下一个节点
abstractSchHandler.doHandler(schedules, cursor,
abstractSchHandler);
}
}
- 判断erp信息节点
public class SwitchHandler implements Handler {
@Override
public void doHandler(List<Schedule> schedules, Integer cursor,
AbstractSchHandlerContains abstractSchHandler) {
schedules.forEach(a -> {
//做数据判断 然后再传递给下一个节点
});
abstractSchHandler.doHandler(schedules, cursor,
abstractSchHandler);
}
}
- 整理erp信息到数据流中
public class ColHandler implements Handler {
@BeanField(beanName = "xxxMapper", beanType = xxxMapper.class)
private xxxMapper xxxMapper;
@Override
public void doHandler(List<Schedule> schedules, Integer cursor,
AbstractSchHandlerContains abstractSchHandler) {
//获取信息传递到下一个节点
schedules.addAll('协助信息');
abstractSchHandler.doHandler(schedules, cursor,
abstractSchHandler);
}
}
- 保存数据
public class SaveHandler implements Handler {
@BeanField(beanName = "xxxMapper", beanType = xxxMapper.class)
private xxxMapper xxxMapper;
@Override
public void doHandler(List<Schedule> schedules, Integer cursor,
AbstractSchHandlerContains abstractSchHandler) {
//保存数据
int i = xxxMapper.saveAll(schedules);
abstractSchHandler.doHandler(schedules, cursor,
abstractSchHandler);
}
}
三. 责任链节点容器
- 抽象节点容器
public abstract class AbstractSchHandlerContains implements Handler {
//责任链节点容器
protected List<Handler> filtersChain = new ArrayList<>();
public List<Handler> getFiltersChain() {
return filtersChain;
}
public void setFiltersChain(List<Handler> filtersChain) {
this.filtersChain = filtersChain;
}
@Override
public void doHandler(List<Schedule> schedules, Integer cursor,
AbstractSchHandlerContains abstractSchHandler) {
//遍历责任链
//判断是否遍历到责任链容器的末尾
if (cursor < filtersChain.size()) {
//获取责任链容器中的节点
Handler handler = filtersChain.get(cursor);
//移动游标
cursor++;
//执行节点的业务逻辑
handler.doHandler(schedules, cursor, abstractSchHandler);
//责任链递归回来后执行代码区域
}
}
}
- 具体责任链节点容器
public class ScheduleHandlerContains extends AbstractSchHandlerContains
{
@Override
public List<Handler> getFiltersChain() {
return super.getFiltersChain();
}
@Override
public void setFiltersChain(List<Handler> filtersChain) {
super.setFiltersChain(filtersChain);
}
@Override
public void doHandler(List<Schedule> schedules, Integer cursor,
AbstractSchHandlerContains abstractSchHandler) {
//实现自定义的遍历节点方法
super.doHandler(schedules, cursor, abstractSchHandler);
}
}
四. 获取责任链容器节点的门面类
自定义注解再结合 ApplicationContextAware 接口获得spring容器 使用反射设置对象的成员变量
handlerType的值
@Slf4j
@Component
public class ScheduleChainBuilderFaced implements ApplicationContextAware {
//责任链节点控制变量
//用来控制责任链节点的顺序与 责任链是否重构的变量
//duty.chain默认值是pullData,judDoc,collaborate,saveData
@Value("${duty.chain}")
private volatile String handlerType;
//记录当前handlerType的配置,判断duty.chain的配置是否有修改
//如果有修改,说明duty.chain的配置有修改,需要从新初始化责任链条
private String currentHandlerType;
//记录责任链节点的成员变量
private AbstractSchHandlerContains handlerList;
//spring容器
private ApplicationContext springContext;
//重写ApplicationContextAware接口的方法 用于获取spring容器
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.springContext = applicationContext;
}
//获取责任链容器的方法
public AbstractSchHandlerContains buildChainByList() {
//如果没有配置,直接返回null
if (handlerType == null) {
return null;
}
//如果是第一次配置,将handlerType记录下来
if (currentHandlerType == null) {
this.currentHandlerType = this.handlerType;
}
currentHandler
if (this.handlerType.equals(currentHandlerType) && this.handlerList
!= null) {
return handlerList;
} else {
synchronized (this) {
//双检锁 保证线程安全
if (this.handlerType.equals(currentHandlerType) &&
this.handlerList != null) {
return handlerList;
}
try {
log.info("配置有修改或首次初始化,组装责任链条!!!");
//创建责任链容器
handlerList = new ScheduleHandlerContains();
List<String> handlerTypeList =
Arrays.asList(handlerType.split(","));
//获取自定义注解中的值 用来初始化责任链节点中的成员变量
for (String handlerType : handlerTypeList) {
//获取字节码对象
Class<?> aClass =
Class.forName(HandlerEnumByList.valueOf(handlerType).getValue());
//创建对象
Handler handler = (Handler) aClass.newInstance();
//获取注解
for (Field declaredField :
aClass.getDeclaredFields()) {
//获取自定义注解中的值
BeanField annotation =
declaredField.getAnnotation(BeanField.class);
if (!Objects.isNull(annotation)) {
//获取注解中的值
String requireBeanName =
annotation.beanName();
Class<?> requireBeanType =
annotation.beanType();
//从spring容器中获取
Object bean =
springContext.getBean(requireBeanName, requireBeanType);
declaredField.setAccessible(true);
//给成员变量赋值
declaredField.set(handler, bean);
}
}
//加入责任链节点容器中 //默认加入ArrayList中
handlerList.getFiltersChain().add(handler);
}
//从新赋值修改后的配置
this.currentHandlerType = this.handlerType;
// 返回责任链条
return handlerList;
} catch (Exception e) {
throw new UnsupportedOperationException(e);
}
}
}
}
}
五. 创建时元数据
public enum HandlerEnumByList {
collaborate("com.xxx.schedutychain.handlers.ColHandler"),
judDoc("com.xxx.schedutychain.handlers.SwitchHandler"),
pullData("com.xxx.schedutychain.handlers.PullSchDataHandler"),
saveData("com.xxx.schedutychain.handlers.SaveHandler");
String value = "";
HandlerEnumByList(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
六. 自定义成员变量注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BeanField {
String beanName() default "";
Class<?> beanType() ;
}
七. 调用接口
@Resource
private ScheduleChainBuilderFaced scheduleChainBuilderFaced;
@GetMapping("/xxxx")
@ResponseBody
@Transactional
public void xxxxSchedule() {
AbstractSchHandlerContains scheduleHandler =
scheduleChainBuilderFaced.buildChainByList();
ScheduleHandler.doHandler(new ArrayList<>(), 0, scheduleHandler);
}