0
点赞
收藏
分享

微信扫一扫

Activiti6工作流,搞懂模型,流程,任务,项目直接上手就干

奋斗De奶爸 2022-03-30 阅读 70
java后端

Activiti6工作流,搞懂模型,流程,任务,项目直接上手就干

1流程图概述

在这里插入图片描述

Activiti6工作流的流程设计需要经历 1模型的创建与发布 2流程的启用 3对于流程相关发起的节点任务进行申请,审批等操作

2管理模型说明

2.1创建/更新模型

1逻辑说明:

​ 1新建一个空模型(默认后台创建,然后前端修改模型信息)

​ 2然后页面展示绘制流程图,页面返回重定向地址:” /static/modeler.html?modelId=”(参数是返回的),默认修改后关闭自动保存)

2代码实现:

	/**
* 新建一个空模型
*/

@RequestMapping("/create")
public void newModel(HttpServletRequest request, HttpServletResponse response) throws IOException {
RepositoryService repositoryService = processEngine.getRepositoryService();
// 初始化一个空模型
Model model = repositoryService.newModel();

// 设置一些默认信息
String name = "";
String description = "";
int revision = 1;
String key = "m_" + CreatedTools.getCreated();
// 设置子系统
model.setTenantId("子系统1");

ObjectNode modelNode = objectMapper.createObjectNode();
modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);

model.setName(name);
model.setKey(key);
model.setMetaInfo(modelNode.toString());

repositoryService.saveModel(model);
String id = model.getId();

// 完善ModelEditorSource
ObjectNode editorNode = objectMapper.createObjectNode();
editorNode.put("id", "canvas");
editorNode.put("resourceId", "canvas");
ObjectNode stencilSetNode = objectMapper.createObjectNode();
stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
editorNode.put("stencilset", stencilSetNode);
repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8"));
response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + id);
}

/**
* 保存一个模型
*/

@RequestMapping(value = "/model/{modelId}/save", method = RequestMethod.PUT)
@ResponseStatus(value = HttpStatus.OK)
public void saveModel(@PathVariable String modelId, String name, String description, String json_xml,
String svg_xml)
{
try {
Model model = repositoryService.getModel(modelId);

ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());

modelJson.put(MODEL_NAME, name);
modelJson.put(MODEL_DESCRIPTION, description);
model.setMetaInfo(modelJson.toString());
model.setName(name);

repositoryService.saveModel(model);

repositoryService.addModelEditorSource(model.getId(), json_xml.getBytes("utf-8"));

InputStream svgStream = new ByteArrayInputStream(svg_xml.getBytes("utf-8"));
TranscoderInput input = new TranscoderInput(svgStream);

PNGTranscoder transcoder = new PNGTranscoder();
// Setup output
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
TranscoderOutput output = new TranscoderOutput(outStream);

// Do the transformation
transcoder.transcode(input, output);
final byte[] result = outStream.toByteArray();
repositoryService.addModelEditorSourceExtra(model.getId(), result);
outStream.close();

} catch (Exception e) {
LOGGER.error("Error saving model", e);
throw new ActivitiException("Error saving model", e);
}
}

3可视化页面

​ 1.模型新增页面

​ 2模型编辑页面
在这里插入图片描述

4涉及的表结构信息

表名表说明
act_ge_bytearray#二进制文件表
字段名字段说明
ID_唯一标识
REV_
NAME_
DEPLOYMENT_ID_
BYTES_文件流
GENERATED_

2.2发布模型

1逻辑说明:

​ 1选择模型进行发布操作

​ 注意:1每次更改后需要重新发布,否则模型未更新;

​ 2根据模型Id判断模型是否发布(已经发布的模型存在运行中的流程,需要先处理流程然后再发布);

​ 3模型设计需要有主线流程(开始结束任务否则提示修改重新发布),在部署表中创建部署的信息,同时在二进制文件表中存储模型的信息

2代码实现:

	/**
* 发布模型为流程定义
*/

@RequestMapping("/deploy")
@ResponseBody
public Object deploy(String modelId) throws Exception {

// 获取模型
RepositoryService repositoryService = processEngine.getRepositoryService();
Model modelData = repositoryService.getModel(modelId);
byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());

if (bytes == null) {
return "模型数据为空,请先设计流程并成功保存,再进行发布。";
}

