目录
1、流程实例管理
1.1、查询流程实例
1.2、查询流程实例运行状态
2、将bos系统中的用户和角色同步到activiti框架的用户表和组表中去
2.1、将角色同步到 act_id_group 表中去
2.2、将用户同步到 act_id_user 表中去
3、设计物流配送流程
4、启动物流配送流程
4.1、查询工作单列表数据
4.2、根据key启动流程实例
5、组任务操作
5.1、查询组任务
5.2、拾取组任务
6、个人任务操作
6.1、查询个人任务
6.2、办理个人任务
今天内容安排:
1、流程实例管理(查询流程实例、查看流程实例运行状态)
2、将bos系统中的用户和角色同步到activiti框架的用户表和组表中去
3、设计物流配送流程
4、启动物流配送流程
5、组任务操作(查询、拾取)
6、个人任务操作(查询、办理)
回到顶部
1、流程实例管理
1.1、查询流程实例
第一步:创建一个流程实例管理ProcessInstanceAction,提供list()方法,查询流程实例列表数据
// 注入Service
@Autowired
private RuntimeService runtimeService;
/**
* 查询流程实例(同步)
* @return
*/
public String list() {
// 创建流程实例查询对象
ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery();
query.orderByProcessInstanceId().desc(); // 根据流程实例id排序,降序
List
list = query.list(); // 执行查询,获得流程实例列表数据
// 将流程实例列表数据压入值栈中
ActionContext.getContext().getValueStack().set("list", list);
return "list";
}
第二步:配置struts.xml
/WEB-INF/pages/workflow/processinstance.jsp
第三步:提供processinstance.jsp页面,展示列表数据
| ${id} |
${processDefinitionId} |
${activityId} |
|
查看流程图
|
第四步:在ProcessInstanceAction中提供findData()的方法,根据流程实例id查询对应的流程变量数据(ajax)
// 接收页面提交过来的参数:流程实例id
private String id;
public void setId(String id) {
this.id = id;
}
/**
* 根据流程实例id查询对应的流程变量数据(ajax)
* @return
* @throws IOException
*/
public String findData() throws IOException {
Map variables = runtimeService.getVariables(id);
ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");
ServletActionContext.getResponse().getWriter().print(variables.toString());
return "none";
}
浏览器效果如下图所示:
1.2、查询流程实例运行状态
第一步:为“查看流程图”按钮绑定事件,注意:点击查看流程图按钮,实际上发起了2次请求
第二步:在ProcessInstanceAction中提供showPng()方法,根据流程实例id获取部署id、图片名称、图片坐标
/**
* 根据流程实例id获取部署id、图片名称、图片坐标
*
* @return
*/
public String showPng() {
// 1、根据流程实例id创建流程实例查询对象
ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery();
query.processInstanceId(id); // 根据流程实例id过滤
ProcessInstance processInstance = query.singleResult(); // 得到流程实例对象
// 2、根据流程实例对象获取流程定义id
String processDefinitionId = processInstance.getProcessDefinitionId();
// 3、根据流程定义id创建流程定义查询对象 --> 根据流程定义id过滤 --> 得到流程定义对象(链式编程),注意:此方式只查询了流程定义表act_re_procdef
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
// 4、根据流程定义对象获取部署id
deploymentId = processDefinition.getDeploymentId();
// 5、根据流程定义对象获取图片名称
imageName = processDefinition.getDiagramResourceName();
// 把部署id和图片名称压入值栈后,在image.jsp页面就可以正常获取出来这两个参数,取出来之后该页面又请求新的地址,新的地址又把这两个参数提交过来,我们在Action中又需要接收(设置)这两个参数,是不是有些麻烦呢?
// 所以针对这种情况,我们需要把部署id和图片名称由局部变量提升为成员变量,并且提供getter和setter方法,终于这两个方法都能用着啦!getter方法用于页面EL表达式获取参数,setter方法用于接收页面提交回来的参数。
// 因为成员变量本身就在struts的值栈里面,因为struts框架本身将Action对象压入值栈中。
// 获取坐标
// 1、获取当前流程实例执行到哪个节点了
String activityId = processInstance.getActivityId(); // usertask1
// 2、加载bpmn(xml)文件,获得一个流程定义对象,注意:此方式不仅查询了流程定义表act_re_procdef,还查询了act_ge_bytearray
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
// 使用流程定义对象的实现类,该实现类里面扩展了很多方法,其中就包括关于坐标的
// 3、根据activityId获取含有坐标信息的对象
ActivityImpl findActivity = processDefinitionEntity.findActivity(activityId);
int x = findActivity.getX();
int y = findActivity.getY();
int width = findActivity.getWidth();
int height = findActivity.getHeight();
// 将坐标信息压入值栈中
ActionContext.getContext().getValueStack().set("x", x);
ActionContext.getContext().getValueStack().set("y", y);
ActionContext.getContext().getValueStack().set("width", width);
ActionContext.getContext().getValueStack().set("height", height);
return "showPng";
}
第三步:配置struts.xml,跳转到image.jsp页面
/WEB-INF/pages/workflow/image.jsp
第四步:提供image.jsp页面
第五步:在ProcessInstanceAction中提供viewImage()方法,根据部署id和图片名称获得对应的输入流
/**
* 根据部署id和图片名称获取对应的png输入流
* @return
*/
public String viewImage() {
// 获取png图片对应的输入流
InputStream pngStream = repositoryService.getResourceAsStream(deploymentId, imageName);
// 使用Struts框架提供的文件下载功能(文件下载结果集):通过输出流把服务端的资源写到客户端
// 先把输入流压入值栈,再到页面把流读出来即可
ActionContext.getContext().getValueStack().set("pngStream", pngStream);
return "viewImage";
}
第六步:配置struts.xml
image/png
pngStream
浏览器效果如下图所示:
回到顶部
2、将bos系统中的用户和角色同步到activiti框架的用户表和组表中去
2.1、将角色同步到 act_id_group 表中去
修改RoleServiceImpl中的save()方法,如下图所示:
2.2、将用户同步到 act_id_user 表中去
注意:我们在添加用户的时候会选择角色,在activiti框架中对应的是用户表关联组表。
修改UserServiceImpl的save()方法,如下图所示:
回到顶部
3、设计物流配送流程
流程定义的id:
使用排他网关:
使用组任务:
任务的id(对应Action中的方法名):
回到顶部
4、启动物流配送流程
准备工作:
修改工作单类
修改工作单对应的hbm映射文件
为了和我们之前的命名规则一致,修改数据库表auth_function中的“启动配送流程”中的page属性的值为workordermanageAction_list.action
4.1、查询工作单列表数据
第一步:在工作单管理Action中提供list()方法,查询流程状态start为0的工作单(即未启动的工作单)
/**
* 查询流程状态start为0的工作单(即未启动的工作单)
* @return
*/
public String list() {
List list = workordermanageService.findListNotStart();
ActionContext.getContext().getValueStack().set("list", list); // 将查询到的结果压栈
return "list";
}
Service层代码:
/**
* 查询流程状态start为0的工作单(即未启动的工作单)
*/
public List findListNotStart() {
// 创建离线条件查询对象
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Workordermanage.class);
// 向离线条件查询对象中封装查询条件
detachedCriteria.add(Restrictions.eq("start", "0"));
return workordermanageDao.findByCriteria(detachedCriteria );
}
第二步:配置struts.xml
/WEB-INF/pages/workflow/startransfer.jsp
第三步:提供startransfer.jsp页面,展示工作单列表数据
浏览器显示效果:
4.2、根据key启动流程实例
第一步:修改列表页面中“启动按钮”绑定事件
启动
|
第二步:在工作单Action中提供start()方法,启动物流配送流程对应的流程实例
注意:“修改工作单中的start值为1,启动流程实例,设置流程变量”为多个数据库表的操作,所以尽量不要在Action中写这么复杂的逻辑,为什么呢?
答:建议写在service里面去,因为涉及到多个数据库表的操作,这样可以保证事务控制。
/**
* 启动物流配送流程
* @return
*/
public String start() {
// 获取工作单id
String id = model.getId();
// 注意:“修改工作单中的start值为1,启动流程实例,设置流程变量”为多个数据库表的操作,所以尽量不要在Action中写这么复杂的逻辑,为什么呢?
// 答:建议写在service里面去,因为涉及到多个数据库表的操作,这样可以保证事务控制。
// 启动流程实例
workordermanageService.start(id);
return "toList";
}
第三步:在工作单Service中提供start()方法,实现数据库操作
/**
* 修改工作单中的start值为1,设置流程变量,启动流程实例
*/
public void start(String workorderId) {
// 修改工作单中的start值为1
Workordermanage workordermanage = workordermanageDao.findById(workorderId);
workordermanage.setStart("1");
// 设置流程变量
String processDefinitionKey = "transfer"; // 流程定义key == 画图时给图起的id,这个不需要查询数据库,为已知数据
String businessKey = workorderId; // 业务主键 == 业务表(工作单)的主键值,因为实际当中携带的数据往往是业务表中数据 ==> 业务主键存在实例流程表中,工作流框架通过业务主键可以找到业务数据
Map variables = new HashMap(); // 流程变量
variables.put("业务数据", workordermanage); // 我们在流程变量里面也存一份业务数据,就是说,“业务数据”我可以存在业务主键中,也可以存在流程变量中
// 启动流程实例
runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
}
如下图所示:
回到顶部
5、组任务操作
5.1、查询组任务
第一步:创建一个TaskAction类,提供查询组任务的方法findGroupTask()
@Autowired
private TaskService taskService;
/**
* 查询组任务
* @return
*/
public String findGroupTask() {
// 创建任务查询对象
TaskQuery query = taskService.createTaskQuery();
String candidateUser = BOSContext.getLoginUser().getId(); // 获取当前登录用户的id
query.taskCandidateUser(candidateUser); // 根据组任务过滤,即根据候选人过滤
List list = query.list(); // 执行查询,获得任务列表数据
// 将任务列表数据压入值栈中
ActionContext.getContext().getValueStack().set("list", list);
return "grouptasklist";
}
第二步:配置struts.xml
/WEB-INF/pages/workflow/grouptask.jsp
第三步:提供grouptask.jsp页面,展示任务列表数据
第三步:在任务Action中,提供显示业务数据的方法showData()
// 接收页面提交过来的参数:任务id
private String taskId;
public void setTaskId(String taskId) {
this.taskId = taskId;
}
/**
* 根据任务id查询对应的流程变量数据(ajax)
* @return
* @throws IOException
*/
public String showData() throws IOException {
Map variables = taskService.getVariables(taskId);
ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");
ServletActionContext.getResponse().getWriter().print(variables.toString());
return "none";
}
浏览器显示效果:
5.2、拾取组任务
第一步:修改jsp页面中“拾取按钮”事件
拾取
|
第二步:在TaskAction中提供拾取任务的方法takeTask()
/**
* 拾取组任务
* @return
*/
public String takeTask() {
String userId = BOSContext.getLoginUser().getId(); // 获取当前登录用户的id
taskService.claim(taskId, userId);
return "togrouptasklist";
}
第三步:配置struts.xml
/WEB-INF/pages/workflow/grouptask.jsp
taskAction_findGroupTask
回到顶部
6、个人任务操作
6.1、查询个人任务
第一步:在TaskAction中提供findPersonalTask()方法,查询当前登录用户的个人任务
/**
* 查询个人任务
*/
public String findPersonalTask() {
// 创建任务查询对象
TaskQuery query = taskService.createTaskQuery();
String assignee = BOSContext.getLoginUser().getId(); // 获取当前登录用户的id
query.taskAssignee(assignee); // 根据个人任务过滤
List list = query.list(); // 执行查询,获得任务列表数据
// 将任务列表数据压入值栈中
ActionContext.getContext().getValueStack().set("list", list);
return "personaltasklist";
}
第二步:配置struts.xml
/WEB-INF/pages/workflow/personaltask.jsp
第三步:提供personaltask.jsp页面,展示个人任务列表数据
图片同查询组任务中的第三步。
浏览器显示效果:
6.2、办理个人任务
6.2.1、办理审核工作单任务
第一步:修改personaltask.jsp页面中“办理任务”按钮的事件
第二步:在TaskAction中提供checkWorkOrderManage()方法,办理审核工作单任务
// 接收页面提交过来的参数:check
// 审核结果:1 表示审核通过,0表示审核不通过
private Integer check;
public Integer getCheck() {
return check;
}
public void setCheck(Integer check) {
this.check = check;
}
/**
* 办理审核工作单任务(实际上是跳转到审核工作单页面 + 真正办理审核工作单任务)
*/
public String checkWorkOrderManage() {
// 根据传递过来的任务id获取任务对象(任务查询对象 --> 根据任务id过滤 --> 任务对象)
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
// 根据任务对象获取流程实例id
String processInstanceId = task.getProcessInstanceId();
// 根据流程实例id获取流程实例对象
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
String workorderId = processInstance.getBusinessKey(); // 业务主键 ==