Activiti7初探

activiti 7.0.0.SR1+springboot 2.0.4.RELEASE

1、 idea中安装activiti的插件

在这里插入图片描述

2、引入依赖

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <activiti.version>7.0.0.SR1</activiti.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatisplus-spring-boot-starter</artifactId>
            <version>1.0.5</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.35</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>${activiti.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.activiti.core.common</groupId>
                    <artifactId>activiti-spring-identity</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

application.properties中增加配置

#表示启动时检查数据库表,不存在则创建
spring.activiti.database-schema-update=true
#表示哪种情况下使用历史表,这里配置为full表示全部记录历史,方便绘制流程图
spring.activiti.history-level=full
#true表示使用历史表,如果不配置,则工程启动后可以检查数据库,只建立了17张表
spring.activiti.db-history-used=true

3、画流程的bpmn图,其实就是设计中的活动图

在这里插入图片描述

4、25张表

在这里插入图片描述

5、核心service

RuntimeService
TaskService
HistoryService
RepositoryService

6、启动流程并自动完成第一步

public String startProcess(ProcessDealDto processDealDto) {

        ProcessInstance instance = runtimeService.startProcessInstanceByKey(WorkFlowConstant.PROCESS_WORKTICKET_ID);
        //验证是否启动成功
        //通过查询正在运行的流程实例来判断
        ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
        //根据流程实例ID来查询
        List<ProcessInstance> runningList = processInstanceQuery.processInstanceId(instance.getProcessInstanceId()).list();
        logger.debug(LogFormatter.toMsg("start process", "instance"), runningList);

        String instanceId = instance.getId();

        //设置处理人
        Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult();
        if (task != null) {
            //自动完成第一步

            Map<String, Object> map = new HashMap<String, Object>(2);
            map.put("check", 1);
            map.put("personId", processDealDto.getPersonId());
            taskService.setAssignee(task.getId(), processDealDto.getCurrentPersonId());
            taskService.complete(task.getId(), map);

            task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult();
            taskService.setAssignee(task.getId(), processDealDto.getPersonId());
        } else {
            throw new BusinessException(WorkTaskErrorCode.WORK_TASK_START_PROCESS_ERROR);
        }

        // 返回流程ID
        return instanceId;
    }

7、节点处理

public void auditProcess(ProcessDealDto processDealDto) {
        Task task = null;
        if (ObjectUtils.isNotEmpty(processDealDto.getInstanceId())) {
            task = taskService.createTaskQuery().processInstanceId(processDealDto.getInstanceId()).singleResult();
        } else if (ObjectUtils.isNotEmpty(processDealDto.getTaskId())) {
            task = taskService.createTaskQuery().taskId(processDealDto.getTaskId()).singleResult();
        }

        if (task == null) {
            throw new BusinessException(WorkTaskErrorCode.WORK_TASK_BACK_PROCESS_EMPTY_ERROR);
        }
        if (WorkFlowConstant.AUDIT_PASS.equals(processDealDto.getCheck())) {
            dealProcess(task, processDealDto);
        } else {
            backProcess(task, processDealDto);
        }
    }

/**
     * 退回到上一节点
     *
     * @param task
     * @param processDealDto
     */
    private void backProcess(Task task, ProcessDealDto processDealDto) {

        List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processDealDto.getInstanceId())
                .orderByTaskCreateTime()
                .desc()
                .list();

        if (ObjectUtils.isEmpty(htiList) || htiList.size() < 2) {
            return;
        }

        HistoricTaskInstance myTask = htiList.get(1);
        String myTaskId = myTask.getId();

        if (null == myTaskId) {
            throw new BusinessException(WorkTaskErrorCode.WORK_TASK_BACK_PROCESS_USER_ERROR);
        }

        String processDefinitionId = myTask.getProcessDefinitionId();
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);

        //变量
//		Map<String, VariableInstance> variables = runtimeService.getVariableInstances(currentTask.getExecutionId());
        String myActivityId = null;
        List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
                .executionId(myTask.getExecutionId()).finished().list();
        for (HistoricActivityInstance hai : haiList) {
            if (myTaskId.equals(hai.getTaskId())) {
                myActivityId = hai.getActivityId();
                break;
            }
        }
        FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);


        Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
        String activityId = execution.getActivityId();