JsonNode modelNode = new ObjectMapper().readTree(bytes);
BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
model.setTargetNamespace(modelData.getCategory());

if (model.getProcesses().size() == 0) {
return "数据模型不符要求,请至少设计一条主线流程。";
}
byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);

// 发布流程
String processName = modelData.getName() + ".bpmn20.xml";
Deployment deployment = repositoryService.createDeployment().name(modelData.getName())
.category(modelData.getCategory()).addString(processName, new String(bpmnBytes, "UTF-8")).deploy();
modelData.setDeploymentId(deployment.getId());
repositoryService.saveModel(modelData);

return "SUCCESS";
}

3可视化页面

在这里插入图片描述

4涉及的表结构信息

表名表说明
act_re_deployment#流程部署表

2.3查询模型

1逻辑说明:

​ 1查询模型

2代码实现:

	/**
* 获取所有模型
*/

@RequestMapping("/modelList")
@ResponseBody
public Object modelList(String name) {
if (name == null) {
name = "";
}
RepositoryService repositoryService = processEngine.getRepositoryService();
return repositoryService.createModelQuery().modelNameLike("%" + name + "%").modelTenantId("子系统1").list();
}


/**
* 分页查询
*/

@RequestMapping("/modelListPage")
@ResponseBody
public Object modelListPage(String name,int page, int limit) {
if (name == null) {
name = "";
}
RepositoryService repositoryService = processEngine.getRepositoryService();
int totalCount = (int) repositoryService.createModelQuery().modelNameLike("%" + name + "%").modelTenantId("子系统1").count();
List<Model> list = repositoryService.createModelQuery().modelNameLike("%" + name + "%").modelTenantId("子系统1").listPage((page - 1) * limit, page * limit);
Map<String, Object> map = new HashMap<>();
map.put("list", list);
map.put("page", page);
map.put("limit", limit);
map.put("totalRow", totalCount);
return map;
}

3可视化页面

在这里插入图片描述

4涉及的表结构信息

表名表说明
act_ge_bytearray#二进制文件表
字段名字段说明
ID_唯一标识
REV_
NAME_
DEPLOYMENT_ID_
BYTES_文件流
GENERATED_

2.4删除模型

1逻辑说明:

​ 1删除模型前需要判断是否存在正在执行的流程,存在需要先处理流程,硬删除,删除表act_ge_bytearry模型信息(为发布的模型)1

2代码实现:

	/**
* 删除工作流模型
*/

@RequestMapping("/deleteModel")
@ResponseBody
public Object deleteModel(String modelId) {
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.deleteModel(modelId);
return "SUCCESS";
}

3可视化页面

在这里插入图片描述

4涉及的表结构信息

表名表说明
act_re_procdef;#流程定义

3管理流程说明

3.1启动流程型

1逻辑说明:

​ 1.首先需要确定根据流程部署Id获取流程定义

​ 2.可以自定义对象进行配置

​ 3.启动流程

2代码实现:

		// 启动一个流程实例
@GetMapping("/activiti_define_start")
@ResponseBody
public Wrapper<String> activiti_define_start(@Valid String id) {
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();

Map<String, Object> varaiables = new HashMap<>();
// ...此处可注入变量
varaiables.put("username", "111");
varaiables.put("userNames", "111,222");
ProcessInstance pi = runtimeService.startProcessInstanceById(id, varaiables);
runtimeService.setProcessInstanceName(pi.getId(), pd.getName());

logger.info("启动流程实例,获取id-->{},实例名称-->{}", pi.getId(), pd.getName());
return WrapMapper.ok(pi.getId());
}

3可视化页面

在这里插入图片描述

4涉及的表结构信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xpuO0LZB-1648536054227)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220329111617246.png)]

表名表说明
act_ru_execution#流程启动一次只要没有执行完就会有一条数据
act_ru_task#可能记录多条数据
act_ru_variable#记录流程运行时的流程变量
act_ru_identitylink#存放流程办理人的信息
act_hi_procinst#历史流程实例
act_hi_taskinst#历史任务实例
act_hi_actinst#历史活动节点表
act_hi_varinst#历史流程变量表
act_hi_identitylink#历史办理人表
act_hi_comment#批注表
act_hi_attachment#附件表

3.2查询流程

