基于erp业务的责任链模式实战

Handler接口是用来规范所有的责任链节点都要实现 处理数据的方法 AbstractSchHandlerContains
是责任链节点保存的抽象类 ScheduleHandlerContains
子类可以覆盖责任链节点保存容器实现自定义遍历责任链节点容器方法设置自定义容器

一. 创建责任链节点接口 用于规范责任链的处理方法

public interface Handler {void doHandler(List<Schedule> schedules, Integer cursor,AbstractSchHandlerContains abstractSchHandler);
}

二. 创建具体责任链节点

  1. 拉取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);}
}
  1. 判断erp信息节点
public class SwitchHandler implements Handler {@Overridepublic void doHandler(List<Schedule> schedules, Integer cursor,AbstractSchHandlerContains abstractSchHandler) {schedules.forEach(a -> {//做数据判断 然后再传递给下一个节点});abstractSchHandler.doHandler(schedules, cursor,abstractSchHandler);}
}
  1. 整理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);}
}
  1. 保存数据
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);}
}

三. 责任链节点容器

  1. 抽象节点容器
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);//责任链递归回来后执行代码区域}}
}
  1. 具体责任链节点容器
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);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/801976.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

volta(轻松切换管理Node.js版本)

Node.js版本管理 Volta提供了一个简单直观的命令行界面&#xff0c;可以轻松地安装、卸载、更新和切换Node.js版本。 Volta 既可以全局使用&#xff0c;也可以在项目级别使用&#xff0c;可以为每个项目单独设置node版本&#xff0c;nvm不行。 下载安装Volta 参考&#xff1a; …

蓝桥杯-网络安全比赛(5)基础学习-JavaScript原型链的prototype、constructor、object.create()、__proto__

JavaScript的prototype、constructor、Object.create()和__proto__通常不直接作为解题的关键&#xff0c;但它们对于理解和分析Web应用的安全性至关重要。 网络安全比赛通常涉及Web应用的漏洞挖掘和攻击&#xff0c;这要求参赛者具备深厚的Web开发知识&#xff0c;包括JavaScri…

深度学习的层、算子和函数空间

目录 一、层、算子和函数空间概念 二、层&#xff08;Layers&#xff09; 三、算子&#xff08;Operators&#xff09; 3.1常见算子 3.2常见算子的性质 四、函数空间&#xff08;Function Space&#xff09; 一、层、算子和函数空间概念 层&#xff08;Layers&#xff09…

自建远程桌面服务器,控制免root安卓手机和pc

RustDesk是一个开源的远程桌面软件&#xff0c;它允许用户通过互联网在不同设备之间共享桌面和控制权限。这款软件以最少的配置提供了自托管和安全保障&#xff0c;是一个类似于TeamViewer的开源替代品​ (RustDesk)​。RustDesk支持在Windows、macOS、Linux、iOS、Android以及…

[数据概念]对原始公开数据赋权的思考

“ 对于原始、公开信息&#xff0c;要充分保障整个社会对该类信息资源的合理利用&#xff0c;以维护信息公平和促进更大范围的创新。。” 2022年12月&#xff0c;党中央、国务院发布《关于构建数据基础制度更好发挥数据要素作用的意见》&#xff08;以下称《数据二十条》&#…

Java8新特性--lambda表达式

lambda表达式本质上是一个匿名函数&#xff0c;在lambda表达式中我们只需要关心参数列表以及方法体。优点是可以减少代码量。 1.语法 基本语法&#xff1a;(参数)->表达式 或 (参数) -> {语句;} 2.函数式接口 要了解lambda表达式&#xff0c;首先要了解什么是函数式接口…

互联网大厂ssp面经之路:计算机网络part2

什么是 HTTP 和 HTTPS&#xff1f;它们之间有什么区别&#xff1f; a. HTTP&#xff08;超文本传输协议&#xff09;和HTTPS&#xff08;安全超文本传输协议&#xff09;是用于在Web上传输数据的协议。它们之间的区别在于安全性和数据传输方式。 b. HTTP是一种不安全的协议&…

[RK3588-Android12] 关于HDMIN-IN视频调试命令

问题描述 如题关于HDMIN-IN视频应该如何调试。 解决方案&#xff1a; 视频调试 HDMI-IN 设备在内核中会被注册为 video 设备&#xff0c;生成的节点如&#xff1a;/dev/video8。 可以通过 v4l2-ctl 命令来获取设备信息和抓帧。 1.获取设备信息&#xff1a; v4l2-ctl -d /dev…

变分自编码器生成新的手写数字图像

变分自编码器&#xff08;Variational Autoencoder&#xff0c;VAE&#xff09;是一种生成模型&#xff0c;通常用于学习数据的潜在表示&#xff0c;并用于生成新的数据样本。它由两部分组成&#xff1a;编码器和解码器。 编码器&#xff08;Encoder&#xff09;&#xff1a;接…

