美文网首页java面试总结
SpringBoot+Activiti 创建自定义业务审批框架

SpringBoot+Activiti 创建自定义业务审批框架

作者: 东方不喵 | 来源:发表于2019-01-28 19:50 被阅读257次

    流程开发主要分成两部分:

    1. 通用的流程操作(基于Activiti 本身)。
    2. 独立的业务开发。
      而在业务开发中,会伴随着很多与Activiti的代码耦合,会出现大量的同等功能的业务代码,但是由于操作的业务对象不同,又需要写很多冗余的CRUD操作。这样增加了大量低质量的耦合代码。
      为了减少业务代码中的通用性操作代码,可以编写一套自定义的业务代码审批框架。
      项目代码:
      GitHub https://github.com/oldguys/ActivitiDemo
    结构类图:
    框架设计图 .jpg
    设计思路:
    1. 基于设计模式规则: 依赖倒置原则 , 里氏代换原则,将通用的接口方法进行抽象,完成高层接口:WorkEntityMapperProcessInstanceService 设计。
    2. 使用类似于 抽象工厂模式桥梁模式,对系统进行 解耦多态
      CommonWorkEntityService:进行通用的服务调度,像桥梁一样来适配调度多个ProcessInstanceService
      ProcessInstanceService由基于不同业务对象进行实现,通过不同实例,再关联到DAO层的不同业务对象上。
    3. CommonWorkEntityService 继承于 AbstractWorkEntityService,通过调用 init 方法来通用注入业务对象,而实现类则成为统一调度入口。
    调度方式:

    TaskController 调用 CommonWorkEntityService的getWorkEntityInfo(),最终可以分别获取到Entity1ProcessEntity实体或Entity2ProcessEntity实体

    调用图.jpg
    关联与对象注入:

    由于基于SpringBoot,自然要利用Spring的容器进行管理。
    Step1: 由于服务对象实现于接口 ProcessInstanceService,可以去Spring容器中,获取所有实现于该接口的对象。
    Step2: 利用泛型来获取:
    Entity1ProcessInstanceService 继承于 AbstractProcessInstanceService<T> 实现于 ProcessInstanceService<T>
    获取实现类上的泛型,就可以知道业务实体为 Entity1Process,利用Map将对象与业务类别进行关联标识。同理可使用于 DAO层。

    @Service
    public class Entity1ProcessInstanceService extends AbstractProcessInstanceService<Entity1Process> {
    
    }
    

    Step3: 注入对象,依赖倒置中,注入方法有:设值注入,构造注入,接口注入。这里使用设值注入来实现,关联 ProcessInstanceServiceDAOMapper

    Step4: 巧用多态,根据 **里氏代换原则 **,基类可以调用子类,而我们扩展业务对象,一般都采用继承来实现DTO对象,就可以实现不同的子类对象来满足数据的多态。

    @Service
    public class Entity1ProcessInstanceService extends AbstractProcessInstanceService<Entity1Process> {
        @Override
        public Entity1Process getTarget(Long id) {
            // Entity1ProcessInfo 继承于 Entity1Process 
            return new Entity1ProcessInfo();
        }
    }
    
    package com.oldguy.example.modules.workflow.service;
    
    
    import com.oldguy.example.modules.common.dao.jpas.WorkEntityMapper;
    import com.oldguy.example.modules.common.exceptions.FormValidException;
    import com.oldguy.example.modules.common.utils.SpringContextUtils;
    import com.oldguy.example.modules.workflow.configs.WorkFlowConfiguration;
    import com.oldguy.example.modules.workflow.dto.TaskEntityInfo;
    import com.oldguy.example.modules.workflow.dto.WorkBtn;
    import com.oldguy.example.modules.workflow.dto.WorkEntityInfo;
    import com.oldguy.example.modules.workflow.service.entities.ProcessAuditStatusService;
    import com.oldguy.example.modules.workflow.service.entities.ProcessTaskConfigService;
    import org.activiti.bpmn.model.SequenceFlow;
    import org.activiti.engine.RuntimeService;
    import org.apache.commons.lang3.ClassUtils;
    
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.util.*;
    
    /**
     * @author ren
     * @date 2018/12/6
     */
    public abstract class AbstractWorkEntityService {
    
        /**
         * 工作流实体集合
         */
        protected Map<String, ProcessInstanceService> processInstanceServiceMap = Collections.emptyMap();
    
        /**
         * DAO Mapper
         */
        protected Map<String, WorkEntityMapper> workEntityMapperMap = Collections.emptyMap();
    
        protected UserTaskService userTaskService;
    
        protected ProcessService processService;
    
        protected RuntimeService runtimeService;
    
        protected ProcessTaskConfigService processTaskConfigService;
    
        protected ProcessAuditStatusService processAuditStatusService;
    
        /**
         * 获取抽象类型的泛型类
         *
         * @param object
         * @return
         */
        public static Class getActualTypeArgumentByClassAbstractClass(Object object) {
            Class typeClass = (Class) ((ParameterizedType) object.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
            return typeClass;
        }
    
        /**
         * 获取接口的泛型类型
         *
         * @param object
         * @return
         */
        public static Class getActualTypeArgumentByClassInterface(Object object) {
    
            Type[] types = object.getClass().getGenericInterfaces();
            ParameterizedType parameterizedType = (ParameterizedType) types[0];
            Class typeClass = (Class) parameterizedType.getActualTypeArguments()[0];
            return typeClass;
        }
    
        /**
         * 获取Mapper接口上的实现泛型
         *
         * @param object
         * @return
         */
        public static Class getActualTypeArgumentByInterface(Object object) {
    
            List<Class<?>> list = ClassUtils.getAllInterfaces(object.getClass());
    
            Class clazz = list.get(0);
            Type[] types = clazz.getGenericInterfaces();
            Class typeClass = (Class) ((ParameterizedType) types[0]).getActualTypeArguments()[0];
    
            return typeClass;
        }
    
        protected void init() {
            if (null == userTaskService) {
                userTaskService = SpringContextUtils.getBean(UserTaskService.class);
            }
            if (null == processService) {
                processService = SpringContextUtils.getBean(ProcessService.class);
            }
            if (null == runtimeService) {
                runtimeService = SpringContextUtils.getBean(RuntimeService.class);
            }
            if (null == processTaskConfigService) {
                processTaskConfigService = SpringContextUtils.getBean(ProcessTaskConfigService.class);
            }
            if (null == processAuditStatusService) {
                processAuditStatusService = SpringContextUtils.getBean(ProcessAuditStatusService.class);
            }
    
            // 注入DAO Mapper
            if (workEntityMapperMap.isEmpty()) {
                String[] baseEntityMapperNames = SpringContextUtils.getBeanNamesForType(WorkEntityMapper.class);
                workEntityMapperMap = new HashMap<>(baseEntityMapperNames.length);
    
                for (String name : baseEntityMapperNames) {
                    WorkEntityMapper workEntityMapper = SpringContextUtils.getBean(name, WorkEntityMapper.class);
    
                    // 获取返修类
                    Class typeClass = getActualTypeArgumentByInterface(workEntityMapper);
                    workEntityMapperMap.put(typeClass.getSimpleName(), workEntityMapper);
                }
            }
    
            // 注入ProcessInstanceService
            if (processInstanceServiceMap.isEmpty()) {
                String[] workflowNames = SpringContextUtils.getBeanNamesForType(ProcessInstanceService.class);
                processInstanceServiceMap = new HashMap<>(workflowNames.length);
    
                for (String name : workflowNames) {
                    AbstractProcessInstanceService workFlow = SpringContextUtils.getBean(name, AbstractProcessInstanceService.class);
    
                    // 获取返修类
                    Class typeClass = getActualTypeArgumentByClassAbstractClass(workFlow);
    
                    // 注入类别名称
                    workFlow.setClassName(typeClass.getSimpleName());
                    workFlow.setWorkEntityMapper(workEntityMapperMap.get(typeClass.getSimpleName()));
                    workFlow.setProcessTaskConfigService(processTaskConfigService);
                    workFlow.setProcessAuditStatusService(processAuditStatusService);
    
                    processInstanceServiceMap.put(typeClass.getSimpleName(), workFlow);
                }
            }
        }
    }
    
    

    相关文章

      网友评论

        本文标题:SpringBoot+Activiti 创建自定义业务审批框架

        本文链接:https://www.haomeiwen.com/subject/lihzjqtx.html