说明

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

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

资源部署

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

上传资源到activiti
@Service
public 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
@RestController
public 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/deploy
25001

返回的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/deployBpmn
27501                                                                                                                                             curl -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
, ,
Trackback

no comment untill now

Add your comment now