JAVA中支持可配置化的异步责任链模式的实现(1)

一.JAVA 中责任链的实现(一)

         该责任链采用可配置方式,选取责任链执行节点,并且支持链路中存在异步流程

  1.业务接口api

package com.zhuque.springcloudweb.chain.api;

import com.zhuque.springcloudweb.chain.bean.AsyncCallBackRequest;
import com.zhuque.springcloudweb.chain.bean.SyncRequest;

public interface ProcessApi {

    /**
     * 同步请求流程
     * @param request
     */
    public void syncReq (SyncRequest request);

    /**
     * 异步回调
     * @param request
     */
    public void asyncCallBack(AsyncCallBackRequest request);
}

 

2.流程实现

 

package com.zhuque.springcloudweb.chain.api.impl;

import com.zhuque.springcloudweb.chain.NextProcessServiceFactory;
import com.zhuque.springcloudweb.chain.ProcessService;
import com.zhuque.springcloudweb.chain.api.ProcessApi;
import com.zhuque.springcloudweb.chain.bean.AsyncCallBackRequest;
import com.zhuque.springcloudweb.chain.bean.NextChainContants;
import com.zhuque.springcloudweb.chain.bean.NextProcessDealData;
import com.zhuque.springcloudweb.chain.bean.SyncRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class ProcessApiImpl implements ProcessApi {

    @Autowired
    private NextProcessServiceFactory factory;


    @Override
    public void syncReq(SyncRequest request) {
        // 获取流程 0,2,8



        // 组装数据 -- 转换成 NextProcessDealData

        // 获取服务
        ProcessService processService = factory.getProcessService("0");

        factory.executeProcess(new NextProcessDealData());

    }

    @Override
    public void asyncCallBack(AsyncCallBackRequest request) {

        // 根据流水信息获取当前流程


        // 组装数据 -- 转换成 NextProcessDealData
        NextProcessDealData nextProcessDealData = new NextProcessDealData();
        // 设置状态为异步回调
        nextProcessDealData.setReqType(NextChainContants.ReqType.ASYNC_REQ);
        // 获取服务
        ProcessService processService = factory.getProcessService("5");

        factory.executeProcess(nextProcessDealData);

    }


    private NextProcessDealData convertNextSynProcessDealData (SyncRequest request) {
        return new NextProcessDealData();
    }
}

3.异步请求入参

package com.zhuque.springcloudweb.chain.bean;


import lombok.Data;

@Data
public class AsyncCallBackRequest {

    private String applyNo;
}


 

4.同步请求入参

package com.zhuque.springcloudweb.chain.bean;

import lombok.Data;

@Data
public class SyncRequest {

    String applyNo;

}

 

4.责任链上线文基类

package com.zhuque.springcloudweb.chain.bean;

import lombok.Data;

import java.io.Serializable;

@Data
public class ChainBean implements Serializable {
    /**
     * 责任链 是否执行
     */
    private Boolean doProcess = true;

    /**
     * 流程编号
     */
    private String processIds;
    /**
     * 请求类型
     */
    private String reqType;
    /**
     * 当前程序执行节点
     */
    private String proocessId;
}

 

5.责任链业务数据类

package com.zhuque.springcloudweb.chain.bean;


import lombok.Data;

@Data
public class NextProcessDealData extends ChainBean {

}

6.链路执行描述枚举类

package com.zhuque.springcloudweb.chain.bean;

/**
 * 责任链描述
 */
public enum ChainDescribeEnum {

    FIRST_PROCESS ("1","流程一"),

    SECOND_PROCESS("2","流程二"),

    THIRD_PROCESS("3","流程三"),
    ;

    private String processId;

    private String describe;

    ChainDescribeEnum(String processId, String describe) {

        this.processId = processId;

        this.describe = describe;

    }

    public static String getDescribe  (String processId) {

        for (ChainDescribeEnum chainEnum: ChainDescribeEnum.values() ) {
            if (chainEnum.processId .equals(processId)) {
                return chainEnum.describe;
            }
        }
        return null;
    }
}

7.字符常量池

package com.zhuque.springcloudweb.chain.bean;

public class NextChainContants {


    public static String FIRST_PROCESS = "1";

    public static String SECOND_PROCESS = "2";

    public static String THIRD_PROCESS = "3";

    public static class ReqType {
        /**
         * 同步请求
         */
        public static final String SYNC_REQ = "0";
        /**
         * 异步请求
         */
        public static final String ASYNC_REQ = "1";
    }

}

8.责任链接口

package com.zhuque.springcloudweb.chain;

import com.zhuque.springcloudweb.chain.bean.NextProcessDealData;


public interface ProcessService {

    /**
     * 执行流程
     * @param processDealData
     * @return
     */
    ProcessService processDeal(NextProcessDealData processDealData);

    /**
     * 获取当前节点编号
     * @return
     */
    String getProcessId();

    /**
     * 获取下一节点编号
     * @return
     */
    String getNextProcessId();
}

9.工厂类:该类包括节点数据收集,链路驱动

package com.zhuque.springcloudweb.chain;

import com.zhuque.springcloudweb.chain.bean.NextProcessDealData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 *InitializingBean接口为bean提供了初始化方法的方式,
 * 它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法
 *
 * ApplicationContextAware: 通过它Spring容器会自动把上下文环境对象调用ApplicationContextAware
 * 接口中的setApplicationContext方法,可以通过这个上下文环境对象得到Spring容器中的Bean
 */
@Slf4j
@Component
public class NextProcessServiceFactory implements InitializingBean, ApplicationContextAware {


