参考文档:

https://github.com/jbarrez/spring-boot-with-activiti-example
https://github.com/sxyx2008/spring-activiti-webapp
http://www.cnblogs.com/hongwz/p/5548473.html

Spring典型配置

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean> <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="jobExecutorActivate" value="false" />
</bean> <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean> <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
<bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
<bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" /> ...

自定义的实体类可以这么设置:

<beans>
...
<tx:annotation-driven transaction-manager="transactionManager"/> <bean id="userBean" class="org.activiti.spring.test.UserBean">
<property name="runtimeService" ref="runtimeService" />
</bean> <bean id="printer" class="org.activiti.spring.test.Printer" /> </beans>

写注解:

@ContextConfiguration("classpath:org/activiti/spring/test/transaction/SpringTransactionIntegrationTest-context.xml")

然后就可以访问Activiti的工厂类和自定义的实体类,
比如RepositoryService的实例这样获得,同时这也是Spring集成环境下的bpmn文件的部署方式:

RepositoryService repositoryService =
(RepositoryService) applicationContext.getBean("repositoryService");
String deploymentId = repositoryService
.createDeployment()
.addClasspathResource("org/activiti/spring/test/hello.bpmn20.xml")
.deploy()
.getId();

new 一个自定义的实体类实例:

UserBean userBean = (UserBean) applicationContext.getBean("userBean");
userBean.hello();

自定义的实体类:

public class UserBean {

/** Spring 注入 */
private RuntimeService runtimeService; @Transactional
public void hello() {
runtimeService.startProcessInstanceByKey("helloProcess");
} public void setRuntimeService(RuntimeService runtimeService) {
this.runtimeService = runtimeService;
}
}

表达式

在流程定义文件bpmn20.xml使用表达式

表达式可以灵活动态的使用类的方法,他可以实现流程计算逻辑和实体类的解耦,说具体些就是流程定义文件可以不用Hardcode了,直接通过接口调用的形式访问具体的类,
举例,定义一个输出打印的类,

public class Printer {

public void printMessage() {
  System.out.println("hello world");
}
}

在Spring里注册:

<beans>
... <bean id="printer" class="org.activiti.examples.spring.Printer" /> </beans>

建立关联配置:

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
...
<property name="beans">
<map>
<entry key="printer" value-ref="printer" />
</map>
</property>
</bean>

最后,就可以在流程定义文件bpmn20.xml使用表达式,定义了一个serviceTask:
这种调用方法非常灵活,也是集成Spring高效和方便的地方

<definitions id="definitions">

<process id="helloProcess">

<startEvent id="start" />
<sequenceFlow id="flow1" sourceRef="start" targetRef="print" /> <serviceTask id="print" activiti:expression="#{printer.printMessage()}" />
<sequenceFlow id="flow2" sourceRef="print" targetRef="end" /> <endEvent id="end" /> </process> </definitions>

使用Spring自动部署bpmn20.xml
仅当文件变化的时候,才会被重新部署,特别方便用于系统调试,程序员必备

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
...
<property name="deploymentResources"
value="classpath*:/org/activiti/spring/test/autodeployment/autodeploy.*.bpmn20.xml" />
</bean> <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>

可以使用通配符

<property name="deploymentResources" value="classpath*:/activiti/*.bpmn" />
<property name="deploymentMode" value="single-resource" />

Hibernate 4.2.x集成

POM:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency> <dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.183</version>
</dependency>

配置是不是很简单?

然后就可以开发了

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; @Configuration
@ComponentScan
@EnableAutoConfiguration
public class MyApplication { public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
} @Bean
public CommandLineRunner init(final RepositoryService repositoryService,
final RuntimeService runtimeService,
final TaskService taskService) { return new CommandLineRunner() {
@Override
public void run(String... strings) throws Exception {
System.out.println("Number of process definitions : "
+ repositoryService.createProcessDefinitionQuery().count());
System.out.println("Number of tasks : " + taskService.createTaskQuery().count());
runtimeService.startProcessInstanceByKey("oneTaskProcess");
System.out.println("Number of tasks after process start: " + taskService.createTaskQuery().count());
}
}; }
}

使用MySQL数据库
POM:

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>8.0.15</version>
</dependency>

数据源

@Bean
public DataSource database() {
return DataSourceBuilder.create()
.url("jdbc:mysql://127.0.0.1:3306/activiti-spring-boot?characterEncoding=UTF-8")
.username("alfresco")
.password("alfresco")
.driverClassName("com.mysql.jdbc.Driver")
.build();
}

REST开发扩展

Spring Boot可以快速开发web api接口,REST对集成第三方应用非常重要
POM:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>

