activiti5入门(三)

activiti的war包要跑起来,tomcat的目录中不能有汉字!!

流程定义部署(流程部署和流程定义):

用到RepositoryService: 仓储服务对象。

流程定义部署我们使用war包形式上传,所以用的是输入流的方式。以简单的servlet为例:

前台主要部分:

<form action="deploy.action" method="post" enctype="multipart/form-data">
请选择流程定义文件:<input type="file" name="bpmn"/>
<input type="submit" value="上传"/>
</form>

后台servlet:

@WebServlet("/deploy.do")
@MultipartConfig
public class UploadBpmn extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取请求参数(文件上传)
Part part = request.getPart("bpmn");//bpmn是前台表单中的<input type="file" name="bpmn"/>name

// 获取文件名
Collection<String> lists = part.getHeaderNames();
for (String key : lists){
System.out.println(key);
System.out.println(part.getHeader(key));
}
String contentDisposition = part.getHeader("content-disposition");//这个content-disposition是上面的key中的一个,
String fileName = contentDisposition.substring(contentDisposition.lastIndexOf("=") + 2, contentDisposition.length() - 1);

// 获取文件类型 (contentType: application/octet-stream)
String contentType = part.getContentType();
System.out.println("contentType: " + contentType);
// 获取文件的输入流
InputStream inputStream = part.getInputStream();

/** 获取流程引擎 */前面有一篇有介绍
ProcessEngine pe = ProcessEngineUtils.getProcessEngine();
/** 获取仓储服务 */
RepositoryService repositoryService = pe.getRepositoryService();
/** 创建部署构建对象 */
DeploymentBuilderbuilder = repositoryService.createDeployment();
/** 添加需要部署的文件 */
builder.addInputStream(fileName, inputStream);

/** 添加name */
builder.name(fileName);
/** 添加种类 */
builder.category("自定义");
/** 进行部署 */
builder.deploy();


request.getRequestDispatcher("/xxx.jsp").forward(request, response);
}

每次重新部署一个id相同的bpmn时,正在执行的流程会被自动删除。

查询和删除操作

repositoryService.createDeploymentQuery().orderByDeploymenTime().desc().list(); 返回List<Deployment>

repositoryService.deleteDeployment(deploymentId, true);true代表级联,默认就是级联

-----------------------------------------------------------------------------------------------------------------

用eclipse画完流程图之后的bpmn文件中有一个流程id,这个是唯一的。当这个bpmn去部署时,只要之前有过这个流程,那么它会在流程定义表(act_re_procdef)中创建一条这个流程部署的最新定义(理解为你修改了流程,然后又去重新部署,那么它会有最新的一条流程定义,当然老的还在,表中有个字段是版本号。我们在使用时都会用新的),表中Key_字段就是流程图中的id。那么流程定义到底是干嘛的?它就是用来启动一个流程的。

流程定义与流程部署是不一样的,一个流程部署可以对应多个流程定义。流程部署的表是act_re_deployment,流程定义的表是act_re_procdef。可以理解为act_re_procdef是act_re_deployment的从表。

流程定义查询:repositoryService.createProcessDefinitionQuery().latestVersion().orderByProcessDefinitionVersion().desc().list();//latestVersion()表示我们要查询最新。返回List<ProcessDefinition>

流程定义不需要删除,因为当你不要这个流程定义时,你就把流程部署给删除好了。

通过ID启动流程:processEngine.getRuntimeService().startProcessInstanceById(pdid);//pdid是流程定义的id,另外,这里不再需要仓库服务了,而是RuntimeService

通过流程图的key启动流程:processEngine.getRuntimeService().startProcessInstanceByKey(pdKey);每次都会执行某个流程部署中最新的流程定义。

可见我们应该使用key这种方式启动流程

流程一旦启动,就会有一个流程实例。一个流程可以启动n次,也就是说流程实例可以有n个。就如同很多人都可以请假。

一个流程定义可以查看n个流程实例

流程实例其实就是act_ru_execution(运行中服务涉及的表)存放的条目

根据流程定义ID查询所有流程实例:

ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
List<ProcessInstance> piLists = processInstanceQuery.processDefinitionId(pdId).orderByProcessInstanceId().desc().list();

request.setAttribute("piLists", piLists);

request.getRequestDispatcher("/processInstances.jsp").forward(request, response);//查询结果转发到JSP

根据流程实例ID查看流程图(流程图当前节点会用红框包围):

// 根据流程实例ID查询流程定义ID
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(piId).singleResult();

InputStream is = repositoryService.getProcessDiagram(processInstance.getProcessDefinitionId());//注意流的关闭,这里为了方便没关
BufferedImage image = ImageIO.read(is);
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setColor(Color.RED);
// 设置粗细
graphics.setStroke(new BasicStroke(3.0f));

// 消除锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 获取当前所有的活动节点id(就是轮到的那个节点)
List<String> activeActivityIds = runtimeService.getActiveActivityIds(piId);
// 流程图模型
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
for (String activeActivityId : activeActivityIds) {
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(activeActivityId);
graphics.drawRoundRect((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(),
(int) graphicInfo.getHeight(), 10, 10);
}
response.setContentType("image/png");
ImageIO.write(image, "png", response.getOutputStream());//这个方法里面会帮我们关闭输出流

可以考虑用IOUtils.copy(in, output);

根据流程实例ID下载流程图(通过原始Servlet实现)

// 根据流程实例ID查询流程定义ID
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(piId)
.singleResult();

InputStream is = repositoryService.getProcessDiagram(processInstance.getProcessDefinitionId());
response.setContentType("application/octet-stream;charset=UTF-8");
response.setHeader("Content-Disposition",
"attachment; filename="
+ new String((processInstance.getProcessDefinitionName() + ".png").getBytes("utf-8"),
"iso8859-1"));
ServletOutputStream outputStream = response.getOutputStream();//这里不要用response.getWriter(),因为它是字符流,图片不支持,图片要用字节流
byte[] array = new byte[1024];
int length = -1;
while ((length = is.read(array, 0, array.length)) != -1) {
outputStream.write(array, 0, length);
}
outputStream.flush();
outputStream.close();

根据流程实例id删除流程:

runtimeService.deleteProcessInstance(piId, "test delete");

response.sendRedirect(request.getContextPath() + "/queryProcessInstanceById.action?pdId="+pdId);//删除完做重定向即可,不要做转发,麻烦

根据流程实例id触发走一步(发信号signal),这里没有涉及到usertask,所以可以用signal手动触发走一步:

runtimeService.signal(piId);

response.sendRedirect(request.getContextPath() + "/queryProcessInstanceById.action?pdId="+pdId);

当流程实例走完后,会从act_ru_execution表中自动删除,act_hi_procinst可以看到流程实例的状态(有开始和结束时间,如果没结束,那么结束时间为空),act_hi_actinst表可以看到流程实例经过的所有节点

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值