# easy-pipeline **Repository Path**: gitee_pikaqiu/easy-pipeline ## Basic Information - **Project Name**: easy-pipeline - **Description**: 简易的管道流框架 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-10-09 - **Last Updated**: 2023-11-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # easy-pipeline ✨ 不知道大家在公司开发时是不是总遇到一个类中有很长很长的代码的情况,就是所谓的祖传代码,修改一行代码,可能会影响好多地方,我对此深有体会,所以才有了easy-pipeline。easy-pipeline 正如它的名称,是一个简易的管道流框架。 管道流是指一种将数据在一系列处理步骤中传递的模式。将数据从一个阶段传递到下一个阶段的方法。每个阶段执行特定的数据处理操作。 `Data --> Step 1 --> Step 2 --> Step 3 --> Result` 这种模式的目的是简化代码、提高可读性,并将复杂任务分解成小的、可组合的部分。 ## 基本介绍📖 当我们在开发一个很复杂的业务时,要分为几个步骤来进行操作,其中的每一个步骤都较复杂,这时可以使用`easy-pipeline`。将按照操作步骤拆分,以防止业务膨胀,后续难以维护的问题。 例如:模拟电商中的用户下单业务 ```java public void saveOrder(Integer userId){ // 业务参数校验 检查交易合法性 Result checkResult = checkService.checkPayment(); if (userId == null && checkResult.getCode != "AAA" ){ throw new BusinessException("业务参数异常"); } // 查询商品信息 (从数据库查询数据) Goods goods = goodsService.getById(goodsId); // 修改商品库存 (操作数据库) stockService.updateStock(); // 下单 保存订单信息 orderService.saveOrder(); // 调用银行等第三方接口 bankService.moneyUpdate(); // 积分kafka推送 (操作kafka) kafkaTemplate.send(integral); // ... } ``` 我们可以将下单操作进行按照步骤拆分成不同的处理环节,一个类只让它做一个事情,在将这些类像珍珠一样串成一串,使它成为一个链表结构,形成管道。 如果业务后续中某个环节有变化,比如,积分`kafka`推送 存在bug,或想要换一种写法,或者是这个环节不想要了,通过`easy-pipeline`对比之前的写法都可以较为轻松的实现。 ## 快速开始 🛠️ 使用 `easy-pipeline `非常简单,由于现在还没有发布到`maven/aliyun center`中去,如果想要使用,需要clone一下代码,当作一个模块来用即可。 使用之前我觉得有必要简单说一下,管道流顾名思义就是管道+流,在`easy-pipeline`中一个“管道”就是一个`filter`,而“流”,就是`context`即上下文对象,`context`每次由一个管道流入另一个管道,都会经过一些处理。 ### 上下文 需要继承 `AbstractEventContext` #### PipelineContext ```java public class PipelineContext extends AbstractEventContext { public PipelineContext(BizType businessType, FilterSelector filterSelector) { super(businessType, filterSelector); } /** * 请求对象 */ @Getter @Setter private PipelineRequest pipelineRequest; /** * 响应对象 */ @Getter @Setter private PipelineResponse pipelineResponse; /** * 是否继续 */ @Setter private boolean chainContinue = true; @Override public boolean continueChain() { return chainContinue; } @Override public BizType getBizType() { if (Objects.isNull(pipelineRequest)) { throw new IllegalArgumentException("未指定业务操作类型"); } return BusinessTypeEnum.getOneRequire(pipelineRequest.getBizCode()); } } ``` #### PipelineRequest ```java @Data public class PipelineRequest { /** * 业务码 */ private String bizCode; /** * 用户id */ private Integer userId; } ``` #### PipelineResponse ```java @Data public class PipelineResponse { } ``` #### BusinessTypeEnum ```java @Getter @AllArgsConstructor public enum BusinessTypeEnum implements BizType { BUSINESS_1("business1","业务1"), BUSINESS_2("business2","业务2"), ; private String code; private String name; public static BusinessTypeEnum getOneRequire(String bizCode){ for (BusinessTypeEnum msgBizTypeEnum : BusinessTypeEnum.values()) { if (msgBizTypeEnum.getCode().equals(bizCode)) { return msgBizTypeEnum; } } throw new IllegalArgumentException("未找到对应业务类型,业务码: "+ bizCode); } } ``` ### 过滤器 需要继承 `EventFilter` #### Biz1PipelineFilter ```java public interface Biz1PipelineFilter extends EventFilter { } ``` #### Biz1PipelineFilter1 ```java @Slf4j @Component public class Biz1PipelineFilter1 extends AbstractEventFilter implements Biz1PipelineFilter { @Override protected void handler(PipelineContext context) { log.info("Biz1PipelineFilter1 执行了..."); } } ``` #### Biz1PipelineFilter2 ```java @Slf4j @Component public class Biz1PipelineFilter2 extends AbstractEventFilter implements Biz1PipelineFilter { @Override protected void handler(PipelineContext context) { log.info("Biz1PipelineFilter2 执行了..."); } } ``` #### BizPipelineExecuter `easy-pipeline`自带了一个方法模板`BasePipelineTemplate` 如果满足不了当前的业务需求可以重写该模板 ```java @Slf4j @Component public class BizPipelineExecuter extends BasePipelineTemplate { public final PipelineResponse apply(PipelineRequest pipelineRequest) { String bizCode = pipelineRequest.getBizCode(); log.info("[{}]交易开始, 请求参数: {}", bizCode, CharSequenceUtil.replace(JSONUtil.toJsonStr(pipelineRequest), "\n", "")); // 设置上下文对象 BusinessTypeEnum bizTypeEnum = BusinessTypeEnum.getOneRequire(pipelineRequest.getBizCode()); PipelineContext pipelineContext = new PipelineContext(bizTypeEnum, super.filterSelectorFactory.getFilterSelector(bizTypeEnum.getCode())); pipelineContext.setPipelineRequest(pipelineRequest); pipelineContext.setPipelineResponse(new PipelineResponse()); templateFacade(pipelineContext); PipelineResponse pipelineResponse = pipelineContext.getPipelineResponse(); pipelineContext.setPipelineResponse(pipelineResponse); log.info("[{}]交易结束 响应报文: {} ", bizCode, JSONUtil.toJsonStr(pipelineResponse)); return pipelineResponse; } } ``` ### 调用 ```java @SpringBootTest(classes = EasyPipelineApplication.class) @RunWith(SpringRunner.class) public class BizPipelineTest { @Autowired private BizPipelineExecuter bizPipelineExecuter; @Test public void bussiness1(){ PipelineRequest pipelineRequest = new PipelineRequest(); pipelineRequest.setBizCode("business1"); pipelineRequest.setUserId(99999); PipelineResponse pipelineResponse = bizPipelineExecuter.apply(pipelineRequest); } } ``` ### 配置 ```yaml server: port: 9527 # 业务管道流 配置demo pipeline-config: configs: business1: - Biz1PipelineFilter1 - Biz1PipelineFilter2 ``` 可以通过新增或删除对应的过滤器控制对应的业务。 举例,完整业务为:`Data --> Biz1PipelineFilter1 --> Biz1PipelineFilter2 --> Biz1PipelineFilter3 --> Result` 现在不想让 `Biz1PipelineFilter2 `对应的业务执行,此时我们可以不用修改代码直接将对应的配置注释或删除掉即可;同理,如果想要在`Biz1PipelineFilter3 `后面加一个`Biz1PipelineFilter4 `我们需要在编写代码完成后再配置中增加对应的配置。