言尽于此,完结
无论是一个初级的 coder,高级的程序员,还是顶级的系统架构师,应该都有深刻的领会到设计模式的重要性。
- 第一,设计模式能让专业人之间交流方便,如下:
程序员A:这里我用了XXX设计模式
程序员B:那我大致了解你程序的设计思路了
- 第二,易维护
项目经理:今天客户有这样一个需求…
程序员:明白了,这里我使用了XXX设计模式,所以改起来很快
- 第三,设计模式是编程经验的总结
程序员A:B,你怎么想到要这样去构建你的代码
程序员B:在我学习了XXX设计模式之后,好像自然而然就感觉这样写能避免一些问题
- 第四,学习设计模式并不是必须的
程序员A:B,你这段代码使用的是XXX设计模式对吗?
程序员B:不好意思,我没有学习过设计模式,但是我的经验告诉我是这样写的
从设计思想解读开源框架,一步一步到Spring、Spring5、SpringMVC、MyBatis等源码解读,我都已收集整理全套,篇幅有限,这块只是详细的解说了23种设计模式,整理的文件如下图一览无余!
搜集费时费力,能看到此处的都是真爱!
-
【附件】获取附件
-
【常用方法】
-
- 获取CommandContext(全局任意地方使用)
-
获取当前任务节点
-
获取流程定义
-
根据节点id获取FlowElement节点对象
-
设置执行实例的当前活动节点为目标节点
-
向operations中压入继续流程的操作类
-
删除任务
-
完成任务
-
获取流程定义的start节点
-
获取流程定义的第一个节点
-
驳回到起始节点
-
流程任意节点跳转、驳回、退回、拒绝等
-
历史活动查询
-
历史任务查询
-
查询流程状态
背景
记录项目需求中常用的功能以及其实现方式
本文都是基于Activiti6.0.0
【流程】我发起的流程
- 1.在启动流程的时候,设置当前用户,代码如下:
try {
identityService.setAuthenticatedUserId(“zs”);
runtimeService.startProcessInstanceByKey(“leave”);
} finally {
identityService.setAuthenticatedUserId(null);
}
引擎自动操作如下:
-
act_ru_execution 表 START_USER_ID字段 插入用户id
-
引擎会记录启动人信息,在ACT_HI_PROINST表的START_USER_ID字段,记录用户id “zs”.
- 2.查询我发起的时候,输入用户id
List list = historyService.createHistoricProcessInstanceQuery()
.startedBy(“zs”).list();
实际是执行如下的sql
SELECT DISTINCT
RES.*,
DEF.KEY_ AS PROC_DEF_KEY_,
DEF.NAME_ AS PROC_DEF_NAME_,
DEF.VERSION_ AS PROC_DEF_VERSION_,
DEF.DEPLOYMENT_ID_ AS DEPLOYMENT_ID_
FROM
ACT_HI_PROCINST RES
LEFT OUTER JOIN ACT_RE_PROCDEF DEF ON RES.PROC_DEF_ID_ = DEF.ID_
WHERE
RES.START_USER_ID_ = ‘zs’
ORDER BY
RES.ID_ ASC
LIMIT ‘2147483647’ OFFSET ‘0’
备注:
createHistoricProcessInstanceQuery finished–> 完成的流程; unfinish —>
还在运行中的流程
【流程】与我相关的流程
List list = historyService
.createHistoricProcessInstanceQuery().involvedUser(“zs”).list();
实际sql
SELECT DISTINCT
RES.*,
DEF.KEY_ AS PROC_DEF_KEY_,
DEF.NAME_ AS PROC_DEF_NAME_,
DEF.VERSION_ AS PROC_DEF_VERSION_,
DEF.DEPLOYMENT_ID_ AS DEPLOYMENT_ID_
FROM
ACT_HI_PROCINST RES
LEFT OUTER JOIN ACT_RE_PROCDEF DEF ON RES.PROC_DEF_ID_ = DEF.ID_
WHERE
( EXISTS ( SELECT LINK.USER_ID_ FROM
ACT_HI_IDENTITYLINK LINK WHERE USER_ID_ = ‘zs’ AND LINK.PROC_INST_ID_ = RES.ID_ ) )
ORDER BY
RES.ID_ ASC
LIMIT ‘2147483647’ OFFSET ‘0’
【任务】我的待办任务
String assignee = “zs”;
List list = taskService()//与正在执行的任务管理相关的Service
.createTaskQuery()//创建任务查询对象
.taskAssignee(assignee)//指定个人任务查询,指定办理人
.orderByTaskCreateTime().asc()//使用创建时间的升序排列
/*返回结果集/
.list();//返回列表
if (list != null && list.size() > 0) {
for (Task task : list) {
System.out.println(“任务ID:” + task.getId());
System.out.println(“任务名称:” + task.getName());
System.out.println(“任务的创建时间:” + task.getCreateTime());
System.out.println(“任务的办理人:” + task.getAssignee());
System.out.println(“流程实例ID:” + task.getProcessInstanceId());
System.out.println(“执行对象ID:” + task.getExecutionId());
System.out.println(“流程定义ID:” + task.getProcessDefinitionId());
System.out.println(task.toString());
System.out.println(“########################################################”);
}
}
【任务】我的已办任务
List list = historyService.createHistoricTaskInstanceQuery()
.taskAssignee(“zs”)
.finished()// 已完成
.list();
【任务】修改任务审核人
taskEntity.setAssignee(assignee);
historyManager.recordTaskAssigneeChange(delegateTask.getId(), assignee);
【批注】添加批注
try {
Authentication.setAuthenticatedUserId(“zs”);//批注人的名称 一定要写,不然查看的时候不知道人物信息
String taskId = “21”; // 任务id;
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
String processInstanceId = task.getProcessInstanceId(); // 实例id
String type = “comment”; // 批注类型,这个参数如果不写默认就是"comment",用于扩展 用的。
String message = “同意起飞同意”; // 批注内容
// 给当前任务添加批注信息
taskService.addComment(taskId, processInstanceId, type, message);
} finally {
Authentication.setAuthenticatedUserId(null);
}
INSERT INTO
ACT_HI_COMMENT ( ID_, TYPE_, TIME_, USER_ID_,
TASK_ID_, PROC_INST_ID_, ACTION_, MESSAGE_, FULL_MSG_ )
VALUES
( ‘7503’, ‘comment’, ‘2020-11-26 11:42:39.908’, ‘zs’,
‘21’, ‘8’, ‘AddComment’, ‘同意起飞同意’, ‘java.io.ByteArrayInputStream@6b2042de’
)
【批注】获取批注
- 1.根据实例id获取批注
List processInstanceComments = taskService.getProcessInstanceComments(processInstanceId);
实际sql
select * from ACT_HI_COMMENT where PROC_INST_ID_ = ‘8’ order by TIME_ desc
- 2、根据任务id获取批注
List taskComments = taskService.getTaskComments(taskId);
select * from ACT_HI_COMMENT where TASK_ID_ = ‘21’ and TYPE_ = ‘comment’ order by TIME_ desc
【附件】创建附件
try {
Authentication.setAuthenticatedUserId(“zs”);//批注人的名称 一定要写,不然查看的时候不知道人物信息
String attachmentType = “”;
String taskId = “21”; // 任务id
String processInstanceId = “8”; // 任务实例id
String attachmentName = “test.png”; // 附件名称
String attachmentDescription = “描述描述”; // 附件描述
String url = “www.baidu.com/a.png”;
taskService.createAttachment(attachmentType, taskId, processInstanceId, attachmentName, attachmentDescription, url);
} finally {
Authentication.setAuthenticatedUserId(null);
}
INSERT INTO
ACT_HI_COMMENT ( ID_, TYPE_, TIME_, USER_ID_, TASK_ID_, PROC_INST_ID_,
ACTION_, MESSAGE_, FULL_MSG_ )
VALUES
( ‘10002’, ‘event’, ‘2020-11-26 11:57:30.691’, ‘zs’, ‘21’, ‘8’,
‘AddAttachment’, ‘test.png’, ‘null’ )
INSERT INTO
ACT_HI_ATTACHMENT ( ID_, REV_, USER_ID_, NAME_,
DESCRIPTION_, TYPE_, TASK_ID_, PROC_INST_ID_, URL_, CONTENT_ID_, TIME_ )
VALUES
( ‘10001’, 1, ‘zs’, ‘test.png’,
‘描述描述’, ‘’, ‘21’, ‘8’, ‘www.baidu.com/a.png’, ‘null’, ‘2020-11-26 11:57:30.668’
)
【附件】获取附件
- 1.根据流程实例ID查询附件
// 根据流程实例ID查询附件
List processInstanceAttachments = taskService.getProcessInstanceAttachments(“8”);
// 实际sql
select * from ACT_HI_ATTACHMENT where PROC_INST_ID_ = ‘8’ order by TIME_ desc
- 2.根据任务ID查询附件
// 根据任务ID查询附件
List attachments= taskService.getTaskAttachments(“21”);
// 实际sql
select * from ACT_HI_ATTACHMENT where TASK_ID_ = ‘21’ order by TIME_ desc
【常用方法】
尽量都是没什么限制的全局可用方法。
获取CommandContext(全局任意地方使用)
这个很方便可以在任意地方使用,service,自定义事件,自定义命令中等等
//import org.activiti.engine.impl.context.Context;
CommandContext commandContext = Context.getCommandContext();
HistoryManager historyManager = commandContext.getHistoryManager();
获取当前任务节点
//import org.activiti.engine.impl.context.Context;
CommandContext commandContext = Context.getCommandContext();
获取任务实例管理类
TaskEntityManager taskEntityManager = commandContext.getTaskEntityManager();
获取当前任务实例
TaskEntity currentTask = taskEntityManager.findById(taskId);
ExecutionEntity execution = currentTask.getExecution();
String executionId = execution.getId();
获取流程定义
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
根据节点id获取FlowElement节点对象
FlowElement flowElement = process.getFlowElement(targetNodeId);
设置执行实例的当前活动节点为目标节点
execution.setCurrentFlowElement(flowElement);
向operations中压入继续流程的操作类
commandContext.getAgenda().planContinueProcessOperation(execution);
删除任务
可用用内置的删除命令
org.activiti.engine.impl.cmd。DeleteTaskCmd
public DeleteTaskCmd(String taskId, String deleteReason, boolean cascade) {
this.taskId = taskId;
this.cascade = cascade;
this.deleteReason = deleteReason;
}
public DeleteTaskCmd(Collection taskIds, String deleteReason, boolean cascade) {
this.taskIds = taskIds;
this.cascade = cascade;
this.deleteReason = deleteReason;
}
// 执行方式1
new DeleteTaskCmd(delegateTask.getId(), null).execute(Context.getCommandContext());// 执行完成命令
// 执行方式2
processEngine.getManagementService().executeCommand(cmd)
完成任务
内置的CompleteTaskCmd命令,还有很多类似的,待挖掘
new CompleteTaskCmd(delegateTask.getId(), null).execute(Context.getCommandContext());// 执行完成命令
// 执行方式2
processEngine.getManagementService().executeCommand(cmd)
获取流程定义的start节点
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
FlowElement flowElement = process.getInitialFlowElement();
FlowNode startActivity = (FlowNode) flowElement;
获取流程定义的第一个节点
/**
- 获得第一个节点.
*/
public FlowNode findFirstActivity(String processDefinitionId) {
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
FlowElement flowElement = process.getInitialFlowElement();
FlowNode startActivity = (FlowNode) flowElement;
if (startActivity.getOutgoingFlows().size() != 1) {
throw new IllegalStateException(
"start activity outgoing transitions cannot more than 1, now is : "
- startActivity.getOutgoingFlows().size());
}
SequenceFlow sequenceFlow = startActivity.getOutgoingFlows()
.get(0);
FlowNode targetActivity = (FlowNode) sequenceFlow.getTargetFlowElement();
if (!(targetActivity instanceof UserTask)) {
logger.info(“first activity is not userTask, just skip”);
return null;
}
return targetActivity;
}
驳回到起始节点
processEngine.getManagementService().executeCommand(cmd)
public class RollbackFirstTaskCmd extends NeedsActiveTaskCmd {
private static Logger logger = LoggerFactory.getLogger(RollbackFirstTaskCmd.class);
public RollbackFirstTaskCmd(String taskId){
super(taskId);
}
public String deletereason;
public Void execute(CommandContext commandContext, TaskEntity currentTask) {
String processDefinitionId = currentTask.getProcessDefinitionId();
String executionId = currentTask.getExecutionId();
面试准备+复习分享:
为了应付面试也刷了很多的面试题与资料,现在就分享给有需要的读者朋友,资料我只截取出来一部分哦
tivity;
}
驳回到起始节点
processEngine.getManagementService().executeCommand(cmd)
public class RollbackFirstTaskCmd extends NeedsActiveTaskCmd {
private static Logger logger = LoggerFactory.getLogger(RollbackFirstTaskCmd.class);
public RollbackFirstTaskCmd(String taskId){
super(taskId);
}
public String deletereason;
public Void execute(CommandContext commandContext, TaskEntity currentTask) {
String processDefinitionId = currentTask.getProcessDefinitionId();
String executionId = currentTask.getExecutionId();
面试准备+复习分享:
为了应付面试也刷了很多的面试题与资料,现在就分享给有需要的读者朋友,资料我只截取出来一部分哦
[外链图片转存中…(img-OXeh0lRo-1715805219923)]