1.项目介绍
在现有ssh架构基础上整合flowable工作流.
2.实现步骤
(1)新增flowable相关jar包
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring</artifactId>
<version>6.3.1</version>
</dependency>
(2)修改原有配置文件spring-hibernate
原始xml文件中新增flowable相关配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
">
<!-- Spring对com.xrom.ssh目录下的@Repository、@Service、@@Component注解标注的bean进行自动扫描 -->
<context:component-scan base-package="com.xrom.ssh">
<!-- 扫描时跳过 @Controller 注解的JAVA类(控制器) -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- hibernate配置 -->
<context:property-placeholder location="classpath:/jdbc.properties" />
<!--配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${database.driverClassName}" /> <!--数据库连接驱动 -->
<property name="jdbcUrl" value="${database.url}" /> <!--数据库地址 -->
<property name="user" value="${database.username}" /> <!--用户名 -->
<property name="password" value="${database.password}" /> <!--密码 -->
<property name="maxPoolSize" value="40" /> <!--最大连接数 -->
<property name="minPoolSize" value="1" /> <!--最小连接数 -->
<property name="initialPoolSize" value="10" /> <!--初始化连接池内的数据库连接 -->
<property name="maxIdleTime" value="20" /> <!--最大空闲时间 -->
</bean>
<!--配置session工厂 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.xrom.ssh.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> <!--hibernate根据实体自动生成数据库表 -->
<prop key="hibernate.dialect">${hibernate.dialect}</prop> <!--指定数据库方言 -->
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <!--在控制台显示执行的数据库操作语句 -->
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop> <!--在控制台显示执行的数据哭操作语句(格式) -->
</props>
</property>
</bean>
<!-- 事物管理器配置 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="processEngineConfiguration" class="org.flowable.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="asyncExecutorActivate" value="false" />
<property name="activityFontName" value="宋体" />
<property name="labelFontName" value="宋体" />
<property name="annotationFontName" value="宋体" />
</bean>
<bean id="processEngine" class="org.flowable.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="identityService" factory-bean="processEngine" factory-method="getIdentityService"/>
<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"/>
<bean id="formService" factory-bean="processEngine" factory-method="getFormService" />
<bean id="flowableRule" class="org.flowable.engine.test.FlowableRule">
<property name="processEngine" ref="processEngine" />
</bean>
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>
(3)jdbc.properties文件base.url添加&useSSL=false
由于本机mysql版本为8.0 因此更改端口3305用于连接docker中mysql 5.7
database.driverClassName= com.mysql.jdbc.Driver
database.username=root
database.password=root
database.url=jdbc:mysql://localhost:3305/restful_api?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false
(4)项目启动,flowable自动创建所缺失的表,控制台日志如下
(5)idea安装Flowable BPMN visualizer插件
(6)resources下创建processes文件夹
(7)新建ask_for_leave.bpmn20.xml
(8)打开View BPMN(Flowable) Diagram 画一个简易的流程
(9)提取接口读取.bnmp20.xml文件,创建流程
@POST
@Path("/createFlowable")
public void createFlowable() {
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("./processes/ask_for_leave.bpmn20.xml")
.deploy();
}
(10)提取接口,启动流程
@POST
@Path("/addTask")
public String addExpense(@QueryParam("roleId") String roleId) {
try {
HashMap<String, Object> map = new HashMap<>();
map.put("leaveTask", staffId);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("ask_for_leave", map);
runtimeService.setVariable(processInstance.getId(), "name", "javaboy");
runtimeService.setVariable(processInstance.getId(), "reason", "休息一下");
runtimeService.setVariable(processInstance.getId(), "days", 10);
log.info("创建请假流程 processId:{}", processInstance.getId());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
(11)生成流程图,查看当前流程进度
@POST
@Path("/processDiagram")
public void genProcessDiagram(@Context HttpServletResponse httpServletResponse, @QueryParam("processId") String processId) {
try {
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
//流程走完的不显示图
if (pi == null) {
return;
}
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
//使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
String InstanceId = task.getProcessInstanceId();
List<Execution> executions = runtimeService
.createExecutionQuery()
.processInstanceId(InstanceId)
.list();
//得到正在执行的Activity的Id
List<String> activityIds = new ArrayList<>();
List<String> flows = new ArrayList<>();
for (Execution exe : executions) {
List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
activityIds.addAll(ids);
}
//获取流程图
BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0);
OutputStream out = null;
byte[] buf = new byte[1024];
int legth = 0;
try {
out = httpServletResponse.getOutputStream();
while ((legth = in.read(buf)) != -1) {
out.write(buf, 0, legth);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
(12)postman返回结果