前言:博主之前对于工作流这一块的知识是空白的,也是因为前段时间公司的一个项目,然后其中有个审核环节需要用到工作流来开发比较简单,所以就各种找资料恶补了一番。现阶段博主也仅仅停留在会用,用过,有点校验的阶段,写这篇博客也是想把自己的经验写下来(ps:博主有个习惯,就是一些工作上的难点,或者是自己以前没有接触过的东西,博主就会自己用过之后会把它写下来,这样的话有助于自己巩固这个知识点),如果能帮助到那些正需要的童鞋的话,那是再好不过了~~
1.eclipse安装插件
1)打开 Help -> Install New Software. 在如下面板中:
2)然后点击右上角的Add按钮,添加配置插件的地址,如下图:
3)对应的填入下面的值即可(下面的值我也是从网上找来的)
Name: Activiti BPMN 2.0 designer
Location: http://activiti.org/designer/update/
4)点击OK之后,勾选对应的选项即可:
5)然后新建工程的时候,如果有activiti相关的东西就证明插件安装成功
2.准备activiti的开发环境搭建----springmvc整合activiti
1)pom文件添加activiti相关jar包和spring整合包
<!--工作流activiti -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>${activiti.version}</version>
</dependency>
<activiti.version>5.22.0</activiti.version>
2)xml中的相关配置
<!-- Activiti相关配置 -->
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration"></property>
</bean>
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<!--注入数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!--配置事物管理 -->
<property name="transactionManager" ref="transactionManager"></property>
<!--没有表创建表 -->
<property name="databaseSchemaUpdate" value="true"></property>
<property name="jobExecutorActivate" value="false"></property>
<!--自动部署 -->
<property name="deploymentResources">
<list>
<value>classpath*:activiti/OrderCheck.bpmn</value>
</list>
</property>
</bean>
<!--activiti的各种服务接口 -->
<!-- 工作流仓储服务 -->
<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" />
以上配置配置完,启动你的服务时,就会去你配置的自动部署的路径下面去找bpmn结尾的activiti文件去自动创建核心流程引擎对象,也就是processEngine
3.activiti流程图的一些属性
上图就是我当时项目里的一个审核的流程,逻辑上来讲并不是很复杂,运用到的activiti知识点也不是很多,只有一个排他网关,接下来我就讲一下我认为学会用activiti必需要知道的一些东西(本人也不是很熟悉,只是了解)
1)首先要给你的流程processEngine设置一个id和name,这个id就是你的processEngine唯一标识,开启这个流程实例就需要用得到你的id作为key(因为用id开启流程实例activiti会根据你的最新版本的流程来开启),具体设置如下:
2)然后就是根据你的实际业务逻辑给你自己设计的流程的每个task设置一个当前task的待办人或者待办组,如下:
Assignee:当前task的待办人,只有这个人才有权限看到当前任务,也只有这个人才能操作
users和groups:待办组,可以设置一组当前task的待办人,这里就可以集合role来做权限控制,只有某个role才能看到和操作当前任务
3)当前task默认执行的flow和flow的一些属性:每个task都有一个default flow属性设置,可有可无,但是如果有存在task提交之后会产生多个结果的情况下,最好需要设置,比如我在合同领取task设置了default flow为flow20,那么当当前task提交的时候,默认就会直接走flow,走到下一task
如果我想它走flow33,那么我就得需要再flow的main config属性里面设置condition的值,这里可以用表达式来做一个判断
当我在代码里设置的流程变量满足这个表达式,那么当提交当前task的时候,就会走flow33这条线。
4.activiti实战
1)开启一个流程:开启流程是通过runtimeService来实现的,activiti提供了各种service来满足用户的需求,在这里有一个很关键的点,流程关联业务。怎么样让流程和业务关联起来,其实activiti已经考虑到了 ,所以设计了一个businessKey,这个key就是流程关联业务的核心。
String processKey = "OrderCheck";
String businessTable = FtCustomerRecordOrder.class.getSimpleName();
//设置下一个任务办理人,也就是预约流程的办理人就是当前登录用户
Map<String,Object> vars = new HashMap<String, Object>();
vars.put("openUser", lud.getUid());
vars.put("checkType", 0);
String ObjId = businessTable + "." + orderNo;
//设置流程变量 让流程关联业务
vars.put("ObjId", ObjId);
//流程实例ID
String processInstanceId = actTaskService.startProcess(processKey, businessTable, orderNo, vars);
@Override
public String startProcess(String processKey,String businessTable,String businessId,Map<String, Object> vars) {
processInstanceByKey =
runtimeService.startProcessInstanceByKey(processKey,businessTable+"."+businessId,vars);
//返回流程实例ID
return processInstanceByKey.getProcessInstanceId();
}
开启流程的时候,我是用订单表实体类名.orderNo订单编号的形式拼接成一个businessKey,这样的话我开启的这个流程实例就跟我的这条orderNo绑定在一起了,等到我需要知道我这个流程实例是属于哪条订单的时候,取出businessKey就知道了
2)提交当前task。提交task的时候需要设置参数,参数包括下一个任务办理人,以及流程变量,判断走哪一条flow
@Override
public void complete(String taskId, Integer uid, String procInsId,String comment, String title, Map<String, Object> vars) {
if (StringUtils.isNotBlank(procInsId) && StringUtils.isNotBlank(comment)){
taskService.addComment(taskId, procInsId, comment);
}
// 设置流程变量
if (vars == null){
vars = new HashMap<String, Object>();
}
if(uid != null){
taskService.setAssignee(taskId, String.valueOf(uid));
}
// 设置流程标题
if (StringUtils.isNotBlank(title)){
vars.put("title", title);
}
//taskService.setVariablesLocal(taskId, vars);
// 提交任务
taskService.complete(taskId,vars);
}
3)获取当前待办任务总条数
@Override
public int todoCount(Activiti act) {
// TODO Auto-generated method stub
// =============== 等待签收的任务 ===============
TaskQuery toClaimQuery = taskService.createTaskQuery()
.includeProcessVariables().active().orderByTaskCreateTime().desc();
// 设置查询条件
if (StringUtils.isNotBlank(act.getAssignee())) {
toClaimQuery.taskAssignee(act.getAssignee());
}
if (StringUtils.isNotBlank(act.getTaskName())) {
toClaimQuery.taskName(act.getTaskName());
}
if (StringUtils.isNotBlank(act.getCandidateUser())){
toClaimQuery.taskCandidateUser(act.getCandidateUser());
}
if (StringUtils.isNotBlank(act.getCandidateGroup())){
toClaimQuery.taskCandidateGroup(act.getCandidateGroup());
}
if (StringUtils.isNotBlank(act.getProcDefKey())){
toClaimQuery.processDefinitionKey(act.getProcDefKey());
}
if (StringUtils.isNotBlank(act.getProcDefId())){
toClaimQuery.processDefinitionId(act.getProcDefId());
}
if (act.getBeginDate() != null){
toClaimQuery.taskCreatedAfter(act.getBeginDate());
}
if (act.getEndDate() != null){
toClaimQuery.taskCreatedBefore(act.getEndDate());
}
// 根据流程变量查询
Map<String,Object> vars = act.getVars();
if (vars != null){
for(Map.Entry<String, Object> entry : vars.entrySet()){
Object v = entry.getValue();
if(null != v && !v.equals("")){
toClaimQuery.processVariableValueEquals(
entry.getKey(), v);
}
}
}
return (int)toClaimQuery.count();
}
4)获取当前待办任务分页数据
@Override
public List<Activiti> todoList(int firstResult, int maxResults, Activiti act) {
// TODO Auto-generated method stub
List<Activiti> result = new ArrayList<Activiti>();
// =============== 等待签收的任务 ===============
TaskQuery toClaimQuery = taskService.createTaskQuery()
.includeProcessVariables().active().orderByTaskCreateTime().desc();
// 设置查询条件
if (StringUtils.isNotBlank(act.getAssignee())) {
toClaimQuery.taskAssignee(act.getAssignee());
}
if (StringUtils.isNotBlank(act.getTaskName())) {
toClaimQuery.taskName(act.getTaskName());
}
if (StringUtils.isNotBlank(act.getCandidateUser())){
toClaimQuery.taskCandidateUser(act.getCandidateUser());
}
if (StringUtils.isNotBlank(act.getCandidateGroup())){
toClaimQuery.taskCandidateGroup(act.getCandidateGroup());
}
if (StringUtils.isNotBlank(act.getProcDefKey())){
toClaimQuery.processDefinitionKey(act.getProcDefKey());
}
if (StringUtils.isNotBlank(act.getProcDefId())){
toClaimQuery.processDefinitionId(act.getProcDefId());
}
if (act.getBeginDate() != null){
toClaimQuery.taskCreatedAfter(act.getBeginDate());
}
if (act.getEndDate() != null){
toClaimQuery.taskCreatedBefore(act.getEndDate());
}
// 根据流程变量查询
Map<String,Object> vars = act.getVars();
if (vars != null){
for(Map.Entry<String, Object> entry : vars.entrySet()){
Object v = entry.getValue();
if(null != v && !v.equals("")){
toClaimQuery.processVariableValueEquals(
entry.getKey(), v);
}
}
}
// 查询列表
List<Task> toClaimList = toClaimQuery.listPage(firstResult, maxResults);
for (Task task : toClaimList) {
Activiti e = new Activiti();
e.setTaskId(task.getId());
e.setTaskName(task.getName());
e.setProcInsId(task.getProcessInstanceId());
e.setTaskName(task.getName());
e.setVars(task.getProcessVariables());
e.setStatus("claim");
e.setBeginDate(task.getCreateTime());
result.add(e);
}
return result;
}
流程结合业务封装数据
@Override
public List<FtOrderCheckDetailDto> queryTODOList(Map<String, Object> param) {
Activiti act = new Activiti();
if (param.get("role") != null) {
act.setCandidateGroup(String.valueOf(param.get("role")));
}
if (param.get("openUser") != null) {
act.setAssignee(String.valueOf(param.get("openUser")));
}
act.setProcDefKey("OrderCheck");
act.setTaskName(String.valueOf(param.get("taskName")));
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
try {
String startTime = String.valueOf(param.get("startTime"));
String endTime = String.valueOf(param.get("endTime"));
if (startTime != "null" || startTime.length() > 0) {
act.setBeginDate(sf.parse(startTime));
}
if (endTime != "null" || endTime.length() > 0) {
act.setEndDate(sf.parse(endTime));
}
} catch (Exception e) {
e.printStackTrace();
}
int firstResult = (int)param.get("firstResult");
int maxResults = (int)param.get("pageSize");
List<Activiti> activitis = actTaskService.todoList(firstResult,maxResults,act);
List<FtOrderCheckDetailDto> tasks = new ArrayList<FtOrderCheckDetailDto>();
if (!activitis.isEmpty()) {
for (Activiti acti : activitis) {
FtOrderCheckDetailDto task = new FtOrderCheckDetailDto();
task.setTaskId(acti.getTaskId());
task.setTaskName(acti.getTaskName());
task.setProcessInstanceId(acti.getProcInsId());
task.setStartTime(acti.getBeginDate());
task.setEndTime(acti.getEndDate());
ProcessInstance pi = runtimeService.createProcessInstanceQuery()
.processInstanceId(acti.getProcInsId())
.singleResult();
//获取business_key 获取orderNo
String businessKey = pi.getBusinessKey();
if (StringUtils.isNotBlank(businessKey)) {
//截取字符串,查询投资记录表信息
int index = businessKey.indexOf(".");
String orderNo = businessKey.substring(index+1);
task.setOrderNo(orderNo);
FtCustomerRecordOrder order =
customerRecordOrderMapper.queryByOrderNo(orderNo);
if (order != null) {
task.setCustomerId(order.getCustomerId());
task.setOrderRemark(order.getRemark());
FtMembers members = membersMapper.getMembersByUid(order.getUid());
FtCustomer customer = customerMapper.selectFtCustomerByCustomerId(order.getCustomerId());
FtProductMaster productMaster =
productMasterMapper.queryByProductCode(order.getProductCode());
FtProductEarningsRule productEarningsRule =
productEarningsRuleMapper.selectByPrimaryKey(order.getProductEarningsRuleId());
FtProductSeparateDetail productSeparateDetail
= productSeparateDetailMapper.selectByPrimaryKey(order.getProductSeparateId());
task.setApplyAt(order.getCreateTime());
task.setInvestmentAmount(order.getInvestmentAmount());
task.setActualAmount(order.getActualAmount());
task.setCheckStatus(order.getCheckStatus());
if (members != null) {
task.setUserNmae(members.getUserName());
}
if (customer != null) {
task.setCustomerName(customer.getCustomerName());
}
if (productMaster != null) {
task.setProductName(productMaster.getProductName());
task.setProductCode(productMaster.getProductCode());
}
if (productEarningsRule != null) {
task.setPerformanceBenchmark(productEarningsRule.getPerformanceBenchmark());
}
Calendar c = Calendar.getInstance();
if (productSeparateDetail != null) {
if (productSeparateDetail.getSeparateInterestAt() != null) {
task.setSeparateInterestAt(productSeparateDetail.getSeparateInterestAt());
//计算到期时间 =产品成立时间 + 期限
c.setTime(productSeparateDetail.getSeparateInterestAt());
c.add(Calendar.MONTH, productMaster.getInvestmentDeadline());
Date endTime = c.getTime();
task.setProductEndTime(endTime);
}
}
}
}
tasks.add(task);
}
}
return tasks;
}
获取待办任务的数据都是用的是runtimeService,如果是获取待办历史那么用的就是historyService
5)获取历史审核任务总数
@Override
public int historicCount(Activiti act) {
HistoricTaskInstanceQuery histTaskQuery = historyService.createHistoricTaskInstanceQuery().finished()
.includeProcessVariables().orderByHistoricTaskInstanceEndTime().desc();
// 设置查询条件
if (StringUtils.isNotBlank(act.getTaskName())) {
histTaskQuery.taskName(act.getTaskName());
}
if(StringUtils.isNotBlank(act.getAssignee())){
histTaskQuery.taskAssignee(act.getAssignee());
}
if (StringUtils.isNotBlank(act.getProcDefKey())){
histTaskQuery.processDefinitionKey(act.getProcDefKey());
}
if (StringUtils.isNotBlank(act.getProcDefId())){
histTaskQuery.processDefinitionId(act.getProcDefId());
}
if (act.getBeginDate() != null){
histTaskQuery.taskCompletedAfter(act.getBeginDate());
}
if (act.getEndDate() != null){
histTaskQuery.taskCompletedBefore(act.getEndDate());
}
// 根据流程变量查询
Map<String,Object> vars = act.getVars();
if (vars != null){
for(Map.Entry<String, Object> entry : vars.entrySet()){
Object v = entry.getValue();
if(null != v && !v.equals("")){
histTaskQuery.processVariableValueEquals(
entry.getKey(), v);
}
}
}
return (int) histTaskQuery.count();
}
6)获取历史审核任务分页数据
@Override
public List<Activiti> historicList(int firstResult, int maxResults,
Activiti act) {
HistoricTaskInstanceQuery histTaskQuery = historyService.createHistoricTaskInstanceQuery().finished()
.includeProcessVariables().includeTaskLocalVariables().orderByHistoricTaskInstanceEndTime().desc();
// 设置查询条件
if (StringUtils.isNotBlank(act.getTaskName())) {
histTaskQuery.taskName(act.getTaskName());
}
if(StringUtils.isNotBlank(act.getAssignee())){
histTaskQuery.taskAssignee(act.getAssignee());
}
if(StringUtils.isNotBlank(act.getProcInsId())){
histTaskQuery.processInstanceId(act.getProcInsId());
}
if (StringUtils.isNotBlank(act.getProcDefKey())){
histTaskQuery.processDefinitionKey(act.getProcDefKey());
}
if (StringUtils.isNotBlank(act.getProcDefId())){
histTaskQuery.processDefinitionId(act.getProcDefId());
}
if (act.getBeginDate() != null){
histTaskQuery.taskCompletedAfter(act.getBeginDate());
}
if (act.getEndDate() != null){
histTaskQuery.taskCompletedBefore(act.getEndDate());
}
// 根据流程变量查询
Map<String,Object> vars = act.getVars();
if (vars != null){
for(Map.Entry<String, Object> entry : vars.entrySet()){
Object v = entry.getValue();
if(null != v && !v.equals("")){
histTaskQuery.processVariableValueEquals(
entry.getKey(), v);
}
}
}
// 查询列表
List<HistoricTaskInstance> histList = histTaskQuery.listPage(firstResult, maxResults);
//处理分页问题
List<Activiti> actList = new ArrayList<Activiti>();
for (HistoricTaskInstance histTask : histList) {
Activiti e = new Activiti();
e.setTaskId(histTask.getId());
e.setTaskName(histTask.getName());
e.setAssignee(histTask.getAssignee());
e.setProcInsId(histTask.getProcessInstanceId());
e.setStatus("finish");
e.setBeginDate(histTask.getStartTime());
e.setEndDate(histTask.getEndTime());
// 审批批注
List<Comment> comment = taskService.getTaskComments(histTask.getId());
if(!comment.isEmpty()){
e.setComment(comment.get(0).getFullMessage());
}
// 流程变量
e.setVars(histTask.getProcessVariables());
// 任务变量
List<HistoricVariableInstance> taskVars = historyService
.createHistoricVariableInstanceQuery().taskId(histTask.getId()).list();
Map<String,Object> mTaskVars = new HashMap<String, Object>();
for(HistoricVariableInstance var : taskVars){
mTaskVars.put(var.getVariableName(), var.getValue());
}
e.setTaskVars(mTaskVars);
actList.add(e);
}
return actList;
}
流程集合业务查询分页数据
@Override
public List<FtOrderCheckDetailDto> queryHistoryList(
Map<String, Object> param) {
Activiti act = new Activiti();
act.setAssignee(String.valueOf(param.get("uid")));
act.setProcDefKey("OrderCheck");
act.setTaskName(String.valueOf(param.get("taskName")));
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
try {
String startTime = String.valueOf(param.get("startTime"));
String endTime = String.valueOf(param.get("endTime"));
if (startTime != "null" || startTime.length() > 0) {
act.setBeginDate(sf.parse(startTime));
}
if (endTime != "null" || endTime.length() > 0) {
act.setEndDate(sf.parse(endTime));
}
} catch (Exception e) {
e.printStackTrace();
}
int firstResult = (int)param.get("firstResult");
int maxResults = (int)param.get("pageSize");
List<Activiti> activitis = actTaskService.historicList(firstResult,maxResults,act);
List<FtOrderCheckDetailDto> tasks = new ArrayList<FtOrderCheckDetailDto>();
if (!activitis.isEmpty()) {
for (Activiti acti : activitis) {
FtOrderCheckDetailDto task = new FtOrderCheckDetailDto();
task.setTaskId(acti.getTaskId());
task.setTaskName(acti.getTaskName());
task.setProcessInstanceId(acti.getProcInsId());
task.setStartTime(acti.getBeginDate());
task.setEndTime(acti.getEndDate());
FtOrderCheckDetail result = mapper.queryByTaskId(acti.getTaskId());
if (result != null) {
task.setType(result.getType());
task.setHandler(result.getHandler());
task.setRemark(result.getRemark());
task.setDisposeAt(result.getDisposeAt());
}
ProcessInstanceHistoryLog pi = historyService
.createProcessInstanceHistoryLogQuery(acti.getProcInsId())
.singleResult();
/*ProcessInstance pi = runtimeService.createProcessInstanceQuery()
.processInstanceId(acti.getProcInsId())
.singleResult();*/
//获取business_key
if (pi != null) {
String businessKey = pi.getBusinessKey();
if (StringUtils.isNotBlank(businessKey)) {
//截取字符串,查询投资记录表信息
int index = businessKey.indexOf(".");
String orderNo = businessKey.substring(index+1);
task.setOrderNo(orderNo);
FtCustomerRecordOrder order =
customerRecordOrderMapper.queryHistoryByOrderNo(orderNo);
if (order != null) {
FtMembers members = membersMapper.getMembersByUid(order.getUid());
FtProductMaster productMaster =
productMasterMapper.queryHistoryByProductCode(order.getProductCode());
task.setCustomerId(order.getCustomerId());
task.setUserNmae(members.getUserName());
task.setCustomerName("");
task.setApplyAt(order.getCreateTime());
task.setProductName(productMaster.getProductName());
task.setInvestmentAmount(order.getInvestmentAmount());
task.setActualAmount(order.getActualAmount());
}
}
}
tasks.add(task);
}
}
return tasks;
}
以上就是博主学习运用activiti的所有干货,希望能帮助到有需要的童鞋~~