在本教程中,我们将演示Spring Boot + Activiti示例。Activiti是一个开源工作流引擎,可以执行BPMN 2.0中描述的业务流程。Activiti引擎的核心目标是采用由人工任务和服务调用组成的流程定义,并按特定顺序执行。
在这里,我们将设计一个BMPN工作流程图和Spring Boot应用程序,它有助于管理流程,如下所示:
然后我们将使用Spring JPA创建员工列表并将其详细信息存储到数据库中,并通过调用Activiti API将任务分配给员工。员工将完成第一项任务和第二项任务。
技术列表:
- Spring Tool Suite 3
- JDK 8
- Spring Boot 1.5.3.RELEASE
- Activiti 5.22.0
- H2(内存中)数据库
- 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="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:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.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="Examples"> <process id="simple-process" name="Simple Process" isExecutable="true"> <startEvent id="start" name="Start"></startEvent> <userTask id="userTask1" name="User Task 1" activiti:assignee="${employee.name}"> <documentation>Complete user task 1 first.</documentation> </userTask> <userTask id="userTask2" name="User Task 2" activiti:assignee="${employee.name}"> <documentation>Work for the second task.</documentation> </userTask> <endEvent id="theEnd"></endEvent> <sequenceFlow id="flow1" sourceRef="userTask2" targetRef="theEnd"></sequenceFlow> <sequenceFlow id="flow3" sourceRef="userTask1" targetRef="userTask2"></sequenceFlow> <sequenceFlow id="flow4" sourceRef="start" targetRef="userTask1"></sequenceFlow> </process> </definitions>
|
activiti:assignee属性 ${employee.name}是被分配到任务的雇员。
模型和存储库类
创建Employee数据模型类。
@Entity public class Employee {
@Id @GeneratedValue private Long id; private String name; private String designation; // generate getters and setters...
public Employee() { }
public Employee(String name, String designation) {
this.name = name; this.designation = designation; } }
|
创建EmployeeRepository实现接口JpaRepository<T, ID>的findByName(Stringname)Employee方法,实现从数据库查询的雇员。
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
public Employee findByName(String name);
}
|
服务类
EmployeeService班负责员工加入到数据库中。应用程序启动时将调用此服务类。
@Service public class EmployeeService {
@Autowired private EmployeeRepository employeeRepository;
// create the list of Employees into the database who perform the task public void createEmployee() {
if (employeeRepository.findAll().size() == 0) {
employeeRepository.save(new Employee("Prince", "Software Enginner")); employeeRepository.save(new Employee("Gaurav", "Technical Lead")); employeeRepository.save(new Employee("Abhinav", "Test Lead")); } } }
|
而ProcessService类是负责启动的过程中,给员工分配任务,检索分配给员工的任务,并通过ID完成特定的任务。
@Service public class ProcessService {
@Autowired private EmployeeRepository employeeRepository;
@Autowired private RuntimeService runtimeService;
@Autowired private TaskService taskService;
@Autowired private RepositoryService repositoryService;
// start the process and set employee as variable public String startTheProcess(String assignee) {
Employee employee = employeeRepository.findByName(assignee);
Map<String, Object> variables = new HashMap<>(); variables.put("employee", employee);
runtimeService.startProcessInstanceByKey("simple-process", variables);
return processInformation(); }
// fetching process and task information public String processInformation() {
List<Task> taskList = taskService.createTaskQuery().orderByTaskCreateTime().asc().list();
StringBuilder processAndTaskInfo = new StringBuilder(); processAndTaskInfo.append("Number of process definition available: " + repositoryService.createProcessDefinitionQuery().count() + " | Task Details= ");
taskList.forEach(task -> {
processAndTaskInfo.append("ID: " + task.getId() + ", Name: " + task.getName() + ", Assignee: " + task.getAssignee() + ", Description: " + task.getDescription()); });
return processAndTaskInfo.toString(); }
// fetch task assigned to employee public List<Task> getTasks(String assignee) { return taskService.createTaskQuery().taskAssignee(assignee).list(); }
// complete the task public void completeTask(String taskId) { taskService.complete(taskId); } }
|
控制器类
ProcessController类处理HTTP请求,调用相应的ProcessService类的方法,和响应的具体结果。
@RestController public class ProcessController {
@Autowired private ProcessService processService;
/* * Method will start the Activiti process engine and set employee to perform * the task */ @RequestMapping(value = "/process") public String startProcessInstance(@RequestParam String assignee) { return processService.startTheProcess(assignee); }
// Retrieve the tasks assigned to an employee @RequestMapping(value = "/tasks") public String getTasks(@RequestParam String assignee) { List<Task> tasks = processService.getTasks(assignee); return tasks.toString(); }
// Complete the task by their ID @RequestMapping(value = "/completetask") public String completeTask(@RequestParam String taskId) { processService.completeTask(taskId); return "Task with id " + taskId + " has been completed!"; } }
|
运行应用程序
最后,创建一个App类,该类调用在启动应用程序时创建员工EmployeeSerice的createEmployee()方法。
@SpringBootApplication public class App {
public static void main(String[] args) { SpringApplication.run(App.class, args); }
@Bean public CommandLineRunner init(final EmployeeService employeeService) {
return new CommandLineRunner() { public void run(String... strings) throws Exception { employeeService.createEmployee(); } }; } }
|
要使用用户标识和密码保护您的应用程序,请在App类中添加以下代码。
@Bean InitializingBean usersAndGroupsInitializer(final IdentityService identityService) {
return new InitializingBean() { public void afterPropertiesSet() throws Exception {
Group group = identityService.newGroup("user"); group.setName("users"); group.setType("security-role"); identityService.saveGroup(group);
User admin = identityService.newUser("admin"); admin.setPassword("admin"); identityService.saveUser(admin); } }; }
|
测试应用程序
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