逻辑:根据流程实例查询获取流程图信息

/**
* 查询流程定义列表
*
* @return
*/

@RequestMapping("/activitDefineList")
@ResponseBody
public List<Map<String, Object>> activitDefineList(String name) {
// 创建查询对象
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
// 使用部署对象ID查询
// processDefinitionQuery.deploymentId(deploymentId);
// 使用流程定义ID查询
// processDefinitionQuery.processDefinitionId(processDefinitionId)
// 使用流程定义的KEY查询
// processDefinitionQuery.processDefinitionKey(processDefinitionKey)

// 使用流程定义的名称模糊查询
if (name == null || "".equals(name.trim())) {
} else {
processDefinitionQuery.processDefinitionNameLike("%" + name + "%");
}
List<ProcessDefinition> list = processDefinitionQuery.list();
return ActivitiTools.turnProcessDefinitions(list);
}

@RequestMapping("/activitiInstanceList")
public List<Map<String, Object>> activitiInstanceList(String name) {
// 创建查询对象
ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
if (name != null ".equals(name)) {
processInstanceQuery.processInstanceNameLike("
%" + name + "%");
}

List<ProcessInstance> list = processInstanceQuery.list();
return ActivitiTools.turnProcessInstances(list);
}

4管理任务说明

4.1申请的任务

1逻辑说明:

​ 1.查询申请的任务清单

2代码实现:

		@RequestMapping("/todoTaskList")
@ResponseBody
public List<Map<String, Object>> todoTaskList(String name) {
// 创建查询对象
TaskQuery taskQuery = taskService.createTaskQuery();
if (name != null ".equals(name)) {
taskQuery.processDefinitionNameLike("
%" + name + "%");
}
// 设置查询条件
// 根据任务的办理人查询
// taskQuery.taskAssignee(assignee);
// 指定流程定义key,只查询某个流程的任务
// taskQuery.processDefinitionKey(processDefinitionKey);
// 获取查询列表
List<Task> list = taskQuery.list();
List<Map<String, Object>> listEnd = ActivitiTools.turnTasks(list);

// 分页时用,非分页慎用
/*
* ProcessInstanceQuery instanceQuery =
* runtimeService.createProcessInstanceQuery(); for (Map<String, Object> map :
* listEnd) { String processDefinitionId = (String)
* map.get("
processDefinitionId"); if (processDefinitionId != null) {
* List<ProcessInstance> processInstanceList =
* instanceQuery.processDefinitionId(processDefinitionId).list(); if
* (processInstanceList != null) { for (ProcessInstance processInstance :
* processInstanceList) { map.put("
processInstanceName",
* processInstance.getName()); } } } }
*/
return listEnd;
}

3可视化页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1F8ORKbC-1648536054228)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220329133347924.png)]

4涉及的表结构信息

在这里插入图片描述

4.2审批的任务

1逻辑说明:

​ 1.查询待审批的任务清单

2代码实现:

