`
wiselyman
  • 浏览: 2080942 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
博客专栏
Group-logo
点睛Spring4.1
浏览量:81079
74ae1471-94c5-3ae2-b227-779326b57435
点睛Spring MVC4...
浏览量:130130
社区版块
存档分类
最新评论

Spring Boot与Activiti集成实战

阅读更多

1.介绍

1.1 Spring Boot

Spring Boot基于Spring和“习惯由于配置”原则,实现快速搭建项目的准生产框架。建议现在的Java从业者快速迁移到以Spring Boot为基础开发,这将大大降低开发的难度和极大的提高开发效率。

1.2 Activiti

在做企业级应用开发的时候,为了避免流程和业务的耦合,我们经常会引入工作流来解决业务中所遇到的审批相关的操作。

Activiti是一个轻量级的工作流和业务流程管理平台,它的核心是一个超快的BPMN2引擎。

1.3 spring-boot-starters

Spring Boot基于“习惯优于配置”的原则,为大量第三方的库提供自动配置的功能。由Spring专家Josh Long主导开发的spring-boot-starters为我们在Spring Boot下使用Activiti做了自动配置。

其中主要自动配置包括:
* 自动创建Activiti ProcessEngine的Bean;
* 所有的Activiti Service都自动注册为Spring的Bean;
* 创建一个Spring Job Executor
* 自动扫描并部署位于src/main/resources/processes目录下的流程处理文件。

2.实战

2.1 流程设计

Activi为我们提供了一个基于eclipse的流程设计器,安装地址为:http://activiti.org/designer/update/

新建Activi项目或流程

我们当前模拟一个简单的工作流程,某人想加入某个公司,然后有权限审批的人审批,审批同意后将此人加入组织并输出“加入组织成功”,不同意输出“加入组织失败”。

设计的流程图如下:

流程源码如下:

  1. <processid="joinProcess"name="Join process"isExecutable="true">
  2. <startEventid="startevent1"name="Start">
  3. <extensionElements>
  4. <activiti:formPropertyid="personId"name="person id"
  5. type="long"required="true"></activiti:formProperty>
  6. <activiti:formPropertyid="compId"name="company Id"
  7. type="long"required="true"></activiti:formProperty>
  8. </extensionElements>
  9. </startEvent>
  10. <endEventid="endevent1"name="End"></endEvent>
  11. <userTaskid="ApprovalTask"name="Approval Task"
  12. activiti:candidateUsers="${joinService.findUsers(execution)}"isForCompensation="true">
  13. <extensionElements>
  14. <activiti:formPropertyid="joinApproved"name="Join Approved"
  15. type="enum">
  16. <activiti:valueid="true"name="Approve"></activiti:value>
  17. <activiti:valueid="false"name="Reject"></activiti:value>
  18. </activiti:formProperty>
  19. </extensionElements>
  20. </userTask>
  21. <sequenceFlowid="flow1"sourceRef="startevent1"targetRef="ApprovalTask"></sequenceFlow>
  22. <serviceTaskid="AutoTask"name="Auto Task"
  23. activiti:expression="${joinService.joinGroup(execution)}"></serviceTask>
  24. <sequenceFlowid="flow2"sourceRef="ApprovalTask"targetRef="AutoTask"></sequenceFlow>
  25. <sequenceFlowid="flow3"sourceRef="AutoTask"targetRef="endevent1"></sequenceFlow>
  26. </process>

 

流程解释:

流程最左边是开始,最右边结束,左二小人图标为用户任务(User Task)需要人参与操作,我们选择有权限的操作的人来源于Spring的bean方法activiti:candidateUsers=”${joinService.findUsers(execution)},左三齿轮图标为服务任务(Service Task),是自动执行的任务,自动调用Spring的bean方法。

2.2 项目搭建

pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>com.wisely</groupId>
  6. <artifactId>activiti</artifactId>
  7. <version>0.0.1-SNAPSHOT</version>
  8. <packaging>jar</packaging>
  9. <name>activiti</name>
  10. <description>Demo project for Spring Boot</description>
  11. <parent>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-parent</artifactId>
  14. <version>1.3.0.RELEASE</version>
  15. <relativePath/><!-- lookup parent from repository -->
  16. </parent>
  17. <properties>
  18. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  19. <java.version>1.8</java.version>
  20. <activiti.version>5.19.0</activiti.version>
  21. </properties>
  22. <dependencies>
  23. <dependency>
  24. <groupId>org.springframework.boot</groupId>
  25. <artifactId>spring-boot-starter-web</artifactId>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter-data-jpa</artifactId>
  30. </dependency>
  31. <dependency>
  32. <groupId>mysql</groupId>
  33. <artifactId>mysql-connector-java</artifactId>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.activiti</groupId>
  37. <artifactId>activiti-spring-boot-starter-basic</artifactId>
  38. <version>${activiti.version}</version>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.springframework.boot</groupId>
  42. <artifactId>spring-boot-starter-test</artifactId>
  43. <scope>test</scope>
  44. </dependency>
  45. </dependencies>
  46. <build>
  47. <plugins>
  48. <plugin>
  49. <groupId>org.springframework.boot</groupId>
  50. <artifactId>spring-boot-maven-plugin</artifactId>
  51. </plugin>
  52. </plugins>
  53. </build>
  54. </project>

 

application.properties配置

  1. spring.jpa.hibernate.ddl-auto=update
  2. spring.jpa.database=MYSQL
  3. spring.datasource.url=jdbc:mysql://192.168.1.68:3306/activiti-spring-boot?characterEncoding=UTF-8
  4. spring.datasource.username=root
  5. spring.datasource.password=密码
  6. spring.datasource.driver-class-name=com.mysql.jdbc.Driver

 

2.3 核心代码

实体类

  1. @Entity
  2. publicclass Person {
  3. @Id
  4. @GeneratedValue
  5. private Long personId;
  6. privateString personName;
  7. @ManyToOne(targetEntity = Comp.class)
  8. private Comp comp;
  9. publicPerson(){
  10. }
  11. publicPerson(String personName){
  12. super();
  13. this.personName = personName;
  14. }
  15. //省略getter、setter方法
  16. }

 

  1. @Entity
  2. publicclass Comp {
  3. @Id
  4. @GeneratedValue
  5. private Long compId;
  6. privateString compName;
  7. @OneToMany(mappedBy = "comp",targetEntity = Person.class)
  8. private List<Person> people;
  9. publicComp(String compName){
  10. this.compName = compName;
  11. }
  12. publicComp(){
  13. }
  14. //省略getter、setter方法
  15. }

 

DAO

  1. publicinterface PersonRepository extends JpaRepository<Person, Long> {
  2. public Person findByPersonName(String personName);
  3. }

 

  1. publicinterface CompRepository extends JpaRepository<Comp, Long>{
  2. }

 

Activiti服务

  1. @Service
  2. @Transactional
  3. publicclass ActivitiService {
  4. //注入为我们自动配置好的服务
  5. @Autowired
  6. private RuntimeService runtimeService;
  7. @Autowired
  8. private TaskService taskService;
  9. //开始流程,传入申请者的id以及公司的id
  10. publicvoidstartProcess( Long personId, Long compId){
  11. Map<String, Object> variables = new HashMap<String, Object>();
  12. variables.put("personId", personId);
  13. variables.put("compId", compId);
  14. runtimeService.startProcessInstanceByKey("joinProcess", variables);
  15. }
  16. //获得某个人的任务别表
  17. public List<Task> getTasks(String assignee){
  18. return taskService.createTaskQuery().taskCandidateUser(assignee).list();
  19. }
  20. //完成任务
  21. publicvoidcompleteTasks(Boolean joinApproved, String taskId){
  22. Map<String, Object> taskVariables = new HashMap<String, Object>();
  23. taskVariables.put("joinApproved", joinApproved);
  24. taskService.complete(taskId, taskVariables);
  25. }
  26. }

 

Service Task服务

  1. @Service
  2. publicclass JoinService {
  3. @Autowired
  4. PersonRepository personRepository;
  5. @Autowired
  6. private CompRepository compRepository;
  7. //加入公司操作,可从DelegateExecution获取流程中的变量
  8. publicvoidjoinGroup(DelegateExecution execution){
  9. Boolean bool = (Boolean) execution.getVariable("joinApproved");
  10. if(bool){
  11. Long personId = (Long) execution.getVariable("personId");
  12. Long compId = (Long) execution.getVariable("compId");
  13. Comp comp = compRepository.findOne(compId);
  14. Person person = personRepository.findOne(personId);
  15. person.setComp(comp);
  16. personRepository.save(person);
  17. System.out.println("加入组织成功");
  18. }else{
  19. System.out.println("加入组织失败");
  20. }
  21. }
  22. //获取符合条件的审批人,演示这里写死,使用应用使用实际代码
  23. public List<String> findUsers(DelegateExecution execution){
  24. return Arrays.asList("admin","wtr");
  25. }
  26. }

 

控制器

  1. @RestController
  2. publicclass MyRestController {
  3. @Autowired
  4. private ActivitiService myService;
  5. //开启流程实例
  6. @RequestMapping(value="/process/{personId}/{compId}", method= RequestMethod.GET)
  7. publicvoidstartProcessInstance(@PathVariable Long personId,@PathVariable Long compId){
  8. myService.startProcess(personId,compId);
  9. }
  10. //获取当前人的任务
  11. @RequestMapping(value="/tasks", method= RequestMethod.GET)
  12. public List<TaskRepresentation> getTasks(@RequestParamString assignee){
  13. List<Task> tasks = myService.getTasks(assignee);
  14. List<TaskRepresentation> dtos = new ArrayList<TaskRepresentation>();
  15. for(Task task : tasks){
  16. dtos.add(newTaskRepresentation(task.getId(), task.getName()));
  17. }
  18. return dtos;
  19. }
  20. //完成任务
  21. @RequestMapping(value="/complete/{joinApproved}/{taskId}", method= RequestMethod.GET)
  22. publicStringcomplete(@PathVariable Boolean joinApproved,@PathVariableString taskId){
  23. myService.completeTasks(joinApproved,taskId);
  24. return"ok";
  25. }
  26. //Task的dto
  27. staticclass TaskRepresentation {
  28. privateString id;
  29. privateString name;
  30. publicTaskRepresentation(String id, String name){
  31. this.id = id;
  32. this.name = name;
  33. }
  34. publicStringgetId(){
  35. return id;
  36. }
  37. publicvoidsetId(String id){
  38. this.id = id;
  39. }
  40. publicStringgetName(){
  41. return name;
  42. }
  43. publicvoidsetName(String name){
  44. this.name = name;
  45. }
  46. }
  47. }

 

入口类

  1. @SpringBootApplication
  2. publicclass ActivitiApplication {
  3. @Autowired
  4. private PersonRepository personRepository;
  5. @Autowired
  6. private CompRepository compRepository;
  7. publicstaticvoidmain(String[] args){
  8. SpringApplication.run(ActivitiApplication.class, args);
  9. }
  10. //初始化模拟数据
  11. @Bean
  12. public CommandLineRunner init(final ActivitiService myService){
  13. returnnewCommandLineRunner(){
  14. publicvoidrun(String... strings)throws Exception {
  15. if(personRepository.findAll().size() == 0){
  16. personRepository.save(newPerson("wtr"));
  17. personRepository.save(newPerson("wyf"));
  18. personRepository.save(newPerson("admin"));
  19. }
  20. if(compRepository.findAll().size() == 0){
  21. Comp group = newComp("great company");
  22. compRepository.save(group);
  23. Person admin = personRepository.findByPersonName("admin");
  24. Person wtr = personRepository.findByPersonName("wtr");
  25. admin.setComp(group);wtr.setComp(group);
  26. personRepository.save(admin);personRepository.save(wtr);
  27. }
  28. }
  29. };
  30. }
  31. }

 

2.4 演示

启动程序会自动初始化Activiti所用的数据库和我们的业务数据库,并自动发布我们的流程。

此时我们要加入的公司id为1,申请加入的人的id为2,使用PostMan访问http://localhost:8080/process/2/1 此时数据库发生如下变化

此时用户admin和wtr具备审批申请的权利,此时我们访问http://localhost:8080/tasks?assignee=admin 查看admin用户的任务,返回结果为:

  1. [
  2. {
  3. "id":"10",
  4. "name":"Approval Task"
  5. }
  6. ]

 

我们现在通过访问http://localhost:8080/complete/true/10 完成任务,true为同意(可以选择false),10为task的id,任务完成后会自动调用Service Task,此时wyf这条记录的comp_compId为更新为当前公司的id。

若代码不方便阅读,请查看http://www.microinsight.cn/2015/11/24/spring-boot-activiti/

 

新书推荐《JavaEE开发的颠覆者: Spring Boot实战》,涵盖Spring 4.x、Spring MVC 4.x、Spring Boot企业开发实战。

 

京东地址:http://item.jd.com/11894632.html

当当地址:http://product.dangdang.com/23926195.html

亚马逊地址:http://www.amazon.cn/图书/dp/B01D5ZBFUK/ref=zg_bsnr_663834051_6 

淘宝地址:https://item.taobao.com/item.htm?id=528426235744&ns=1&abbucket=8#detail

 

或自己在京东、淘宝、亚马逊、当当、互动出版社搜索自选。

 


2
0
分享到:
评论
3 楼 白天看黑夜 2017-12-05  
JavaEE开发的颠覆者 Spring Boot实战 完整版(带目录) 免费下载
http://www.itmayun.com/it/files/226631678709806/resource/515672241683315/1.html
2 楼 a43430096 2017-04-20  
你好 按照你的配置 项目启动没有报错  但是请请求的时候 弹出了用户名密码  这个是怎么回事啊
1 楼 nucleus 2016-05-29  
代码的排版也太难看了吧...

相关推荐

Global site tag (gtag.js) - Google Analytics