开发服务类,服务类是用于控制器的重复调用,即帮助类

@Service
public class MyService { @Autowired
private RuntimeService runtimeService; @Autowired
private TaskService taskService; @Transactional
public void startProcess() {
runtimeService.startProcessInstanceByKey("oneTaskProcess");
} @Transactional
public List<Task> getTasks(String assignee) {
return taskService.createTaskQuery().taskAssignee(assignee).list();
} }

控制器:
注意:启动流程使用POST,获取任务使用了GET,在输出时自动把实体类(TaskRepresentation)转换为JSON格式

@RestController
public class MyRestController { @Autowired
private MyService myService; @RequestMapping(value="/process", method= RequestMethod.POST)
public void startProcessInstance() {
myService.startProcess();
} @RequestMapping(value="/tasks", method= RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
public List<TaskRepresentation> getTasks(@RequestParam String assignee) {
List<Task> tasks = myService.getTasks(assignee);
List<TaskRepresentation> dtos = new ArrayList<TaskRepresentation>();
for (Task task : tasks) {
dtos.add(new TaskRepresentation(task.getId(), task.getName()));
}
return dtos;
} static class TaskRepresentation { private String id;
private String name; public TaskRepresentation(String id, String name) {
this.id = id;
this.name = name;
} public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} } }

需要注意@ComponentScan一定在加在application类的注解

测试:
curl -X POST http://localhost:8080/process
curl http://localhost:8080/tasks?assignee=kermit
[{"id":"10004","name":"my task"}]

JPA支持

默认JPA是Hibernate

POM:

<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-jpa</artifactId>
<version>${activiti.version}</version>
</dependency>

实体类:

@Entity
class Person { @Id
@GeneratedValue
private Long id; private String username; private String firstName; private String lastName; private Date birthDate; public Person() {
} public Person(String username, String firstName, String lastName, Date birthDate) {
this.username = username;
this.firstName = firstName;
this.lastName = lastName;
this.birthDate = birthDate;
} public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getFirstName() {
return firstName;
} public void setFirstName(String firstName) {
this.firstName = firstName;
} public String getLastName() {
return lastName;
} public void setLastName(String lastName) {
this.lastName = lastName;
} public Date getBirthDate() {
return birthDate;
} public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
}

如果不使用in-memory数据库,数据表不会自动建立,需要 application.properties 增加配置:
spring.jpa.hibernate.ddl-auto=update

增加接口:

public interface PersonRepository extends JpaRepository<Person, Long> {

Person findByUsername(String username);

}

服务类:

@Service
@Transactional
public class MyService { @Autowired
private RuntimeService runtimeService; @Autowired
private TaskService taskService; @Autowired
private PersonRepository personRepository; public void startProcess(String assignee) { Person person = personRepository.findByUsername(assignee); Map<String, Object> variables = new HashMap<String, Object>();
variables.put("person", person);
runtimeService.startProcessInstanceByKey("oneTaskProcess", variables);
} public List<Task> getTasks(String assignee) {
return taskService.createTaskQuery().taskAssignee(assignee).list();
} public void createDemoUsers() {
if (personRepository.findAll().size() == 0) {
personRepository.save(new Person("jbarrez", "Joram", "Barrez", new Date()));
personRepository.save(new Person("trademakers", "Tijs", "Rademakers", new Date()));
}
} }

在CommandLineRunner 初始化的时候,添加用户持久化数据(createDemoUsers())

@Bean
public CommandLineRunner init(final MyService myService) { return new CommandLineRunner() {
public void run(String... strings) throws Exception {
  myService.createDemoUsers();
}
}; }

控制器:

@RestController
public class MyRestController { @Autowired
private MyService myService; @RequestMapping(value="/process", method= RequestMethod.POST)
public void startProcessInstance(@RequestBody StartProcessRepresentation startProcessRepresentation) {
myService.startProcess(startProcessRepresentation.getAssignee());
} ... static class StartProcessRepresentation { private String assignee; public String getAssignee() {
return assignee;
} public void setAssignee(String assignee) {
this.assignee = assignee;
}
}

流程定义再一次使用了表达式:

<userTask id="theTask" name="my task" activiti:assignee="${person.id}"/>

测试:POST一个流程启动者的username
curl -H "Content-Type: application/json" -d '{"assignee" : "jbarrez"}' http://localhost:8080/process
curl http://localhost:8080/tasks?assignee=1

[{"id":"12505","name":"my task"}]

更高级的内容可以自行研究:

  • Actuator support
  • Spring Integration support
  • Rest API integration
  • Spring Security support

Liferay7 BPM门户开发之5: Activiti和Spring集成的更多相关文章