@RequestMapping("/mineTodoTaskList")
@ResponseBody
public List<Map<String, Object>> todoTaskList(String name, String user_id, String depart_id) {
// 创建查询对象
TaskQuery taskQuery = taskService.createTaskQuery();
TaskQuery taskQuery1 = taskService.createTaskQuery();
if (name != null ".equals(name)) {
taskQuery.processDefinitionNameLike("
%" + name + "%");
taskQuery1.processDefinitionNameLike("
%" + name + "%");
}
taskQuery.taskCandidateOrAssigned(user_id);
taskQuery1.taskCandidateOrAssigned(depart_id);
// 设置查询条件
// 根据任务的办理人查询
// taskQuery.taskAssignee(assignee);
// 指定流程定义key,只查询某个流程的任务
// taskQuery.processDefinitionKey(processDefinitionKey);
// 获取查询列表
List<Task> list = taskQuery.list();
List<Task> list1 = taskQuery1.list();
list.addAll(list1);
List<Map<String, Object>> listEnd = ActivitiTools.turnTasks(list);
return listEnd;
}

4.3提交申请

1逻辑说明:

​ 1.提交审批任务

​ 2.更新form表单信息

2代码实现:

@PostMapping("/submit")
public Wrapper<String> submit(@Valid @RequestBody FormSubmitDto formSubmitDto) {
String task_id = formSubmitDto.getTask_id();
String form = formSubmitDto.getForm();

Task task = taskService.createTaskQuery().taskId(task_id).singleResult();
if (task == null) {
return WrapMapper.ok("您已提交成功!");
}

logger.info("表单提交...");
JSONObject formJson = JsonUtil.jsonStrToJsonObject(form);
logger.info("formJson--{}", formJson);
Set<String> keySet = formJson.keySet();
for (String key : keySet) {
Object val = formJson.getString(key);
logger.info("{}:{}", key, val);
taskService.setVariable(task.getId(), key, val);
taskService.setVariableLocal(task.getId(), key, val);
}
// 保存表单以及表单的值
formValsService.saveFormVals(formSubmitDto);

logger.info("表单相关操作完成!");

taskService.complete(task.getId());

logger.info("检查重复审批人, 自动去重.");
// formDuplicateService.doDuplicateTask(task.getProcessInstanceId());
logger.info("根据完成时间,自动设置提醒方式.");
modelJsonService.dueNextTaskPushHandle(task.getProcessInstanceId());

return WrapMapper.ok("提交成功!");
}

4.4提交审批

1逻辑说明:

​ 1.提交审批任务

​ 2.更新form表单信息

2代码实现:

@PostMapping("/submit")
public Wrapper<String> submit(@Valid @RequestBody FormSubmitDto formSubmitDto) {
String task_id = formSubmitDto.getTask_id();
String form = formSubmitDto.getForm();

Task task = taskService.createTaskQuery().taskId(task_id).singleResult();
if (task == null) {
return WrapMapper.ok("您已提交成功!");
}

logger.info("表单提交...");
JSONObject formJson = JsonUtil.jsonStrToJsonObject(form);
logger.info("formJson--{}", formJson);
Set<String> keySet = formJson.keySet();
for (String key : keySet) {
Object val = formJson.getString(key);
logger.info("{}:{}", key, val);
taskService.setVariable(task.getId(), key, val);
taskService.setVariableLocal(task.getId(), key, val);
}
// 保存表单以及表单的值
formValsService.saveFormVals(formSubmitDto);

logger.info("表单相关操作完成!");

taskService.complete(task.getId());

logger.info("检查重复审批人, 自动去重.");
// formDuplicateService.doDuplicateTask(task.getProcessInstanceId());
logger.info("根据完成时间,自动设置提醒方式.");
modelJsonService.dueNextTaskPushHandle(task.getProcessInstanceId());

return WrapMapper.ok("提交成功!");
}

五额外说明

1关于受理人概念

​ 当一个流程被启动的时候,我们可以在节点上选择受理人是谁,如果选择并且填写了受理人

​ 1受理人有值,XML流程里面定义的受理人,TASK会直接填入这个人

​ 2受理人无值,可以使用签收功能去指定受理人,就是候选组里面谁签收谁就成了受理人

Task task=taskService.createTaskQuery().singleResult();
//签收
taskService.claim(task.getId(), "billy");
logger.info(taskService.createTaskQuery().singleResult().getAssignee());

2关于委托人概念

​ 受理人委托其他人操作该TASK的时候,受理人就成了委托人OWNER_,其他人就成了受理人ASSIGNEE_

Task task=taskService.createTaskQuery().singleResult();
//委托
taskService.delegateTask(task.getId(), "cc");
logger.info(taskService.createTaskQuery().singleResult().getOwner());
logger.info(taskService.createTaskQuery().singleResult().getAssignee());
//结果:owner是Billy,assignee是cc

​ 2受理人无值,可以使用签收功能去指定受理人,就是候选组里面谁签收谁就成了受理人

Task task=taskService.createTaskQuery().singleResult();
//签收
taskService.claim(task.getId(), "billy");
logger.info(taskService.createTaskQuery().singleResult().getAssignee());

2关于委托人概念

​ 受理人委托其他人操作该TASK的时候,受理人就成了委托人OWNER_,其他人就成了受理人ASSIGNEE_

Task task=taskService.createTaskQuery().singleResult();
//委托
taskService.delegateTask(task.getId(), "cc");
logger.info(taskService.createTaskQuery().singleResult().getOwner());
logger.info(taskService.createTaskQuery().singleResult().getAssignee());
//结果:owner是Billy,assignee是cc
举报

相关推荐

0 条评论