Spring boot activiti6.0 动态流程

自定义流程,通过BpmnModel对象动态生成流程并在act_ge_bytearray中生成对应的流程图,CustomProcess为自定义类封装了流程名称和流程usertask,一下代码默认添加的都是usertask任务。


import com.gosun.sacw.activiti.model.CustomProcess;
import com.gosun.sacw.activiti.model.CustomProcessNode;
import com.gosun.sacw.sacw.uitl.BHUtil;
import org.activiti.bpmn.model.*;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.validation.ProcessValidator;
import org.activiti.validation.ProcessValidatorFactory;
import org.activiti.validation.ValidationError;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component("processDeployBuilder")
public class ProcessDeployBuilder {

    public static final String STARTEVENT = "startEvent";
    public static final String ENDEVENT = "endEvent";
//  public static final String PARALLELGATEWAY = "parallelGateway";
//  public static final String USERTASK = "userTask";
//  public static final String SEQUENCEFLOW = "sequenceFlow";
//  public static final String SERVICETASK = "serviceTask";
//  public static final String EXCLUSIVEGATEWAY = "exclusiveGateway";

    public static final double STARTEVENT_X = 50D;
    public static final double STARTEVENT_Y = 75D;
    public static final double STARTEVENT_HEIGHT = 30D;
    public static final double STARTEVENT_WIDTH = 30D;
    public static final double USERTASK_Y = 40D;
    public static final double USERTASK_HEIGHT = 100D;
    public static final double USERTASK_WIDTH = 80D;
    public static final double EVENT_OFFSET = 100D;//偏移量

    @Autowired
    private RepositoryService repositoryService;

    public String deployProcess(CustomProcess customProcess) throws Exception {
        BpmnModel bpmnModel = new BpmnModel();
        String processId = "proc_" + BHUtil.uuid();
        org.activiti.bpmn.model.Process bpmnProcess = new org.activiti.bpmn.model.Process();
        bpmnProcess.setId(processId);
        bpmnProcess.setName(customProcess.getName());
        //开始事件
        StartEvent startEvent = generateStartEvent(bpmnModel);
        bpmnProcess.addFlowElement(startEvent);

        String preEventId = startEvent.getId();
        List<CustomProcessNode> customProcessNodes = customProcess.getNodes();
        int userTaskNum = customProcessNodes.size();
        for (int i = 0; i < userTaskNum; i++) {
            CustomProcessNode customProcessNode = customProcessNodes.get(i);
            UserTask userTask = generateUserTask(bpmnModel, customProcessNode, i + 1);
            bpmnProcess.addFlowElement(userTask);
            SequenceFlow sequenceFlow = generateSequenceFlow(bpmnModel, preEventId, userTask.getId(), i + 1);
            bpmnProcess.addFlowElement(sequenceFlow);
            preEventId = userTask.getId();
        }

        EndEvent endEvent = generateEndEvent(bpmnModel, userTaskNum + 1);
        bpmnProcess.addFlowElement(endEvent);
        SequenceFlow sequenceFlow = generateSequenceFlow(bpmnModel, preEventId, endEvent.getId(), userTaskNum + 1);
        bpmnProcess.addFlowElement(sequenceFlow);
        bpmnModel.addProcess(bpmnProcess);
        //校验流程
        ProcessValidatorFactory processValidatorFactory = new ProcessValidatorFactory();
        ProcessValidator defaultProcessValidator = processValidatorFactory.createDefaultProcessValidator();
        List<ValidationError> validate = defaultProcessValidator.validate(bpmnModel);
        //流程校验失败
        if (validate.size() > 0) {
            throw new RuntimeException("流程部署异常,异常信息:" + validate);
        }
        //部署流程
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
        deploymentBuilder.key(processId).name("请假审批流程");
        deploymentBuilder.addBpmnModel(processId + ".bpmn20.xml", bpmnModel);
        deploymentBuilder.deploy();

        return processId;
    }

    //开始节点
    public StartEvent generateStartEvent(BpmnModel bpmnModel) {
        StartEvent startEvent = new StartEvent();
        startEvent.setId(STARTEVENT);
        startEvent.setName("流程申请");
        GraphicInfo graphicInfo = generateGraphicInfo(STARTEVENT_X, STARTEVENT_Y, STARTEVENT_WIDTH, STARTEVENT_HEIGHT);
        bpmnModel.addGraphicInfo(STARTEVENT, graphicInfo);
        return startEvent;
    }

