This article is included in my personal blog: www.chengxy-nds.top, Technical data Sharing, with Progress

Programmer is a brick, where needs to move

The OA system in the company has to be upgraded recently, so I was seconded there due to lack of staff. But to be honest, I have never done this function before. It is my first time to contact the development of workflow, and I am still a little curious about what kind of process it is.

The project mainly used Springboot + Flowable to reconstruct the original workflow. Flowable is a lightweight workflow engine written in Java language, which is relatively easy to use and high development efficiency. Let’s learn this framework together.

Official address: https://www.flowable.org/docs/userguide/index.html, sharing is just simple application, further research must also look at the official documentation.

Flowable core dependencies

<! -- Flowable workflow dependencies --><dependency>
	<groupId>org.flowable</groupId>
	<artifactId>flowable-spring-boot-starter</artifactId>
	<version>6.3.0</version>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>1.3.2</version>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<scope>runtime</scope>
</dependency>
Copy the code

Process design

The core of workflow development is the design of the task flow. Flowable officially recommends using the industry standard BPMN2.0 XML to describe the workflow to be defined.

We need to create a PROCESSES path under the Resource directory to hold the relevant XML process configuration files. By default, the Flowable framework loads the workflow files in this directory and parses the XML, persisting the parsed process configuration information to the database.

Flowable is database dependent, but it does not require manual table creation. Instead, it automatically creates a series of tables into MySQL when the program is first started.

spring:
  datasource:
    url: jdbc:mysql:/ / 47.93.6.5:3306 / order? serverTimezone=UTC
    username: root
    password: 123455
Copy the code

It was found that 60 tables were generated after the project was successfully started, which is quite large. It is suggested to use a special database to store these workflow tables.

For example: if a leave process, the manager needs to approve, leave can be effective, if he rejected the end of the process.

Next we use XML to translate the above leave flow chart, the whole is very simple as long as you are careful enough, let’s see what each label means.

<? xml version="1.0" encoding="UTF-8"? > <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
             xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
             typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath"
             targetNamespace="http://www.flowable.org/processdef">
    <process id="Leave" name="LeaveProcess" isExecutable="true">
        <userTask id="leaveTask" name="Leave" flowable:assignee="${leaveTask}"/>
        <userTask id="managerTask" name="Manager Review"/>
        <exclusiveGateway id="managerJudgeTask"/>
        <endEvent id="endLeave" name="The end"/>
        <startEvent id="startLeave" name="Start"/>
        <sequenceFlow id="modeFlow" sourceRef="leaveTask" targetRef="managerTask"/>
        <sequenceFlow id="flowStart" sourceRef="startLeave" targetRef="leaveTask"/>
        <sequenceFlow id="jugdeFlow" sourceRef="managerTask" targetRef="managerJudgeTask"/>
        <endEvent id="endLeave2"/>
        <sequenceFlow id="flowEnd" name="通过" sourceRef="managerJudgeTask" targetRef="endLeave">
            <conditionExpression xsi:type="tFormalExpression"> <! [CDATA[${checkResult=='through'}]]>
            </conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="rejectFlow" name="Rejected" sourceRef="managerJudgeTask"
                      targetRef="endLeave2">
            <conditionExpression xsi:type="tFormalExpression"> <! [CDATA[${checkResult=='rejected'}]]>
            </conditionExpression>
        </sequenceFlow>
    </process>
    <bpmndi:BPMNDiagram id="BPMNDiagram_process">
        <bpmndi:BPMNPlane bpmnElement="Leave" id="BPMNPlane_process">
            <bpmndi:BPMNShape bpmnElement="leaveTask" id="BPMNShape_leaveTask">
                <omgdc:Bounds height="79.99999999999999" width="100.0" x="304.60807973558974" y="122.00000000000001"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="managerTask" id="BPMNShape_managerTask">
                <omgdc:Bounds height="80.0" width="100.0" x="465.0" y="122.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="managerJudgeTask" id="BPMNShape_managerJudgeTask">
                <omgdc:Bounds height="40.0" width="40.0" x="611.5" y="142.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="endLeave" id="BPMNShape_endLeave">
                <omgdc:Bounds height="28.0" width="28.0" x="696.5" y="148.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="startLeave" id="BPMNShape_startLeave">
                <omgdc:Bounds height="30.0" width="30.0" x="213.2256558149128" y="147.0"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="endLeave2"
                              id="BPMNShape_endLeave2">
                <omgdc:Bounds height="28.0" width="28.0" x="617.5" y="73.32098285753572"/>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge bpmnElement="flowEnd" id="BPMNEdge_flowEnd">
                <omgdi:waypoint x="651.1217948717949" y="162.37820512820514"/>
                <omgdi:waypoint x="696.5002839785394" y="162.0891701657418"/>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="rejectFlow" id="BPMNEdge_rejectFlow">
                <omgdi:waypoint x="631.866093577786" y="142.36609357778607" />
                <omgdi:waypoint x="631.5931090276993" y="101.32067323657485" />
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="modeFlow" id="BPMNEdge_modeFlow">
                <omgdi:waypoint x="404.60807973558974" y="162.0" />
                <omgdi:waypoint x="465.0" y="162.0" />
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="flowStart" id="BPMNEdge_flowStart">
                <omgdi:waypoint x="243.2256558149128" y="162.0" />
                <omgdi:waypoint x="304.60807973558974" y="162.0" />
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="jugdeFlow" id="BPMNEdge_jugdeFlow">
                <omgdi:waypoint x="565.0" y="162.21367521367523" />
                <omgdi:waypoint x="611.9141630901288" y="162.41416309012877" />
            </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
    </bpmndi:BPMNDiagram>