//        logger.warn("------->> activityId:" + activityId);
        FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);

        //记录原活动方向
        List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
        oriSequenceFlows.addAll(flowNode.getOutgoingFlows());

        //清理活动方向
        flowNode.getOutgoingFlows().clear();
        //建立新方向
        List<SequenceFlow> newSequenceFlowList = new ArrayList<SequenceFlow>();
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId");
        newSequenceFlow.setSourceFlowElement(flowNode);
        newSequenceFlow.setTargetFlowElement(myFlowNode);
        newSequenceFlowList.add(newSequenceFlow);
        flowNode.setOutgoingFlows(newSequenceFlowList);

        Map<String, Object> currentVariables = new HashMap<String, Object>();
        currentVariables.put("check", 0);
        currentVariables.put("dealMsg", processDealDto.getDealMsg());
        currentVariables.put("personId", processDealDto.getPersonId());
        taskService.createAttachment("", task.getId(), processDealDto.getInstanceId(), "dealMsg", processDealDto.getDealMsg(), "");
        //完成任务
        taskService.complete(task.getId(), currentVariables);
        //恢复原方向
        flowNode.setOutgoingFlows(oriSequenceFlows);

        Task nextTask = taskService.createTaskQuery().processInstanceId(processDealDto.getInstanceId()).singleResult();
        if(nextTask!=null) {
            taskService.setAssignee(nextTask.getId(), myTask.getAssignee());
        }
    }

    /**
     * 正向流程
     *
     * @param task
     * @param processDealDto
     */
    private void dealProcess(Task task, ProcessDealDto processDealDto) {

        Map<String, Object> map = new HashMap<String, Object>(2);
        map.put("check", processDealDto.getCheck());
        map.put("personId", processDealDto.getPersonId());
        map.put("dealMsg", processDealDto.getDealMsg());

        task.setDescription(WorkFlowStatus.getDescriptionByIndex(processDealDto.getNodeType()));

        String taskId = task.getId();
        taskService.createAttachment("", taskId, processDealDto.getInstanceId(), "dealMsg", processDealDto.getDealMsg(), "");
        taskService.complete(taskId, map);

        //设置处理人,将流程流转到下一个人
        Task nextTask = taskService.createTaskQuery().processInstanceId(processDealDto.getInstanceId()).singleResult();

        if(nextTask!=null) {
            taskService.setAssignee(nextTask.getId(), processDealDto.getPersonId());
        }
    }

8、历史查询

不显示起始节点和排他网关

public List<ProcessHistoryDto> getHistoryByInstance(String instanceId) {

        HistoricActivityInstanceQuery historyInstanceQuery = historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId);
        // 查询历史节点
        List<HistoricActivityInstance> historicActivityInstanceList = historyInstanceQuery.orderByHistoricActivityInstanceStartTime().asc().list();
        if (ObjectUtils.isNotEmpty(historicActivityInstanceList)) {
            List<ProcessHistoryDto> historyDtos = new ArrayList<>();

            Integer lastNodeId = null;

            ProcessHistoryDto lastHistoryNode = null;

            for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
                if(activityInstance.getActivityName().equals("StartEvent") || activityInstance.getActivityName().equals("ExclusiveGateway")){
                    continue;
                }

                ProcessHistoryDto historyDto = new ProcessHistoryDto();
                historyDto.setActivitId(activityInstance.getActivityId());
                historyDto.setDealPersonID(activityInstance.getAssignee());
                historyDto.setDealTime(activityInstance.getEndTime());

                Integer nowNodeId = WorkFlowNodeEnum.getIndexByName(activityInstance.getActivityId());
                historyDto.setNodeId(nowNodeId);
                historyDto.setCheck(true);
                //判断是否为驳回
                if(lastNodeId != null && nowNodeId < lastNodeId){
                    lastHistoryNode.setCheck(false);
                }else if(lastNodeId != null && WorkFlowNodeEnum.WORK_PERMITER_CHECK.getIndex().equals(lastNodeId)
                        && WorkFlowNodeEnum.FINISH.getIndex().equals(nowNodeId)){
                    //从许可人直接驳回
                    lastHistoryNode.setCheck(false);
                }

                if(!"EndEvent".equals(activityInstance.getActivityName())) {
                    List<Attachment> attachmentList = taskService.getTaskAttachments(activityInstance.getTaskId());
                    if (ObjectUtils.isNotEmpty(attachmentList)) {
                        historyDto.setAttachment(attachmentList.get(0).getDescription());
                    }

                    historyDto.setDealPersonName(getPersonNameAndNoById(activityInstance.getAssignee()));
                }

                lastNodeId = nowNodeId;
                lastHistoryNode = historyDto;

                //没有结束时间,表示当前正处于该节点,历史中不展示,但是要用这个节点来判断是否是驳回
                if(ObjectUtils.isEmpty(activityInstance.getEndTime())){
                    continue;
                }

                historyDtos.add(historyDto);
            }
            return historyDtos;
        }
        return null;
    }

