Camunda部署流程定义与发起流程实例

2,017 阅读3分钟

​1、部署流程定义

1.1画图

上文我们提到一个Camunda Modeler,安装一下,方便我们获取xml文件,下载地址:流程设计器

对发起人节点的任务代理人这里设置变量

​在经理审批节点也设置一个任务代理人变量

一个简单的流程图画好之后,在面板左下角可以看见有XML,点击它,在这里就可以获取到所需要的bpmn了。

在项目的resources文件夹下新建一个以bpmn结尾的文件【一定要以.bpmn结尾】,把刚刚获取到的bpmn内容复制过来。

1.2编码

这里直接给出实现类的代码,接口代码就省略了。这里仅给出两种部署方式,其他方法就不提了,不常用。【ResultReturn是自定义的返回值类,有需要的可以私信我获取,返回值改一下,这部分代码与本文无关就不贴出来了

package com.lonewalker.snail.core.service.impl;

import com.lonewalker.snail.common.constant.ProcessConstant;
import com.lonewalker.snail.common.entity.ResultReturn;
import com.lonewalker.snail.common.utils.ResultReturnUtil;
import com.lonewalker.snail.core.service.ProcessDefinitionService;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.repository.Deployment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @description: 流程定义相关服务
 * @author: LoneWalker
 * @create: 2021-12-26
 **/
@Service("processDefService")
public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
    public final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    RepositoryService repositoryService;

    @Override
    public ResultReturn deployDefinitionByResource(String name,String resource) {
        Deployment deploy = repositoryService.createDeployment()
                .name(name)
                .addClasspathResource(resource)
                .deploy();
        logger.info("流程Id:" + deploy.getId());
        logger.info("流程Name:" + deploy.getName());
        return ResultReturnUtil.success(ProcessConstant.DEPLOY_PROCESS_DEFINITION_SUCCESS);
    }

    @Override
    public ResultReturn deployDefinitionByString(String definitionName,String resourceName,String resource) {
        Deployment deploy = repositoryService.createDeployment()
                .name(definitionName)
                .addString(resourceName+".bpmn",resource)
                .deploy();
        logger.info("流程Id:" + deploy.getId());
        logger.info("流程Name:" + deploy.getName());
        return ResultReturnUtil.success(ProcessConstant.DEPLOY_PROCESS_DEFINITION_SUCCESS);
    }
}

本文使用第一种,加载classpath下的资源文件来演示,后续会使用第二种

贴一下Controller的代码和Entity

@RestController
@RequestMapping("/processDefinition")
public class ProcessDefinitionController {

    @Autowired
    ProcessDefinitionService processDefService;

    @PostMapping("/deploy")
    public ResultReturn deployProcessDefinition(@RequestBody ProcessDefinition processDefinition){
        String definitionName = processDefinition.getDefinitionName();
        String resourceName = processDefinition.getResourceName();
        return processDefService.deployDefinitionByResource(definitionName,resourceName);
    }
}

@Data
public class ProcessDefinition implements Serializable {
    private String definitionName;
    private String resourceName;
    private String resource;
}

行了,直接使用postman测试一下吧。

1.3查看部署的流程定义

控制台也是之前提到过的,不赘述。从界面上可以简单看出有一条定义,一次部署。

2、发起流程实例

​**注意:****如果bpmn文件中的这个id没有改变,则重新部署流程定义后,流程引擎会认为是版本迭代,并取最新版本来发起流程实例,**这个id也就是下文中的processDefinitionKey。

2.1开启流程实例的代码

首先创建一个流程实例服务接口

public interface ProcessInstanceService {

public ResultReturn startProcessInstanceByKey(String processDefinitionKey, String businessKey);
}

其实现类:【这里可以看出在开启流程实例时已经对两个参数进行赋值了】

@Service("processInstanceService")
public class ProcessInstanceServiceImpl implements ProcessInstanceService {
@Autowired
private RuntimeService runtimeService;
@Autowired
private IdentityService identityService;

@Override
public ResultReturn startProcessInstanceByKey(String processDefinitionKey, String businessKey,String initiator) {
Map<String,Object> map = new HashMap<>();
map.put("userOne","userOne");
map.put("userTwo","userTwo");
//设置流程发起人
identityService.setAuthenticatedUserId("initiator");
ProcessInstance processInstance=runtimeService.startProcessInstanceByKey(processDefinitionKey,businessKey,map);
}
}

流程实例接口类

@RestController
@RequestMapping("/processInstance")
public class ProcessInstanceController {

@Autowired
ProcessInstanceService processInstanceService;

@PostMapping("/startProcess")
public ResultReturn startProcess(String processDefinitionKey,String businessKey,String initiator){
return processInstanceService.startProcessInstanceByKey(processDefinitionKey,businessKey,initiator);
}
}

然后发起流程:

在控制台查看 有我们开启流程时设置的业务ID、流程定义版本号、当前节点的任务处理人。

其实完成任务和处理人没关系,处理人的设置是用来查询待办,能看见才有机会完成。

2.2查询待办的代码

所以接下来写个查询待办服务。首先创建一个任务服务接口

public interface ProcessTaskService {

public ResultReturn queryMyToDo(String userId);

}

其实现类

@Service
public class ProcessTaskServiceImpl implements ProcessTaskService {

@Autowired
private TaskService taskService;
@Autowired
private IdentityService identityService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private HistoryService historyService;
 @Override
public ResultReturn queryMyToDo(String userId) {
try {
List<Task> tasks = taskService.createTaskQuery().taskAssignee(userId).list();
return ResultReturnUtil.success(tasks);
}catch(Exception e){
e.printStackTrace();
throw new ProcessException(ResponseEnums.QUERY_TASK_MY_TO_DO_FAIL.getMsg());
}
} 
}

controller

@RestController
@RequestMapping("/processTask")
public class ProcessTaskController {
@Autowired
ProcessTaskService processTaskService;
 @GetMapping("/queryMyToDo")
public ResultReturn queryMyToDo(String userId){
return processTaskService.queryMyToDo(userId);
} 
}

请求后

此时也就可以控制谁可以看见哪些任务,有了待办就需要去完成,再来写一个完成任务的接口

2.3审批通过

还是在ProcessTaskService中来写,很简单哈,传一个任务ID即可。

@Override
public ResultReturn taskPass(String taskId) {
taskService.complete(taskId);
return ResultReturnUtil.success("审批通过");
}

@PostMapping("/taskPass")
public ResultReturn taskPass(String taskId){
return processTaskService.taskPass(taskId);
}

在刚刚查询待办的返回数据中就可以获取到TaskId

拿到这个值就可以测试一下审批通过是否可以使用

此时再去看一下,camunda view,说明确实审批通过了

同样的步骤完成【经理审批】节点,也就结束了本条简单的流程。