  1. Liferay7 BPM门户开发之11: Activiti工作流程开发的一些统一规则和实现原理(完整版)

    注意:以下规则是我为了规范流程的处理过程,不是Activiti公司的官方规定. 1.流程启动需要设置启动者,在Demo程序中,“启动者变量”名统一设置为initUserId 启动时要做的: ident ...

  2. Liferay7 BPM门户开发之8: Activiti实用问题集合

    1.如何实现审核的上级获取(任务逐级审批) 这个是必备功能,通过Spring的注入+Activiti表达式可以很容易解决. 可参考: http://blog.csdn.net/sunxing007/a ...

  3. Liferay7 BPM门户开发之7: Activiti中的重要概念和主要数据库结构

    流程的人员参与角色: Assignee :签收者(即待办人) Candidate:候选人 Owner:拥有者 Starter:启动者 participant:参与者,包含查阅 流程变量的类型: Str ...

  4. Liferay7 BPM门户开发之6: Activiti数据库换为mysql

    第一步: 在mysql中创建数据库名字叫 'activiti' 执行D:\activiti-5.21.0\database\create下的脚本 第二步: 打开=> apache-tomcat/ ...

  5. Liferay7 BPM门户开发之4: Activiti事件处理和监听Event handlers

    事件机制从Activiti 5.15开始引入,这非常棒,他可以让你实现委托. 可以通过配置添加事件监听器,也可以通过Runtime API加入注册事件. 所有的事件参数子类型都来自org.activi ...

  6. Liferay7 BPM门户开发之3: Activiti开发环境搭建

    下载地址: http://activiti.org/download.html 源码: https://github.com/Activiti/Activiti 环境准备(检查项): JDK 1.7 ...

  7. Liferay7 BPM门户开发之10: 通用流程实现从Servlet到Portlet(Part1)

    开发目的: 实现通用流程自动化处理(即实现不需要hardcode代码的bpm统一处理后台,仅需要写少量前端html form代码和拖拽设计BPM定义) 既可独立运行或可依托于Liferay或依托其它门 ...

  8. Liferay7 BPM门户开发之37: Liferay7下的OSGi Hook集成开发

    hook开发是Liferay客制扩展的一种方式,比插件灵活,即可以扩展liferay门户,也能对原有特性进行更改,Liferay有许多内置的服务,比如用hook甚至可以覆盖Liferay服务. 可作为 ...

  9. Liferay7 BPM门户开发之17: Portlet 生命周期

    Portlet 生命周期 init() =〉 render() =〉 processAction() =〉 processEvent() =〉 serveResource() =〉destroy() ...

随机推荐

  1. MYSQL分组合并函数

    MySQL中group_concat函数完整的语法如下:group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符' ...

  2. Jekins在Tomcat上的安装和配置

    首先,apache.org的官网下载Apache Tomcat. 第二:点击/一步一步的安装tomcat,没有任何需要说明的难点. 我偏好选择安装tomcat可执行文件,这样可以在安装时就自动吧tom ...

  3. linux网络日志分析

    1.清空日志的技巧 2.访问日志格式分析 3. web日志统计举例

  4. 判断JS的数据类型

    typeof.instanceof. constructor. prototype方法比较 (摘自如何判断JS中的数据类型) 1. 使用typeof操作符. 对一个值使用 typeof 操作符可能返回 ...

  5. Eclipse Android 模拟器启动过慢

    打开AVD Manager窗口,在模拟器配置页面,选择Intel Atom (x86)选项.笔记本的CPU处理器是Intel 酷睿. 可以发现模拟器的启动速度明显变快.

  6. 396. Rotate Function 移动加权求和,取最大值

    [抄题]: Given an array of integers A and let n to be its length. Assume Bk to be an array obtained by ...

  7. Linux终端命令

    一.文件目录类 1.建立目录:mkdir 目录名2.删除空目录:rmdir 目录名3.无条件删除子目录: rm -rf 目录名4.改变当前目录:cd 目录名 (进入用户home目录:cd ~;进入上一 ...

  8. tp3.2 phpexcel 简单导出多个sheet(execl表格)

    参考链接:https://blog.csdn.net/u011341352/article/details/70211962 以下是公共类PHPExcel.php文件: // 开始 <?php/ ...

  9. java_22 Map接口

    1Map Collection是孤立存在的,向集合中存储元素是一个一个放进去的 Map中的集合存储是成对的,可以通过键找到值.即将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值 ...

  10. Java16-java语法基础——异常

    Java16-java语法基础——异常 一.异常概念 1.异常:应用程序在运行过程中出现的错误或非正常的意外情况,即虚拟机的通常操作中可能遇到的异常,是一种常见的运行错误. 2.原因:数组越界.空指针 ...