转载

Spring Boot + Activiti示例 - Websparrow

在本教程中,我们将演示Spring Boot + Activiti示例。Activiti是一个开源工作流引擎,可以执行 BPMN 2.0中 描述的业务流程。Activiti引擎的核心目标是采用由人工任务和服务调用组成的流程定义,并按特定顺序执行。

在这里,我们将设计一个 BMPN工作流程图 和Spring Boot应用程序,它有助于管理流程,如下所示:

Spring Boot + Activiti示例 - Websparrow

然后我们将使用Spring JPA创建员工列表并将其详细信息存储到数据库中,并通过调用Activiti API将任务分配给员工。员工将完成第一项任务和第二项任务。

技术列表:

  1. Spring Tool Suite 3
  2. JDK 8
  3. Spring Boot 1.5.3.RELEASE
  4. Activiti 5.22.0
  5. H2(内存中)数据库
  6. Spring JPA

使用Spring Boot + Activiti工作流流程引擎需要以下依赖项。将以下内容添加到您的pom.xml中。

<properties>
    <java.version>1.8</java.version>
    <activiti.version>5.22.0</activiti.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-spring-boot-starter-basic</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-spring-boot-starter-jpa</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
</dependencies>

BPMN流程定义

将BPMN 2.0流程定义放入src / main / resources / processes文件夹中。此处放置的所有进程将自动部署(即解析并使其可执行)到Activiti引擎。流程定义文件扩展名可以是bpmn20.xml或bpmn,如simple-process.bpmn20.xml或simple-process.bpmn。(这是由Activiti可视化界面生成的xml文件)

<?xml version=<font>"1.0"</font><font> encoding=</font><font>"UTF-8"</font><font>?>
<definitions xmlns=</font><font>"http://www.omg.org/spec/BPMN/20100524/MODEL"</font><font> xmlns:xsi=</font><font>"http://www.w3.org/2001/XMLSchema-instance"</font><font> xmlns:xsd=</font><font>"http://www.w3.org/2001/XMLSchema"</font><font> xmlns:activiti=</font><font>"http://activiti.org/bpmn"</font><font> xmlns:bpmndi=</font><font>"http://www.omg.org/spec/BPMN/20100524/DI"</font><font> xmlns:omgdc=</font><font>"http://www.omg.org/spec/DD/20100524/DC"</font><font> xmlns:omgdi=</font><font>"http://www.omg.org/spec/DD/20100524/DI"</font><font> typeLanguage=</font><font>"http://www.w3.org/2001/XMLSchema"</font><font> expressionLanguage=</font><font>"http://www.w3.org/1999/XPath"</font><font> targetNamespace=</font><font>"Examples"</font><font>>
  <process id=</font><font>"simple-process"</font><font> name=</font><font>"Simple Process"</font><font> isExecutable=</font><font>"true"</font><font>>
    <startEvent id=</font><font>"start"</font><font> name=</font><font>"Start"</font><font>></startEvent>
    <userTask id=</font><font>"userTask1"</font><font> name=</font><font>"User Task 1"</font><font> activiti:assignee=</font><font>"${employee.name}"</font><font>>
      <documentation>Complete user task 1 first.</documentation>
    </userTask>
    <userTask id=</font><font>"userTask2"</font><font> name=</font><font>"User Task 2"</font><font> activiti:assignee=</font><font>"${employee.name}"</font><font>>
      <documentation>Work <b>for</b> the second task.</documentation>
    </userTask>
    <endEvent id=</font><font>"theEnd"</font><font>></endEvent>
    <sequenceFlow id=</font><font>"flow1"</font><font> sourceRef=</font><font>"userTask2"</font><font> targetRef=</font><font>"theEnd"</font><font>></sequenceFlow>
    <sequenceFlow id=</font><font>"flow3"</font><font> sourceRef=</font><font>"userTask1"</font><font> targetRef=</font><font>"userTask2"</font><font>></sequenceFlow>
    <sequenceFlow id=</font><font>"flow4"</font><font> sourceRef=</font><font>"start"</font><font> targetRef=</font><font>"userTask1"</font><font>></sequenceFlow>
  </process>
</definitions>
</font>

activiti:assignee属性 ${employee.name}是被分配到任务的雇员。

模型和存储库类

创建Employee数据模型类。

@Entity
<b>public</b> <b>class</b> Employee {

    @Id
    @GeneratedValue
    <b>private</b> Long id;
    <b>private</b> String name;
    <b>private</b> String designation;
<font><i>// generate getters and setters...</i></font><font>

    <b>public</b> Employee() {
    }

    <b>public</b> Employee(String name, String designation) {

        <b>this</b>.name = name;
        <b>this</b>.designation = designation;
    }
}
</font>

创建EmployeeRepository实现接口JpaRepository<T, ID>的findByName(String name )Employee方法,实现从数据库查询的雇员。

<b>public</b> <b>interface</b> EmployeeRepository <b>extends</b> JpaRepository<Employee, Long> {

    <b>public</b> Employee findByName(String name);

}

服务类

EmployeeService班负责员工加入到数据库中。应用程序启动时将调用此服务类。

@Service
<b>public</b> <b>class</b> EmployeeService {

    @Autowired
    <b>private</b> EmployeeRepository employeeRepository;

    <font><i>// create the list of Employees into the database who perform the task</i></font><font>
    <b>public</b> <b>void</b> createEmployee() {

        <b>if</b> (employeeRepository.findAll().size() == 0) {

            employeeRepository.save(<b>new</b> Employee(</font><font>"Prince"</font><font>, </font><font>"Software Enginner"</font><font>));
            employeeRepository.save(<b>new</b> Employee(</font><font>"Gaurav"</font><font>, </font><font>"Technical Lead"</font><font>));
            employeeRepository.save(<b>new</b> Employee(</font><font>"Abhinav"</font><font>, </font><font>"Test Lead"</font><font>));
        }
    }
}
</font>

