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;@Overridepublic 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 {@Overridepublic 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;@Overridepublic 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;@Overridepublic 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;}@Overridepublic 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
{@Overridepublic List<Handler> getFiltersChain() {return super.getFiltersChain();}@Overridepublic void setFiltersChain(List<Handler> filtersChain) {super.setFiltersChain(filtersChain);}@Overridepublic 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容器@Overridepublic void setApplicationContext(ApplicationContext applicationContext)throws BeansException {this.springContext = applicationContext;}//获取责任链容器的方法public AbstractSchHandlerContains buildChainByList() {//如果没有配置,直接返回nullif (handlerType == null) {return null;}//如果是第一次配置,将handlerType记录下来if (currentHandlerType == null) {this.currentHandlerType = this.handlerType;}currentHandlerif (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);
}