9、代办

public List<PersonToDoDto> getToDoList(String personId) {

        List<Task> list = taskService.createTaskQuery().taskCandidateOrAssigned(personId).list();
        if(ObjectUtils.isNotEmpty(list)){
            List<PersonToDoDto> personToDoDtos = new ArrayList<>();
            for(Task task : list){
                PersonToDoDto personToDoDto = new PersonToDoDto();
                personToDoDto.setInstanceId(task.getProcessInstanceId());
                personToDoDto.setTaskId(task.getId());
                personToDoDtos.add(personToDoDto);
            }
            return personToDoDtos;
        }
        return null;
    }

10、重写用户权限

@Service
public class CustomUserGroupManagerImpl implements UserGroupManager{

    public static List<String> roles = new ArrayList<>();
    public static List<String> groups = new ArrayList<>();
    public static List<String> users = new ArrayList<>();
    public static Map<String,String> userRoleMap = new HashMap<>();
    static {
        roles.add("workCreate");
        roles.add("workPermit");
        roles.add("workLeader");

        groups.add("workGroupA");

        users.add("admin");
        users.add("laowang");
        users.add("xiaofang");

        userRoleMap.put("admin", "workCreate");
        userRoleMap.put("laowang", "workPermit");
        userRoleMap.put("xiaofang", "workLeader");
    }

    @Override
    public List<String> getUserGroups(String s) {

        return groups;
    }

    @Override
    public List<String> getUserRoles(String s) {
        String role = userRoleMap.get(s);
        List<String> list = new ArrayList<>();
        list.add(role);
        return list;
    }

    @Override
    public List<String> getGroups() {
        return groups;
    }

    @Override
    public List<String> getUsers() {
        return users;
    }
}

11、关闭activiti默认的安全校验

启动类上添加注解

@EnableAutoConfiguration(exclude = {org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class})
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().permitAll().and().logout().permitAll();
    }
}

12、配置activiti的数据源和线程池

@Configuration
public class WorkFlowConfiguration{

@Autowired
private UserGroupManager userGroupManager;

    @Autowired
    private DataSource dataSource;

    private int corePoolSize = 10;
    private int maxPoolSize = 30;
    private int keepAliveSeconds = 300;
    private int queueCapacity = 300;

    @Bean
    public SpringProcessEngineConfiguration springProcessEngineConfiguration(
            PlatformTransactionManager transactionManager) throws IOException {

        SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration();
        configuration.setDataSource(dataSource);
        configuration.setTransactionManager(transactionManager);
        SpringAsyncExecutor asyncExecutor = new SpringAsyncExecutor();
        asyncExecutor.setTaskExecutor(workFlowAsync());
        configuration.setAsyncExecutor(asyncExecutor);

        configuration.setDatabaseSchemaUpdate("true");
        configuration.setUserGroupManager(userGroupManager);
        configuration.setHistoryLevel(HistoryLevel.FULL);
        configuration.setDbHistoryUsed(true);
        return configuration;
    }

    @Primary
    @Bean("workFlowTaskExecutor")
    public ThreadPoolTaskExecutor workFlowAsync() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setKeepAliveSeconds(keepAliveSeconds);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix("workFlowTaskExecutor-");
        executor.initialize();
        return executor;
    }


}

13、其他问题

有时候发现application.properties中的配置不起作用

@Configuration
public class InitConfigTest implements CommandLineRunner {

    @Autowired
    private ProcessEngine processEngine;

    @Override
    public void run(String... args) throws Exception {
        Deployment deployment = processEngine.getRepositoryService()
                .createDeployment()
                .name("workTask")
                .addClasspathResource("processes/workTask.bpmn")
//                .addClasspathResource("repository/TestProcess.png")
                .deploy();
    }
}
发布了26 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_36142042/article/details/89506547