而ProcessService类是负责启动的过程中,给员工分配任务,检索分配给员工的任务,并通过ID完成特定的任务。

@Service
<b>public</b> <b>class</b> ProcessService {

    @Autowired
    <b>private</b> EmployeeRepository employeeRepository;

    @Autowired
    <b>private</b> RuntimeService runtimeService;

    @Autowired
    <b>private</b> TaskService taskService;

    @Autowired
    <b>private</b> RepositoryService repositoryService;

    <font><i>// start the process and set employee as variable</i></font><font>
    <b>public</b> String startTheProcess(String assignee) {

        Employee employee = employeeRepository.findByName(assignee);

        Map<String, Object> variables = <b>new</b> HashMap<>();
        variables.put(</font><font>"employee"</font><font>, employee);

        runtimeService.startProcessInstanceByKey(</font><font>"simple-process"</font><font>, variables);

        <b>return</b> processInformation();
    }

    </font><font><i>// fetching process and task information</i></font><font>
    <b>public</b> String processInformation() {

        List<Task> taskList = taskService.createTaskQuery().orderByTaskCreateTime().asc().list();

        StringBuilder processAndTaskInfo = <b>new</b> StringBuilder();
        
        processAndTaskInfo.append(</font><font>"Number of process definition available: "</font><font>
                + repositoryService.createProcessDefinitionQuery().count() + </font><font>" | Task Details= "</font><font>);

        taskList.forEach(task -> {

            processAndTaskInfo.append(</font><font>"ID: "</font><font> + task.getId() + </font><font>", Name: "</font><font> + task.getName() + </font><font>", Assignee: "</font><font>
                    + task.getAssignee() + </font><font>", Description: "</font><font> + task.getDescription());
        });

        <b>return</b> processAndTaskInfo.toString();
    }

    </font><font><i>// fetch task assigned to employee</i></font><font>
    <b>public</b> List<Task> getTasks(String assignee) {
        <b>return</b> taskService.createTaskQuery().taskAssignee(assignee).list();
    }

    </font><font><i>// complete the task</i></font><font>
    <b>public</b> <b>void</b> completeTask(String taskId) {
        taskService.complete(taskId);
    }
}
</font>

控制器类

ProcessController类处理HTTP请求,调用相应的ProcessService类的方法,和响应的具体结果。

@RestController
<b>public</b> <b>class</b> ProcessController {

    @Autowired
    <b>private</b> ProcessService processService;

    <font><i>/*
     * Method will start the Activiti process engine and set employee to perform
     * the task
     */</i></font><font>
    @RequestMapping(value = </font><font>"/process"</font><font>)
    <b>public</b> String startProcessInstance(@RequestParam String assignee) {
        <b>return</b> processService.startTheProcess(assignee);
    }

    </font><font><i>// Retrieve the tasks assigned to an employee</i></font><font>
    @RequestMapping(value = </font><font>"/tasks"</font><font>)
    <b>public</b> String getTasks(@RequestParam String assignee) {
        List<Task> tasks = processService.getTasks(assignee);
        <b>return</b> tasks.toString();
    }

    </font><font><i>// Complete the task by their ID</i></font><font>
    @RequestMapping(value = </font><font>"/completetask"</font><font>)
    <b>public</b> String completeTask(@RequestParam String taskId) {
        processService.completeTask(taskId);
        <b>return</b> </font><font>"Task with id "</font><font> + taskId + </font><font>" has been completed!"</font><font>;
    }
}
</font>

运行应用程序

最后,创建一个App类,该类调用在启动应用程序时创建员工EmployeeSerice的createEmployee()方法。

@SpringBootApplication
<b>public</b> <b>class</b> App {

    <b>public</b> <b>static</b> <b>void</b> main(String[] args) {
        SpringApplication.run(App.<b>class</b>, args);
    }

    @Bean
    <b>public</b> CommandLineRunner init(<b>final</b> EmployeeService employeeService) {

        <b>return</b> <b>new</b> CommandLineRunner() {
            <b>public</b> <b>void</b> run(String... strings) throws Exception {
                employeeService.createEmployee();
            }
        };
    }
}

要使用用户标识和密码保护您的应用程序,请在App类中添加以下代码。

@Bean
InitializingBean usersAndGroupsInitializer(<b>final</b> IdentityService identityService) {

    <b>return</b> <b>new</b> InitializingBean() {
        <b>public</b> <b>void</b> afterPropertiesSet() throws Exception {

            Group group = identityService.newGroup(<font>"user"</font><font>);
            group.setName(</font><font>"users"</font><font>);
            group.setType(</font><font>"security-role"</font><font>);
            identityService.saveGroup(group);

            User admin = identityService.newUser(</font><font>"admin"</font><font>);
            admin.setPassword(</font><font>"admin"</font><font>);
            identityService.saveUser(admin);
        }
    };
}
</font>

测试应用程序

1. 分配任务给员工:

http://localhost:8080/process?assignee=Prince

2. 显示分配给Prince的任务

http://localhost:8080/tasks?assignee=Prince

3. 按任务ID完成分配给Prince的任务。

http://localhost:8080/completetask?taskId=9

4. 再次检查分配给Prince的任务

http://localhost:8080/tasks?assignee=Prince

5. 再次完成任务

http://localhost:8080/completetask?taskId=12

原文  https://www.jdon.com/51996
正文到此结束
Loading...