1.获得流程图乱码问题
修改源码
org.activiti.engine.impl.bpmn.diagram.ProcessDiagramCanvas
在构造方法
public ProcessDiagramCanvas(int width, int height)
中有一行代码是设置字体的,默认是用Arial字体,这就是乱码产生的原因,把字改为本地的中文字体即可,例如:
Font font = new Font("WenQuanYi Micro Hei", Font.BOLD, 11);
从5.12版本开始支持设置字体名称,在引擎中添加如下设置,在生成图片时即可使用微软雅黑设置图片中的文字。
<property name="activityFontName" value="微软雅黑"></property>
2.业务和流程的关联方式
runtimeService.startProcessInstanceByKey
javadoc对其说明:
startProcessInstanceByKey(String processDefinitionKey, Map variables)
Starts a new process instance in the latest version of the process definition with the given key
其中businessKey就是业务ID,例如要申请请假,那么先填写登记信息,然后(保存+启动流程),因为请假是单独设计的数据表,所以保存后得到实体ID就可以把它传给processInstanceBusinessKey方法启动流程。当需要根据businessKey查询流程的时候就可以通过API查询:
runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(processInstanceBusinessKey, processDefinitionKey)
建议数据库冗余设计:在业务表设计的时候添加一列:PROCESS_INSTANCE_ID varchar2(64),在流程启动之后把流程ID更新到业务表中,这样不管从业务还是流程都可以查询到对方!
特别说明: 此方法启动时自动选择最新版本的流程定义。
runtimeService.startProcessInstanceById
javadoc对其说明:
startProcessInstanceById(String processDefinitionId, String businessKey, Map variables)
Starts a new process instance in the exactly specified version of the process definition with the given id.
processDefinitionId:这个参数的值可以通过repositoryService.createProcessDefinitionQuery()方法查询,对应数据库:ACT_RE_PROCDEF;每次部署一次流程定义就会添加一条数据,同名的版本号累加。
特别说明: 此可以指定不同版本的流程定义,让用户多一层选择。
建议使用
startProcessInstanceByKey,特殊情况需要使用以往的版本选择使用startProcessInstanceById。
3.各种状态的任务查询以及和业务对象关联
我们目前分为4中状态:未签收、办理中、运行中、已完成。
3.1未签收(Task)
此类任务针对于把Task分配给一个角色时,例如部门领导,因为部门领导角色可以指定多个人所以需要先签收再办理,术语:抢占式
对应的API查询:
/**
* 获取未签收的任务查询对象
* @param userId 用户ID
*/
@Transactional(readOnly = true)
public TaskQuery createUnsignedTaskQuery(String userId) {
TaskQuery taskCandidateUserQuery = taskService.createTaskQuery().processDefinitionKey(getProcessDefKey())
.taskCandidateUser(userId);
return taskCandidateUserQuery;
}
3.2 办理中(Task)
此类任务数据类源有两种:
签收后的,5.1中签收后就应该为办理中状态
节点指定的是具体到一个人,而不是角色
对应的API查询:
/**
* 获取正在处理的任务查询对象
* @param userId 用户ID
*/
@Transactional(readOnly = true)
public TaskQuery createTodoTaskQuery(String userId) {
TaskQuery taskAssigneeQuery = taskService.createTaskQuery().processDefinitionKey(getProcessDefKey()).taskAssignee(userId);
return taskAssigneeQuery;
}
3.3 运行中(ProcessInstance)
说白了就是没有结束的流程,所有参与过的人都应该可以看到这个实例,但是Activiti的API没有可以通过用户查询的方法,这个只能自己用hack的方式处理了,我目前还没有处理。
从表ACT_RU_EXECUTION中查询数据。
对应的API查询:
/**
* 获取未经完成的流程实例查询对象
* @param userId 用户ID
*/
@Transactional(readOnly = true)
public ProcessInstanceQuery createUnFinishedProcessInstanceQuery(String userId) {
ProcessInstanceQuery unfinishedQuery = runtimeService.createProcessInstanceQuery().processDefinitionKey(getProcessDefKey())
.active();
return unfinishedQuery;
}
3.4 已完成(HistoricProcessInstance)
已经结束的流程实例。
从表ACT_HI_PROCINST中查询数据。
/**
* 获取已经完成的流程实例查询对象
* @param userId 用户ID
*/
@Transactional(readOnly = true)
public HistoricProcessInstanceQuery createFinishedProcessInstanceQuery(String userId) {
HistoricProcessInstanceQuery finishedQuery = historyService.createHistoricProcessInstanceQuery()
.processDefinitionKey(getProcessDefKey()).finished();
return finishedQuery;
}
4.任务委派
activiti默认是不带有选人的功能的,它默认的是在调用complete 方法的时候自动根据下一个节点的 assignee属性或者candidate属性 设置下一节点的候选人或者 assginee。
package org.activiti.designer.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.util.HashMap;
import java.util.Map;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.DelegationState;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.engine.test.Deployment;
import org.junit.Rule;
import org.junit.Test;
/**
* 任务委派
*
* @author henryyan
*/
public class ProcessTestDelegateTask {
@Rule
public ActivitiRule activitiRule = new ActivitiRule();
@Test
@Deployment(resources = { "diagrams/AutoAssignee.bpmn" })
public void startProcess() throws Exception {
RuntimeService runtimeService = activitiRule.getRuntimeService();
Map<String, Object> variableMap = new HashMap<String, Object>();
variableMap.put("name", "Activiti");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("AutoAssignee", variableMap);
assertNotNull(processInstance.getId());
System.out.println("id " + processInstance.getId() + " " + processInstance.getProcessDefinitionId());
TaskService taskService = activitiRule.getTaskService();
Task task = taskService.createTaskQuery().singleResult();
assertNull(task.getAssignee());
// 签收
taskService.claim(task.getId(), "user1");
task = taskService.createTaskQuery().singleResult();
assertNotNull(task.getAssignee());
// 委派
taskService.delegateTask(task.getId(), "henryyan");
// 查询被委派的任务
task = taskService.createTaskQuery().taskAssignee("henryyan").taskDelegationState(DelegationState.PENDING).singleResult();
assertNotNull(task);
// 被委派人完成任务
taskService.resolveTask(task.getId());
// 查询已完成的委派任务
task = taskService.createTaskQuery().taskDelegationState(DelegationState.RESOLVED).singleResult();
assertNotNull(task);
assertEquals("user1", task.getAssignee());
assertEquals("user1", task.getOwner());
// taskService.complete(task.getId(), Collections.singletonMap("taskTwoAssignee", "user2"));
}
}
同样也可以用TaskListener来实现
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.TaskListener;
import org.apache.ibatis.annotations.Delete;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TaskUserQuery implements TaskListener{
/**
*
*/
private static final long serialVersionUID = 1L;
private static Logger logger = LoggerFactory.getLogger(TaskUserQuery.class);
protected DataSource dataSource;
private org.activiti.engine.impl.el.FixedValue orgLevel ;
private org.activiti.engine.impl.el.FixedValue dutyNo ;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 审批过程中找人的方法
* @param str 组名
* @return
* @throws SQLException
*/
public String getTaskUser(String str) throws SQLException {
logger.debug("-------------------自定义找人----------------------------getTaskUser");
Connection conn = dataSource.getConnection();
Statement state = conn.createStatement();
String queryTaskUserSql = "select id_ from act_id_user aiu where exists (select 1 from act_id_membership aim where aim.user_id_ = aiu.id_ and aim.group_id_='"+str+"' )";
ResultSet rs = state.executeQuery(queryTaskUserSql);
rs.next();
logger.debug("-------------------自定义找人----------------------------:返回的人是"+rs.getString(1));
conn.close();
state.close();
return rs.getString(1);
}
public List<String> getTaskUserList(String str) throws SQLException {
logger.debug("-------------------自定义找人----------------------------getTaskUserList");
List<String> taskUser = new ArrayList<String>();
Connection conn = dataSource.getConnection();
Statement state = conn.createStatement();
String queryTaskUserSql = "select id_ from act_id_user aiu where exists (select 1 from act_id_membership aim where aim.user_id_ = aiu.id_ and aim.group_id_='"+str+"' )";
ResultSet rs = state.executeQuery(queryTaskUserSql);
while(rs.next()) {
taskUser.add(rs.getString(1));
}
logger.debug("------------------- 自定义找人----------------------------:返回的人是"+taskUser.toString());
conn.close();
state.close();
return taskUser;
}
@Override
public void notify(DelegateTask delegateTask) {
Map<String,Object> map = delegateTask.getVariables();
String taskId = delegateTask.getId();
System.out.println("in taskUserQuer class variable is:"+map.toString());
System.out.println("in taskUserQuer class taskid is:"+taskId);
System.out.println("in taskUserQuer class orgLevel is:"+orgLevel.getExpressionText());
String id = delegateTask.getId();
String s = delegateTask.getAssignee();
//根据流程变量的内容设置下一个节点的审批人
delegateTask.setAssignee(map.get("nextUser").toString());
Map<String,Object> m1 = delegateTask.getExecution().getVariables();
Map<String,Object> m2 = delegateTask.getVariablesLocal();
// logger.debug("-----------------------------------------id is:"+id);
// // logger.debug("-----------------------------------------arg is:"+dutyNo.getExpressionText());
// delegateTask.setAssignee(dutyNo.getExpressionText());
// TODO Auto-generated method stub
// logger.debug("----------------------设置选人 开始--------------------------");
// delegateTask.setAssignee("admin");
// logger.debug("----------------------设置选人 结束--------------------------");
}
}