什么是Activiti?
Activiti5是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。Activiti基于Apache许可的开源BPM平台,创始人Tom Baeyens是JBoss jBPM的项目架构师,它特色是提供了eclipse插件,开发人员可以通过插件直接绘画出业务流程图。本文采用activiti5.22版本。数据库是ORACLE11g
1.Activiti数据库结构
1)通过运行activiti官方提供的数据库脚本创建数据库,支持db2、h2、hsql、mssql、mysql、oracle、postgres数据库
1、act_ge_ 通用数据表,ge是general的缩写
2、act_hi_ 历史数据表,hi是history的缩写,对应HistoryService接口
3、act_id_ 身份数据表,id是identity的缩写,对应IdentityService接口
4、act_re_ 流程存储表,re是repository的缩写,对应RepositoryService接口,存储流程部署和流程定义等静态数据
5、act_ru_ 运行时数据表,ru是runtime的缩写,对应RuntimeService接口
2.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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="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>
<!-- 定义Service服务 -->
<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"/>
<bean id="identityService" factory-bean="processEngine"
factory-method="getIdentityService"/>
<bean id="formService" factory-bean="processEngine"
factory-method="getFormService"></bean>
</beans>
七大接口:
1.RepositoryService:提供一系列管理流程部署和流程定义的API。
2.RuntimeService:在流程运行时对流程实例进行管理与控制。
3.TaskService:对流程任务进行管理,例如任务提醒、任务完成和创建任务等。
4.IdentityService:提供对流程角色数据进行管理的API,这些角色数据包括用户组、用户及它们之间的关系。
5.ManagementService:提供对流程引擎进行管理和维护的服务。
6.HistoryService:对流程的历史数据进行操作,包括查询、删除这些历史数据。
7.FormService:表单服务。
3.activiti-webapp-explorer2整合
1)将模板导入项目中
explorer整合实现在线编辑工作流
将src目录下diagram-viewer,editor-app,modeler.html 复制到自己项目中,如下图,本文是复制到webapp下
2)配置全局路径
配置前段访问路径,否则activiti编辑器会无法访问
/*
* Activiti Modeler component part of the Activiti project
* Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
'use strict';
var ACTIVITI = ACTIVITI || {};
ACTIVITI.CONFIG = {
'contextRoot' : '/',#配置全文访问路径
};
3)后台配置
1.配置后台,页面访问接口配置,activti提供了基本的页面获取、流程保存、流程编辑等接口,用于工作流的在线演示与编辑。
2.将stencilset.json赋值到配置文件目录下,保证StencilsetRestResource能访问到,这是流程设计器的菜单和功能文件,保存为json格式。
4.后台实例代码
1)创建流程
/**
* 创建流程
*/
@RequestMapping("/createActiviti")
public void createActiviti(HttpServletRequest request,HttpServletResponse response) throws IOException{
Model model = repositoryService.newModel();
String name = "新建流程";
String description = "";
int revision = 1;
String key = "processKey";
ObjectNode modelNode = objectMapper.createObjectNode();
modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);
model.setName(name);
model.setKey(key);
model.setMetaInfo(modelNode.toString());
repositoryService.saveModel(model);
String id = model.getId();
//完善ModelEditorSource
ObjectNode editorNode = objectMapper.createObjectNode();
editorNode.put("id", "canvas");
editorNode.put("resourceId", "canvas");
ObjectNode stencilSetNode = objectMapper.createObjectNode();
stencilSetNode.put("namespace",
"http://b3mn.org/stencilset/bpmn2.0#");
editorNode.put("stencilset", stencilSetNode);
repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8"));
// return "redirect:/modeler.html?modelId=" + id;
response.sendRedirect(request.getContextPath() + "/modeler.html?modelId="+id);
}
2)更新流程
/**
* 更新流程
*/
@RequestMapping("/updateActiviti")
public void updateActiviti(String id,HttpServletRequest request,HttpServletResponse response) throws IOException{
response.sendRedirect(request.getContextPath() + "/modeler.html?modelId="+id);
}
3)发布流程
/**
* 发布
*/
@PostMapping("/publish")
@ResponseBody
public Object publish(@RequestParam(value="id")String id){
Result result=new Result();
try {
Model modelData=repositoryService.getModel(id);
byte[] bytes=repositoryService.getModelEditorSource(modelData.getId());
if(bytes==null){
result.setMsg("模型不得为空");
result.setSuccess(false);
return result;
}
JsonNode modelNode=null;
modelNode=new ObjectMapper().readTree(bytes);
BpmnModel model=new BpmnJsonConverter().convertToBpmnModel(modelNode);
if(model.getProcesses().size()==0){
result.setMsg("数据不符合要求");
result.setSuccess(false);
return result;
}
byte[] bpmnByates = new BpmnXMLConverter().convertToXML(model);
//发布流程
String processName=modelData.getName()+".bpmn20.xml";
String convertToXML=new String(bpmnByates);
System.out.println(convertToXML);
Deployment deployment=repositoryService.createDeployment()
.name(modelData.getName())
.addString(processName, new String(bpmnByates, "UTF-8"))
.deploy();
modelData.setDeploymentId(deployment.getId());
repositoryService.saveModel(modelData);
result.setMsg("发布成功");
result.setSuccess(true);
} catch (Exception e) {
result.setMsg("发布失败");
result.setSuccess(false);
}
return result;
}
3)流程查询
/**
* 流程查询
*/
@PostMapping("/deployDatagrid")
@ResponseBody
public Object deployDatagrid(String s_name, HttpServletResponse response,Integer page, Integer rows, String sort, String order){
PageInfo pageInfo = new PageInfo(page, rows, sort, order);
if(StringUtils.isBlank(s_name)){
s_name="";
}
int p1=page-1;
int r1=9-p1;
List<Deployment> deploymentList=repositoryService.createDeploymentQuery()
.deploymentNameLike("%" + s_name + "%").orderByDeploymenTime().desc()
.listPage(p1, r1);
long total=repositoryService.createDeploymentQuery().deploymentNameLike("%"+s_name+"%").count();
List<com.pasic.model.po.DeploymentEntity> deploymentList2=new ArrayList<com.pasic.model.po.DeploymentEntity>();
for (Deployment deployment : deploymentList) {
com.pasic.model.po.DeploymentEntity depm=new com.pasic.model.po.DeploymentEntity(deployment.getId(),deployment.getName(),deployment.getCategory(),deployment.getTenantId(),deployment.getDeploymentTime());
deploymentList2.add(depm);
}
System.out.println(deploymentList2);
pageInfo.setRows(deploymentList2);
pageInfo.setTotal((int)total);
if(total/rows==0){
pageInfo.setPagesize(0);
}else{
pageInfo.setPagesize(page++);
}
pageInfo.setNowpage(page);
pageInfo.setSize(rows);
pageInfo.setSuccess(true);
pageInfo.setMessage("列表获取成功");
return pageInfo;
}
4)删除流程
/**
* 删除流程
*/
@PostMapping("/deleteDeploy")
@ResponseBody
public Object deleteDeploy(@RequestParam(value="id")String id){
Result result=new Result();
try {
//加true强制删除
repositoryService.deleteDeployment(id,true);
result.setSuccess(true);
result.setMsg("删除成功");
} catch (Exception e) {
result.setSuccess(false);
result.setMsg("删除失败");
}
return result;
}
5)查看流程图片
1.后台
/**
* 查看流程图 图片
*/
@GetMapping("/showProcessPng")
public String showProcessPng(@RequestParam(value="deployId")String deployId,org.springframework.ui.Model model){
// model.addAttribute("diagramResourceName", processDefinition.getDiagramResourceName());
model.addAttribute("deployId", deployId);
return "activiti/deploy/showProcessPng";
}
@RequestMapping("/showView")
public String showView(String deploymentId, HttpServletResponse response)
throws Exception {
ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery()
.deploymentId(deploymentId)
.singleResult();
InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName());
OutputStream outputStream = response.getOutputStream();
for (int b = -1; (b = inputStream.read()) != -1; ) {
outputStream.write(b);
}
outputStream.close();
inputStream.close();
return null;
}
2.前台
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/commons/global.jsp" %>
<script>
</script>
<div class="bootui-layout" data-options="fit:true,border:false">
<div data-options="region:'center',fit:true,border:false">
<img style="position:absolute;top:0px;left:0px" src="${path }/act/showView?deploymentId=${deployId}">
</div>
</div>
6)将用户同步到activiti认证表中
/**
* 同步用户到activiti中
*/
@PostMapping("/syncdata")
@ResponseBody
public Object syncdata(){
Result result=new Result();
try {
Wrapper<SysUser> wrapper=new EntityWrapper<SysUser>();
List<SysUser> userList=userService.selectList(wrapper);
User au = null;
for (SysUser user : userList) {
au=new UserEntity();
au.setId(user.getId());
au.setFirstName(user.getName());
au.setEmail("");
identityService.deleteUser(au.getId());
identityService.saveUser(au);
}
Wrapper<SysRole> wrapper2=new EntityWrapper<SysRole>();
List<SysRole> sysRoleList=roleService.selectList(wrapper2);
Group group=null;
for (SysRole role : sysRoleList) {
group=new GroupEntity();
group.setId(role.getId());
group.setName(role.getName());
identityService.deleteGroup(group.getId());
identityService.saveGroup(group);
}
Wrapper<SysUserRole> wrapper3=new EntityWrapper<SysUserRole>();
List<SysUserRole> roleUserList=userRoleService.selectList(wrapper3);
for (SysUserRole userRole : roleUserList) {
identityService.deleteMembership(userRole.getUserId(), userRole.getRoleId());
identityService.createMembership(userRole.getUserId(), userRole.getRoleId());
}
result.setMsg("同步成功");
result.setSuccess(true);
} catch (Exception e) {
result.setMsg("同步失败");
result.setSuccess(false);
}
return result;
}