    private ApplicationContext applicationContext;

    /**
     * map存储当前流程
     */
    private static Map<String,ProcessService> processServiceMap = new ConcurrentHashMap<>();

    /**
     * 获取流程执行
     * @param processId
     */
    public ProcessService getProcessService(String processId){
        if (StringUtils.isEmpty(processId)) {
            return null;
        }
        ProcessService processService = processServiceMap.get(processId);
        if (processService == null) {
            log.info("无此流程编号 : {}",processId);
            throw new IllegalArgumentException("流程编号服务不存在");
        }
        return processService;
    }

    /**
     * 程序执行器-- 链式驱动
     * @param processDealData
     */
    public void executeProcess (NextProcessDealData processDealData)  {
        log.info ("【责任链流程开始】");
        ProcessService processService = getProcessService(processDealData.getProocessId());
        while(true) {
            if (null == processService) {
                log.info("【责任链流程结束】");
                break;
            }
            processService = processService.processDeal(processDealData);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, ProcessService> map = applicationContext.getBeansOfType(ProcessService.class);
        if (!CollectionUtils.isEmpty(map)) {
            map.forEach((k,v)->{
                processServiceMap.put(v.getProcessId(),v);
            });
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

10.链路节点抽象类:该节点提供统一流水信息处理,统一异常处理等功能

package com.zhuque.springcloudweb.chain;
import com.zhuque.springcloudweb.chain.bean.ChainDescribeEnum;
import com.zhuque.springcloudweb.chain.bean.NextChainContants;
import com.zhuque.springcloudweb.chain.bean.NextProcessDealData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;


@Slf4j
public abstract  class AbstractProcess implements ProcessService {

    @Autowired
    private NextProcessServiceFactory factory;

    @Override
    public ProcessService processDeal (NextProcessDealData processDealData) {
        String nextProcessId = null;
        if (!continued(processDealData.getProcessIds())) {
            return factory.getProcessService(getNextProcessId());
        }
        try {
            log.info("当前执行流程-> {}:{} 【开始】",processDealData.getProcessIds(),ChainDescribeEnum.getDescribe(processDealData.getProcessIds()));
            if (NextChainContants.ReqType.SYNC_REQ.equals(processDealData.getReqType())||StringUtils.isEmpty(processDealData.getReqType())) {
                nextProcessId = doExecute(processDealData);
            } else {
                processDealData.setReqType(null);
                nextProcessId = doAsyExecute(processDealData);
            }
            // 更新流程信息 -- 更新主流水表信息
            successHandler(processDealData);
        } catch(Exception e) {

            // 异常处理
            exceptionHandler(processDealData ,e);
        }
       ProcessService processService = factory.getProcessService(nextProcessId);
        return processService;
    }


    private Boolean continued(String processIds) {
        if (StringUtils.isEmpty(processIds)) {
            return false;
        }
        if (processIds.contains(getProcessId())) {
            return true;
        }
        return false;
    }


    /**
     * 流程成功处理器
     * @param processDealData
     */
    private final void successHandler(NextProcessDealData processDealData){
        log.info("当前执行流程-> {}:{} 【结束】",processDealData.getProcessIds(),ChainDescribeEnum.getDescribe(processDealData.getProcessIds()));
    }

    /**
     * 流程失败处理
     * @param processDealData
     * @param e
     */
    private final void exceptionHandler(NextProcessDealData processDealData, Exception e) {
        log.info("流程 : {},{},异常,异常信息 : {}",processDealData.getProcessIds(),ChainDescribeEnum.getDescribe(processDealData.getProcessIds()),e);
        throw new RuntimeException("流程执行异常");
    }

    /**
     * 同步请求
     * @param processDealData
     * @return
     */
    public abstract String doExecute(NextProcessDealData processDealData);

    /**
     * 异步请求
     * @param processDealData
     * @return
     */
    public abstract String doAsyExecute (NextProcessDealData processDealData);
}

11.同步链式子节点1

package com.zhuque.springcloudweb.chain.impl;

import com.zhuque.springcloudweb.chain.AbstractProcess;
import com.zhuque.springcloudweb.chain.bean.NextChainContants;
import com.zhuque.springcloudweb.chain.bean.NextProcessDealData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class NextFirstProcess extends AbstractProcess {


    @Override
    public String doExecute(NextProcessDealData processDealData) {
        log.info("第一层链式流程。。。同步请求");
        return getNextProcessId();
    }

    @Override
    public String doAsyExecute(NextProcessDealData processDealData) {
        log.info ("第一层链式流程。。。。异步请求");
        return null;
    }

    @Override
    public String getProcessId() {
        return NextChainContants.FIRST_PROCESS;
    }

    @Override
    public String getNextProcessId() {
        return NextChainContants.SECOND_PROCESS;
    }
}

 

12.异步链式字节点

package com.zhuque.springcloudweb.chain.impl;

import com.zhuque.springcloudweb.chain.AbstractProcess;
import com.zhuque.springcloudweb.chain.bean.NextChainContants;
import com.zhuque.springcloudweb.chain.bean.NextProcessDealData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class NextSecondProcess extends AbstractProcess {


    @Override
    public String doExecute(NextProcessDealData processDealData) {
        log.info("方法实现类二,用于异步");
        return null;
    }

    @Override
    public String doAsyExecute(NextProcessDealData processDealData) {
        return null;
    }

    @Override
    public String getProcessId() {
        return NextChainContants.SECOND_PROCESS;
    }

    @Override
    public String getNextProcessId() {
        return NextChainContants.THIRD_PROCESS;
    }
}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值