用Echarts词云数据可视化热词表白​​

目录 1、使用前准备 2、准备工作 3、盒子搭建 4、整体展现 1、使用前准备 找到表白对象&#xff08;重中之重&#xff01;&#xff09;&#xff0c;不要一见钟情&#xff08;个人觉得&#xff1a;一见钟情属于见色起意&#xff01;&#xff09;&#xff0c;因为数据可视化需…

高效洁净,静音运行:油烟净化器助力餐饮业绿色发展

我最近分析了餐饮市场的油烟净化器等产品报告&#xff0c;解决了餐饮业厨房油腻的难题&#xff0c;更加方便了在餐饮业和商业场所有需求的小伙伴们 餐饮业作为繁忙城市中蓬勃发展的一部分&#xff0c;一直在不懈努力&#xff0c;以满足人们对美食的渴望。但在烹饪的背后&#…

Unity自定义框架(2)-----------事件中心

前言&#xff1a; Unity作为一款强大的游戏开发引擎&#xff0c;提供了丰富的工具和框架&#xff0c;其中事件中心框架是一个备受关注的重要组成部分。本文将深入探讨Unity事件中心框架的重要性以及它在游戏开发中的作用。 什么是事件中心框架&#xff1f; 事件中心框架是一…

Python中的Lambda匿名函数

背景 Lambda匿名函数在Python中经常出现&#xff0c;小巧切灵活&#xff0c;使用起来特别方便&#xff0c;但是小编建议大家少使用&#xff0c;最好多写几行代码&#xff0c;自定义个函数。 既然Python中存在Lambda匿名函数&#xff0c;那么小编本着存在即合理的原则&#xf…

海外仓为何要做仓库管理系统?位像素海外仓系统的仓库管理功能有哪些?

在当今繁荣的跨境电商市场中&#xff0c;海外仓已经成为了许多电商企业的重要选择。但是&#xff0c;海外仓的成功与否并不仅仅取决于其位置和规模&#xff0c;同样重要的是其仓库管理系统的有效性。那么&#xff0c;海外仓为何要做仓库管理系统呢&#xff1f;让我们一起来探讨…

统计机构编配

办公室、组织人事处、政策法规处、国民经济综合统计处、国民经济核算处、工业统计处、固定资产投资统计处、贸易外经统计处、城镇化和人口就业统计处、农村统计处、能源统计处、服务业统计综合处、普查处、机关党委&#xff0c;市社会经济调查中心、市统计执法监察支队、市社情…

“成像光谱遥感技术中的AI革命:ChatGPT在遥感领域中的应用“

遥感技术主要通过卫星和飞机从远处观察和测量我们的环境&#xff0c;是理解和监测地球物理、化学和生物系统的基石。ChatGPT是由OpenAI开发的最先进的语言模型&#xff0c;在理解和生成人类语言方面表现出了非凡的能力。本文重点介绍ChatGPT在遥感中的应用&#xff0c;人工智能…

可视化大屏的应用(9):智慧旅游和智慧景区

可视化大屏在智慧旅游领域具有多种价值&#xff0c;可以为旅游管理者和游客提供更加便捷、优质的服务和体验。本期大千UI工场带来智慧旅游和智慧景区的可视化大屏界面&#xff0c;供大家欣赏。 可视化大屏在智慧旅游领域的价值如下&#xff1a; 提供全面的信息展示&#xff0…

蓝桥杯每日一题:母亲的奶牛(BFS)

农夫约翰有三个容量分别为 A,B,C升的挤奶桶。 最开始桶 A 和桶 B 都是空的&#xff0c;而桶 C 里装满了牛奶。 有时&#xff0c;约翰会将牛奶从一个桶倒到另一个桶中&#xff0c;直到被倒入牛奶的桶满了或者倒出牛奶的桶空了为止。 这一过程中间不能有任何停顿&#xff0c;并…

数据结构:构建完全二叉查找树

文章目录 1、步骤 1: 对给定数组排序2、步骤 2: 递归构建完全二叉查找树3、注意4、在有序数组中寻找根结点位置5、代码实现6、其他方法&#xff1f;基本思路插入操作删除操作特别考虑 对于一个给定序列的二叉查找树&#xff0c;有很多种&#xff0c;但是完全二叉查找树只有一种…

浏览器工作原理与实践--分层和合成机制:为什么CSS动画比JavaScript高效

在上一篇文章中我们分析了CSS和JavaScript是如何影响到DOM树生成的&#xff0c;今天我们继续沿着渲染流水线向下分析&#xff0c;来聊聊DOM树之后所发生的事情。 在前面《05 | 渲染流程&#xff08;上&#xff09;&#xff1a;HTML、CSS和JavaScript文件&#xff0c;是如何变成…