</definitions>
Copy the code

Basically, the line logic of the flowchart is drawn with different XML tags.

: represents a complete workflow


: Description of workflow


: the starting point (start) in the workflow


: End position in workflow (end)


: Represents a task audit node (group leader, manager, etc.)


: logical judgment node. It is equivalent to the diamond box in the flowchart


: A line that links nodes. The sourceRef attribute indicates the starting node of the line, and the targetRef attribute indicates the node to which the line points.

This big lump up hereXMLDoesn’t it look super cumbersome? If only there was an automatic generation tool, I foundIDEAIt comes with design tools, but it’s too hard to use.

As a programmer for baidu programming, not other’s ability to get to the Internet to find the answer or can be, since I feel trouble writing XML, so want to official must also think about, perhaps have a ready-made tools, shopping for a circle’s official website https://www.flowable.org/downloads.html, I actually found it.

Github download: github.com/flowable/fl… .

Then I found an online editing tool:www.learun.cn:8090/home_online…

The process of examination and approval

After the process design, the rest is to approve the workflow and generate flow charts.

The XML file will receive the variable leaveTask. Flowable will carry out database persistence internally and return a processId processId, which can be used to query the overall situation of workflow. Task Id Task Indicates the specific leave task of an employee.

Note: A leave process processId can contain multiple leave tasks taskId.

/ * * *@author xiaofu
     * @description Startup process@date 2020/8/26 slew both * /
    @RequestMapping(value = "startLeaveProcess")
    @ResponseBody
    public String startLeaveProcess(String staffId) {
        HashMap<String.Object> map = new HashMap<>();
        map.put("leaveTask", staffId);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("Leave", map);
        StringBuilder sb = new StringBuilder();
        sb.append("Create leave process processId:" + processInstance.getId());
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(staffId).orderByTaskCreateTime().desc().list();
        for (Task task : tasks) {
            sb.append("TaskId task." + task.getId());
        }
        return sb.toString();
    }
Copy the code

Take a look at the current flowchart using the processId returned when the process is started

http://localhost:4000/leave/createProcessDiagramPic? processId=37513
Copy the code

Next, reject the leave application, pass in the corresponding taskId and execute the reject, and then see the effect of the whole workflow.

http://localhost:4000/leave/rejectTask? taskId=10086
Copy the code
 / * * *@param taskId
     * @author xinzhifu
     * @description Rejected *@date 2020/8/27 comes * /
    @ResponseBody
    @RequestMapping(value = "rejectTask")
    public String rejectTask(String taskId) {
        HashMap<String.Object> map = new HashMap<>();
        map.put("checkResult"."Rejected");
        taskService.complete(taskId, map);
        return "Application rejected ~";
    }
Copy the code

See the whole leave process in the manager review this successfully blocked.

http://localhost:4000/leave/createProcessDiagramPic? processId=37513
Copy the code

conclusion

Workflow development is generally used in traditional projects such as OA system. It is the first time for me to try to do such functions, and I have gained a lot. Another knowledge point has been added to the technology stack. Today’s share is a super simple demo, because it is just the beginning of contact, and when I use the thief, I will do more mature and in-depth sharing for my friends.

The demo making address: https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-work-flowable


Original is not easy, burning hair output content, if there is a lost harvest, a praise to encourage it!

I sorted out hundreds of technical e-books and gave them to my friends. Pay attention to the public number reply [666] to get yourself. I set up a technology exchange group with some friends to discuss technology and share technical information, aiming to learn and progress together. If you are interested, please join us!