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

news/2024/5/19 13:01:30 标签: 责任链模式, java, spring boot

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

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

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

二. 创建具体责任链节点

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

三. 责任链节点容器

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

java">@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);
				}
			}
		}
	}
}

五. 创建时元数据

java">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;
	}
}

六. 自定义成员变量注解

java">@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BeanField {
	String beanName() default "";
	Class<?> beanType() ;
}

七. 调用接口

java">@Resource
private ScheduleChainBuilderFaced scheduleChainBuilderFaced;

@GetMapping("/xxxx")
@ResponseBody
@Transactional
public void xxxxSchedule() {
	AbstractSchHandlerContains scheduleHandler =
	scheduleChainBuilderFaced.buildChainByList();

	ScheduleHandler.doHandler(new ArrayList<>(), 0, scheduleHandler);
}

http://www.niftyadmin.cn/n/5477717.html

相关文章

DataEase-V1.18版本源码通过Docker镜像部署与静态资源通过阿里云OSS存储实现看这一篇就够了

修改DataEase实现静态资源阿里云OSS存储 后端源码文件读取配置类配置 1.阿里云OSS配置类 /*** ClassName AliyunConfig.java* author shuyixiao* version 1.0.0* Description 阿里云OSS配置* createTime 2024年04月03日 10:03:00*/ Data Configuration public class AliyunC…

芒果YOLOv8改进组合157:动态标签分配ATSS+新颖高效AsDDet检测头组合改进,共同助力VisDrone涨点1.8%,小目标高效涨点

💡本篇内容:【芒果YOLOv8改进ATSS标签分配策略|第三集】芒果YOLOv8改进组合157:动态标签分配ATSS+新颖高效AsDDet检测头组合改进,共同助力VisDrone涨点1.8%,小目标高效涨点 💡🚀🚀🚀本博客 标签分配策略ATSS改进+ 新颖高效AsDDet检测头组合改进,适用于 YOLOv8 …

libVLC 提取视频帧使用OpenGL渲染

在上一节中&#xff0c;我们讲解了如何使用QWidget渲染每一帧视频数据。 由于我们不停的生成的是QImage对象&#xff0c;因此对 CPU 负荷较高。其实在绘制这块我们可以使用 OpenGL去绘制&#xff0c;利用 GPU 减轻 CPU 计算负荷&#xff0c;本节讲解使用OpenGL来绘制每一帧视频…

ideaSSM 网上选课管理系统bootstrap开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea 开发 SSM 网上选课管理系统是一套完善的信息管理系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff…

Paper Digest | GPT-RE:基于大语言模型针对关系抽取的上下文学习

持续分享 SPG 及 SPG LLM 双驱架构应用相关进展 1、动机 在很多自然语言处理任务中&#xff0c;上下文学习的性能已经媲美甚至超过了全资源微调的方法。但是&#xff0c;其在关系抽取任务上的性能却不尽如人意。以 GPT-3 为例&#xff0c;一些基于 GPT-3 的上下文学习抽取方…

橘子学JDK之JMH-04(@Setup @TearDown)

这里我们来操作官方的第五个例子&#xff0c;这里引出一个叫做固定方法的概念。 一、案例代码 package com.levi;import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.run…

c++找最高成绩

根据给定的程序&#xff0c;写成相关的成员函数&#xff0c;完成指定功能。 函数接口定义&#xff1a; 定义max函数&#xff0c;实现输出最高成绩对应的学号以及最高成绩值。 裁判测试程序样例&#xff1a; #include <iostream> using namespace std; class Student{…

小程序开发SSL证书下载和安装

在开发小程序时&#xff0c;确保数据的安全传输至关重要&#xff0c;而实现这一目标的关键在于正确获取与安装SSL证书。以下详细介绍了从获取到安装SSL证书的完整流程&#xff0c;以助您为小程序构建可靠的加密通信环境。 一、小程序SSL证书类型选择&#xff1a; 域名验证型D…