说明

在上一章节中,介绍了如何基于bpmn2.0的xml文件发起流程和获取待办,其中流程文件和代码打包在一起,但实际项目中很少会把流程文件和代码一起打包部署,这样的话,每次流程更新或者发布新流程都需要重新部署应用,因此我们制定了以下部署方案:

  • 提供流程部署接口,可以通过上传流程文件对流程进行部署。
  • 如果流程文件没有发生变化,不做新的部署,防止因为重新部署导致版本号上升。

资源部署

activit部署资源文件需要通过RepositoryService创建一个deployment,通过该deployment进行资源的部署,不单单是bpmn流程文件,activiti可以部署任何文件。

上传资源到activiti
@Servicepublic class DeploymentService {    @Autowired    private RepositoryService repositoryService;    /**     * deploy resource     *     * @param name resource name     * @param fin  resource inputstream     * @return     */    public String deploy(String name, InputStream fin) {        String deploymentId = repositoryService.createDeployment()                .addInputStream(name, fin)                .name(name)                .key(name)                .deploy()                .getId();        return deploymentId;    }}

部署的时候指定部署的namekey,方便后续对部署进行进一步操作。

声明restController
@RestControllerpublic class DeploymentController {    @Autowired    private DeploymentService service;    @PostMapping(value = "/deploy")    public String deploy(@RequestParam("file") MultipartFile file) {        try {            return service.deploy(file.getOriginalFilename(), file.getInputStream());        } catch (IOException e) {            e.printStackTrace();            throw new RuntimeException("upload failed");        }    }}

这里以文件名作为部署的名称,可以根据实际情况指定名称。

测试(可以通过postman进行测试,这里使用curl工具进行上传测试)
curl -X POST -F 'file=@WechatIMG1.jpeg' http://localhost:8080/deploy25001

返回的25001就是部署id。

当执行deploy操作时,activiti后台做了以下事

  • 在表ACT_RE_DEPLOYMENT创建一条记录
  • 将资源存储至表ACT_GE_BYTEARRAY,字段BYTES_存储文件内容

流程部署

流程部署和资源部署一样,但有一点需要注意,部署流程时,资源的名称必须以bpmn20.xml或者bpmn结尾,否则activiti会当作普通资源上传,你可以在controller上加个判断避免用户上错错误文件。

 @PostMapping(value = "/deployBpmn")public String deployBpmn(@RequestParam("file") MultipartFile file) {    try {        String name = file.getOriginalFilename();        if (!name.endsWith(".bpmn20.xm") && !name.endsWith(".bpmn")) {            name = name + ".bpmn";        }        return service.deploy(name, file.getInputStream());    } catch (IOException e) {        e.printStackTrace();        throw new RuntimeException("upload failed");    }}

当部署流程后,activit后台除了执行部署资源的动作外,还额外执行以下动作

  • 在表ACT_RE_PROCDEF上创建一条记录,引用deployment_id

流程部署优化

以上我们实现了流程的部署,但每次部署都会导致流程版本递增,我们的方案是如果文件不发生变化则不执行部署操作,保持流程版本好不变,不至于让版本号升的太快,也节省系统资源。那么我们需要完成以下两个逻辑

  • 根据key查询到最新的一次部署
  • 获取最新的一次流程源文件
  • 因为xml是文本文件,我们可以进行文本比对,如果内容一致就认为版本不变

代码如下:

/** * deploy resource * * @param name resource name * @param fin  resource inputstream * @return */public String noChangeNoDeploy(String name, InputStream fin) {    //获取最新的一次部署    Deployment latestDeployment = repositoryService.createDeploymentQuery()            .deploymentName(name)            .deploymentKey(name)            .latest()            .singleResult();    String sbpmn = ActivitiUtil.text(fin);    if (latestDeployment != null) {        //检测是否内容发生变化,只重新部署有修改的流程        InputStream input = repositoryService.getResourceAsStream(latestDeployment.getId(), name);        String dbpmn = ActivitiUtil.text(input);        if (sbpmn.length() == dbpmn.length() && sbpmn.equals(dbpmn)) {            return latestDeployment.getId();        }    }    String deploymentId = repositoryService.createDeployment()            .addString(name, sbpmn)            .name(name)            .key(name)            .deploy()            .getId();    return deploymentId;}

测试:

curl -X POST -F 'file=@ComplexDemo.bpmn20.xml' http://localhost:8080/deployBpmn27501curl -X POST -F 'file=@ComplexDemo.bpmn20.xml' http://localhost:8080/deployBpmn                                                                27501                                                                                                                        

可以看到,如果两次内容一样deployid不会改变

其他

除了通过addInputStream增加资源文件外,RepositoryService还提供了其他api进行资源的添加。如下

DeploymentBuilder addInputStream(String resourceName, InputStream inputStream);DeploymentBuilder addClasspathResource(String resource);DeploymentBuilder addString(String resourceName, String text);DeploymentBuilder addBytes(String resourceName, byte[] bytes);DeploymentBuilder addZipInputStream(ZipInputStream zipInputStream);DeploymentBuilder addBpmnModel(String resourceName, BpmnModel bpmnModel);
本文所有代码已经上传至github,仓库地址为https://github.com/wls1036/springboot-activiti6-tutorial欢迎star