BOS项目笔记第11天
内容:
1、提供新的json文件,修改系统菜单(加入工作流的菜单)
2、流程定义管理(查询、部署流程、查看png流程图片)
3、流程实例管理(查询、查看运行状态)
4、将bos系统中的用户数据和角色数据同步到activiti的用户表和组表
1. 提供新的json文件,修改系统菜单(加入工作流的菜单)
2. 流程定义管理
第一步:创建一个ProcessDefinitionAction,提供list方法,并注入流程引擎对象
查询
@Controller @Scope("prototype") public class ProcessDefinitionAction extends ActionSupport { @Resource private ProcessEngine processEngine; /** * 查询最新版本的流程定义列表数据 */ public String list() { ProcessDefinitionQuery query = processEngine.getRepositoryService() .createProcessDefinitionQuery(); query.latestVersion(); List<ProcessDefinition> list = query.list(); // 压栈 ActionContext.getContext().getValueStack().set("list", list); return "list"; }
第二步:配置struts.xml
第三步:提供processdefinition_list.jsp页面,展示流程定义数据
<body class="easyui-layout"> <div region="center" > <table id="grid" class="easyui-datagrid"> <thead> <tr> <th data-options="field:'id'" width="120">流程编号</th> <th data-options="field:'name'" width="200">流程名称</th> <th data-options="field:'key'" width="100">流程key</th> <th data-options="field:'version'" width="80">版本号</th> <th data-options="field:'viewpng'" width="200">查看流程图</th> </tr> </thead> <tbody> <s:iterator value="list" var="processDefinition"> <!-- 在循环过程中 ,将 processDefinition 对象,同时放入 root 和 map 中--> <tr> <td> <s:property value="id"/> <!-- 从root找 --> <%-- <s:property value="#processDefinition.id"/> <!-- 从map找 --> --%> </td> <td><s:property value="name"/> </td> <td><s:property value="key"/></td> <td><s:property value="version"/></td> <td> <a onclick="window.showModalDialog('processDefinitionAction_showpng.action?pdId=${id }')" class="easyui-linkbutton" data-options="iconCls:'icon-search'">查看流程图 </a> </td> </tr> </s:iterator> </tbody> </table> </div>
2.1 部署流程定义
第一步:提供文件上传的页面
<s:form action="processDefinitionAction_deploy" theme="simple" method="post" enctype="multipart/form-data" id="uploadForm"> <table class="table-edit" width="100%" > <tr class="title"><td colspan="2">发布新流程</td></tr> <tr> <td width="200">浏览流程定义zip压缩文件</td> <td> <input type="file" name="deploy" /> </td> </tr> <tr> <td colspan="2"> <a id="btn" href="javascript:$('#uploadForm').submit();" class="easyui-linkbutton" data-options="iconCls:'icon-save'">发布新流程</a> </td> </tr> </table> </s:form>
第二步:在ProcessDefinitionAction中提供deploy方法,提供File类型的属性deploy
// 接收上传的文件 private File deploy;// zip文件 public void setDeploy(File deploy) { this.deploy = deploy; } /** * 部署流程定义 * * @throws Exception */ public String deploy() throws Exception { DeploymentBuilder deploymentBuilder = processEngine .getRepositoryService().createDeployment(); ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream( deploy)); deploymentBuilder.addZipInputStream(zipInputStream); deploymentBuilder.deploy(); return "toList"; }
第三步:配置struts.xml
2.2 查看流程图片
第一步:修改processdefintion_list.jsp页面中链接按钮的地址
<a onclick="window.showModalDialog('processDefinitionAction_showpng.action?pdId=${id }')" class="easyui-linkbutton" data-options="iconCls:'icon-search'">查看流程图 </a>
第二步:在Action中提供showpng方法,获取对应的png图片的输入流
//接收流程定义ID private String pdId; public void setPdId(String pdId) { this.pdId = pdId; } /** * 查看png图片 */ public String showpng(){ //processEngine.getRepositoryService().getResourceAsStream(deploymentId, resourceName); InputStream pngStream = processEngine.getRepositoryService().getProcessDiagram(pdId); ActionContext.getContext().getValueStack().set("pngStream", pngStream); //使用struts2的文件下载功能展示png图片 return "showpng"; }
第三步:配置struts.xml
<!-- 流程定义管理Action --> <action name="processDefinitionAction_*" class="processDefinitionAction" method="{1}"> <result name="list">/WEB-INF/pages/workflow/processdefinition_list.jsp </result> <!-- <result name="toList" type="redirectAction"> <param name="namespace">/</param> <param name="actionName">processDefinitionAction_list</param> </result> --> <result name="toList" type="redirectAction"> processDefinitionAction_list </result> <result name="showpng" type="stream"> <param name="contentType">image/png</param> <param name="inputName">pngStream</param> <!-- <param name="contentDisposition">attachment;filename="document.pdf"</param> <param name="bufferSize">1024</param> --> </result> </action>
3. 流程实例管理
3.1 查看正在运行的流程实例
第一步:创建ProcessInstanceAction,提供list方法,查询流程实例列表数据
@Controller @Scope("prototype") public class ProcessInstanceAction extends ActionSupport { @Autowired private ProcessEngine processEngine; /** * 查询正在运行的流程实例数据 */ public String list() { // 流程实例查询对象,查询表act_ru_execution ProcessInstanceQuery query = processEngine.getRuntimeService() .createProcessInstanceQuery(); query.orderByProcessDefinitionKey().desc(); List<ProcessInstance> list = query.list(); ActionContext.getContext().getValueStack().set("list", list); return "list"; }
第二步:配置struts.xml
第三步:提供processinstance_list.jsp页面,展示列表数据
<body class="easyui-layout"> <div region="center"> <table id="grid" class="easyui-datagrid"> <thead> <tr> <th data-options="field:'id'" width="60">实例编号</th> <th data-options="field:'name'" width="150">流程定义编号</th> <th data-options="field:'activity'" width="150">运行到哪个任务</th> <th data-options="field:'viewRuntime'" width="500">业务数据</th> <th data-options="field:'viewpng'" width="200">查看流程图</th> </tr> </thead> <tbody> <s:iterator value="list"> <tr> <td>${id }</td> <td>${processDefinitionId }</td> <td>${activityId }</td> <td> <div id="div${id }"></div> <script type="text/javascript"> //根据流程实例id查询流程变量 $.post("${pageContext.request.contextPath}/processInstanceAction_findData.action",{"id":'${id}'},function(data){ $("#div${id}").html(data); }); </script> </td> <td> <script type="text/javascript"> function showPng(id){ window.showModalDialog("processInstanceAction_showPng.action?id="+id); } </script> <a data-options="iconCls:'icon-search'" class="easyui-linkbutton" onclick="showPng('${id}');" href="#">查看流程图</a> </td> </tr> </s:iterator> </tbody> </table> </div> </body>
第四步:在Action中提供findData方法,根据流程实例ID查询对应的流程变量
// 接收流程实例ID private String id; public void setId(String id) { this.id = id; } /** * 根据流程实例ID查询流程变量 * * @throws IOException */ public String findData() throws IOException { Map<String, Object> variables = processEngine.getRuntimeService() .getVariables(id); ServletActionContext.getResponse().setContentType( "text/html;charset=UTF-8"); ServletActionContext.getResponse().getWriter().print(variables); return NONE; }
3.2 查询流程实例运行状态(图片显示)
第一步:在流程实例列表页面,修改链接按钮的地址
效果
第二步:在Action中提供showPng方法,查询部署ID,图片名称,任务坐标
/** * 流程任务获取图片数据 * * @return */ public String showPng() { // 通过流程实例获取流程定义id ProcessInstance processInstance = processEngine.getRuntimeService() .createProcessInstanceQuery().processInstanceId(id) .singleResult(); String processDefinitionId = processInstance.getProcessDefinitionId(); // 通过流程定义id获取流程定义对象,然后获取部署id和图片名称 ProcessDefinition processDefinition = processEngine .getRepositoryService().createProcessDefinitionQuery() .processDefinitionId(processDefinitionId).singleResult(); String deploymentId = processDefinition.getDeploymentId(); String imageName = processDefinition.getDiagramResourceName(); // 通过流程定义id获取详细(包含坐标)的流程定义对象 ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) processEngine .getRepositoryService().getProcessDefinition( processDefinitionId); String activityId = processInstance.getActivityId(); //通过活动id获取活动(当前任务)对象 ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId); //获取图片参数 int x = activityImpl.getX(); int y = activityImpl.getY(); int height = activityImpl.getHeight(); int width = activityImpl.getWidth(); //把所有参数都放到值栈 Map<String,Object> map=new HashMap<String, Object>(); map.put("deploymentId", deploymentId); map.put("imageName", imageName); map.put("x", x); map.put("y", y); map.put("height", height); map.put("width", width); ActionContext.getContext().getValueStack().push(map); return "image"; }
提取工具类:ActivitiUtils
public class ActivitiUtils { public static Map<String, Object> findDataByInstanceId( ProcessEngine processEngine, String id) { // 查询部署ID、png图片名称、当前流程任务的坐标 ProcessInstanceQuery query = processEngine.getRuntimeService() .createProcessInstanceQuery(); // 根据流程实例ID查询流程实例对象 query.processInstanceId(id); ProcessInstance processInstance = query.singleResult(); // 根据流程实例对象查询流程定义ID String processDefinitionId = processInstance.getProcessDefinitionId(); // 根据流程定义ID查询流程定义对象 ProcessDefinitionQuery query2 = processEngine.getRepositoryService() .createProcessDefinitionQuery(); query2.processDefinitionId(processDefinitionId); ProcessDefinition processDefinition = query2.singleResult(); // 获得当前流程实例执行到那个任务了 String activityId = processInstance.getActivityId();// usertask2 // 根据流程定义ID查询流程定义对象(包含有坐标信息) ProcessDefinitionEntity processDefinition2 = (ProcessDefinitionEntity) processEngine .getRepositoryService().getProcessDefinition( processDefinitionId); ActivityImpl activityImpl = processDefinition2.findActivity(activityId); int x = activityImpl.getX(); int y = activityImpl.getY(); int width = activityImpl.getWidth(); int height = activityImpl.getHeight(); Map<String, Object> map = new HashMap<String, Object>(); map.put("deploymentId", processDefinition.getDeploymentId()); map.put("imageName", processDefinition.getDiagramResourceName()); map.put("x", x); map.put("y", y); map.put("width", width); map.put("height", height); return map; } }
第三步:配置struts.xml
第四步:提供image.jsp页面,展示图片和div
<body> <!-- 1.获取到规则流程图 --> <img style="position: absolute;top: 0px;left: 0px;" src="processInstanceAction_viewImage?deploymentId=${deploymentId }&imageName=${imageName}"> <!-- 2.根据当前活动的坐标,动态绘制DIV --> <div style="position: absolute;border:1px solid red; top:${y-1}px;left:${x-1}px;width:${width}px;height:${height}px;"> </div> </body>
第五步:在Action中提供viewImage方法,查询png图片的输入流
//接收图片src传递过来的参数 String deploymentId; String imageName; public void setDeploymentId(String deploymentId) { this.deploymentId = deploymentId; } public void setImageName(String imageName) { this.imageName = imageName; } /** * 查询png图片的输入流,展示图片 */ public String viewImage() { InputStream pngStream = processEngine.getRepositoryService() .getResourceAsStream(deploymentId, imageName); ActionContext.getContext().getValueStack().set("pngStream", pngStream); return "viewImage"; }
第六步:配置struts.xml,使用文件下载
<!-- 流程实例管理Action --> <action name="processInstanceAction_*" class="processInstanceAction" method="{1}"> <result name="list">/WEB-INF/pages/workflow/processinstance_list.jsp</result> <result name="showPng">//WEB-INF/pages/workflow/image.jsp</result> <result name="viewImage" type="stream"> <param name="contentType">image/png</param> <param name="inputName">pngStream</param> </result> </action>
4. 将bos系统中的用户和组同步到activiti中
同步用户
//添加用户,同步到activiti的act_id_user act_id_mebership public void save(User user, String[] roleIds) { String password = user.getPassword(); //使用md5加密 password = MD5Utils.md5(password); user.setPassword(password); userDao.save(user);//持久对象 //添加activiti UserEntity org.activiti.engine.identity.User actUser = new UserEntity(); actUser.setId(user.getId()); processEngine.getIdentityService().saveUser(actUser);//操作act_id_user for (String id : roleIds) { Role role = roleDao.findById(id); //用户关联角色 user.getRoles().add(role); //将ac用户加入到ac组中 role.getName()使用角色名字做为组ID方便阅读 processEngine.getIdentityService().createMembership(actUser.getId(), role.getName()); } }
同步组
//保存角色,同步到activiti的act_id_group public void save(Role model, String funcitonIds) { roleDao.save(model);//持久对象 //创建ac组并添加 Group group = new GroupEntity(); group.setId(model.getName()); group.setName(model.getName()); processEngine.getIdentityService().saveGroup(group ); String[] ids = funcitonIds.split(","); for (String id : ids) { Function function = new Function(); function.setId(id); model.getFunctions().add(function);//角色关联权限 } }