    //用户任务,根据提交的名称和角色信息生成
    public UserTask generateUserTask(BpmnModel bpmnModel, CustomProcessNode customProcessNode, int index) {
        String taskId = "task_" + BHUtil.uuid();
        UserTask userTask = new UserTask();
        userTask.setId(taskId);
        userTask.setName(customProcessNode.getName());
        //设置当前任务审批角色
        userTask.setCandidateGroups(customProcessNode.getAssignment());
        GraphicInfo graphicInfo = generateGraphicInfo(generateEventOffset(index), USERTASK_Y, USERTASK_WIDTH, USERTASK_HEIGHT);
        bpmnModel.addGraphicInfo(taskId, graphicInfo);
        return userTask;
    }

    //结束节点 默认 空结束事件,即最后一个任务审批完毕后流程实例自动结束
    public EndEvent generateEndEvent(BpmnModel bpmnModel, int eventNum) {
        EndEvent endEvent = new EndEvent();
        endEvent.setId(ENDEVENT);
        endEvent.setName("流程结束");
        GraphicInfo graphicInfo = generateGraphicInfo(generateEventOffset(eventNum), STARTEVENT_Y, STARTEVENT_WIDTH, STARTEVENT_HEIGHT);
        bpmnModel.addGraphicInfo(ENDEVENT, graphicInfo);
        return endEvent;
    }

    //节点连接线
    public SequenceFlow generateSequenceFlow(BpmnModel bpmnModel, String sourceRef, String targetRef, int index) {
        //节点连接线开始位置:开始节点的起始位置 + 开始节点的宽度 + (节点偏移量(连接线长度) + 用户任务宽度) * (当前用户任务下标 - 1)
        Double startIndex = STARTEVENT_X + STARTEVENT_WIDTH + (EVENT_OFFSET + USERTASK_WIDTH) * (index - 1);
        String flowId = "flow" + BHUtil.uuid();
        SequenceFlow sequenceFlow = new SequenceFlow();
        sequenceFlow.setId(flowId);
        sequenceFlow.setSourceRef(sourceRef);
        sequenceFlow.setTargetRef(targetRef);
        //流程图信息
        GraphicInfo graphicInfo1 = generateGraphicInfo(startIndex, 50L, 30L, 30L);
        GraphicInfo graphicInfo2 = generateGraphicInfo(startIndex + EVENT_OFFSET, 50L, 30L, 30L);
        List<GraphicInfo> graphicInfoList = new ArrayList<>();
        graphicInfoList.add(graphicInfo1);
        graphicInfoList.add(graphicInfo2);
        bpmnModel.addFlowGraphicInfoList(flowId, graphicInfoList);
        return sequenceFlow;
    }

    //生成流程图位置信息
    public GraphicInfo generateGraphicInfo(double x, double y, double width, double height) {
        GraphicInfo graphicInfo = new GraphicInfo();
        graphicInfo.setX(x);
        graphicInfo.setY(y);
        graphicInfo.setWidth(width);
        graphicInfo.setHeight(height);
        return graphicInfo;
    }

    //获取节点x轴起始位置
    public Double generateEventOffset(int index) {
        //开始节点的起始位置 + 开始节点的宽度 + (节点偏移量(连接线长度)*当前用户任务下标 + 用户任务宽度*(当前用户任务下标 - 1)
        return STARTEVENT_X + STARTEVENT_WIDTH + EVENT_OFFSET * index + USERTASK_WIDTH * (index - 1);
    }

}

生成的流程图出现中文乱码,网上查找原因需要配置SpringProcessEngineConfiguration,但都是以xml配置,不适合spring boot项目,调试源码,发现生成spring boot 自动配置SpringProcessEngineConfiguration对象时调用AbstractProcessEngineAutoConfiguration.baseSpringProcessEngineConfiguration(…),改方法会注入ProcessEngineConfigurationConfigurer对象,并执行配置

if (this.processEngineConfigurationConfigurer != null) {
            this.processEngineConfigurationConfigurer.configure(conf);
        }

由此自定义ProcessEngineConfigurationConfigurer子类,设置字体并注入spring容器

import org.activiti.spring.SpringProcessEngineConfiguration;
import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
import org.springframework.stereotype.Component;

/**
 * AbstractProcessEngineAutoConfiguration.baseSpringProcessEngineConfiguration
 *  构建流程引擎配置信息时会注入ProcessEngineConfigurationConfigurer子类,通过此处自定义配置信息
 */

@Component("customProcessEngineConfigurationConfigurer")
public class CustomProcessEngineConfigurationConfigurer implements ProcessEngineConfigurationConfigurer {
    private static final String FONT_NAME = "宋体";

    @Override
    public void configure(SpringProcessEngineConfiguration springProcessEngineConfiguration) {
        springProcessEngineConfiguration.setActivityFontName(FONT_NAME);
        springProcessEngineConfiguration.setLabelFontName(FONT_NAME);
        springProcessEngineConfiguration.setAnnotationFontName(FONT_NAME);
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值