核心内容摘要
打牌时你盖对被子了吗?——一场关于策略、心态与人生选择的牌局
工作æµ�审批功能是åŠ�å…¬OAç³»ç»Ÿæ ¸å¿ƒèƒ½åŠ›å¦‚æ�œè®©ä½ 设计一个工作æµ�å®¡æ‰¹ç³»ç»Ÿä½ ä¼šå�—å�ƒä¸‡ä¸�è¦�å°�ç�§OA内部系统的å¤�æ�‚性大家å�¯ä»¥å¤´è„‘é£�æš´æ€�考一下å®�ç�°æ–¹æ¡ˆã€‚è¦�æ˜�白工作æµ�审批涉å�Šå¤šä¸ªç”¨æˆ·çš„任务æµ�转多个æµ�程分支跳转虽然是åŠ�公内部系统但是这个系统并ä¸�简å�•如æ�œæ²¡æœ‰å¼ºå¤§çš„工作æµ�引æ“�难以高效扩展旧æµ�程难以å¢�åŠ æ–°æµ�程工作æµ�审批将æˆ�为公å�¸æ‰€æœ‰äººçš„噩梦但是在使用 activitiå¼€æº�工作æµ�引æ“�å��一切痛苦ä¸�噩梦å�‡çƒŸæ¶ˆäº‘æ•£~activiti 支æŒ�æ–°å¢�æµ�程é��常简å�•å�ªéœ€è¦�两æ¥ç”»ä¸ªæµ�程图æ�é…�å‰�端页é�¢é¦–先画一个æµ�ç¨‹å›¾å°†æ–‡ç« å¼€å¤´çš„éœ€æ±‚è½¬åŒ–ä¸º activiti æµ�程图使用Idea 安装 actiBPM æ�’件创建该æµ�程图文件命å��apply.mpmnå®�ç�°è¯·å�‡æµ�程的二级审批能力一级主管审批超过3天二级主管审批。测试æµ�程图首先创建工作æµ�引æ“�部署æµ�程图//创建工作æµ�引æ“� ProcessEngine engine ProcessEngines.getDefaultProcessEngine(); //RepositoryService用äº�部署æµ�程图 RepositoryService repositoryService engine.getRepositoryService(); //部署请å�‡æµ�程图 repositoryService.createDeployment().addClasspathResource(processes/apply.bpmn).deploy();部署æµ�程图这部分工作一般放在工作æµ�çš„å��å�°ç³»ç»Ÿå¼€å�‘创建好æµ�程图以å��ä¸Šä¼ éƒ¨ç½²åˆ°ç³»ç»Ÿä¸ã€‚æ— éœ€å¼€å�‘修改代ç �repositoryService.createDeployment().addClasspathResource(processes/apply.bpmn).deploy();这行代ç �负责部署æµ�程图到æµ�程引æ“�。 工作æµ�引æ“�会解æ��该æµ�程图文件创建æµ�程模版æ�¥ä¸‹æ�¥å°±å�¯ä»¥åœ¨ä½¿ç”¨è¯¥æµ�程模版å�‘èµ·æµ�程å®�例了。员工zhang3å�‘èµ·æ–°æµ�程设置审批人MapString, Object variableMap new HashMap(); variableMap.put(applyUser, zhang
; variableMap.put(supervisor, li
; variableMap.put(upperSupervisor, wang
;员工zhang3 æ��出请å�‡ç”³è¯·åœ¨å�‘èµ·æ–°æµ�程时通过OA其他系统查到zhang3的一级主管是li4二级主管是wang5äº�是设置上审批人。 有人疑问以下å�˜é‡�applyUserç‰æ˜¯ç³»ç»Ÿé»˜è®¤çš„还是在哪里指定的 在创建主管审批节点时指定审批人å�˜é‡�${applyUser}想象一下如æ�œè¯·å�‡ç±»çš„æµ�程å�‡å�¯èƒ½éœ€è¦�一二级主管审批是ä¸�是å�¯ä»¥åœ¨å�‘èµ·æµ�程时统一填充一二级主管 审批人å�˜é‡�。这部分代ç �是ä¸�是就是通用的新å¢�æµ�ç¨‹æ—¶æ— éœ€äºŒæ¬¡ä¿®æ”¹äº†ã€‚å�‘起一个新æµ�程ProcessInstance instance runtimeService.startProcessInstanceByKey(apply_processor_1, variableMap);如上代ç �指定了全æµ�程审批人å�‘起了一个新æµ�程。 有人会疑问apply_processor_1是什么在哪里指定的这是æµ�程模版的 Key在使用Ideaæ�’ä»¶ç”»æµ�程图时需è¦�指定æµ�程图的Key申请人设置请å�‡å¤©æ•°TaskService taskService engine.getTaskService(); Task firstTask taskService.createTaskQuery().taskAssignee(zhang
.singleResult(); taskService.complete(firstTask.getId(), Maps.newHashMap(day,
);创建并开å�¯æµ�程å®�例å��工作æµ�引æ“�相当äº�å¸®ä½ æ‰§è¡Œäº† æµ�程图的 开始节点然å��æµ�程执行到 请å�‡ç”³è¯·èŠ‚ç‚¹æ¤æ—¶é€šè¿‡taskService查询 zhang3çš„ 处ç�†ä»»åŠ¡ã€‚TaskService是通过第一æ¥ProcessEngineè�·å�–到的主è¦�用äº�任务查询。有人会疑问为什么è¦�区分创建æµ�程ã€�处ç�†ç”³è¯·äººå®¡æ‰¹ä»»åŠ¡ä¸¤ä¸ªæ¥éª¤æˆ‘们在æ��请å�‡ç”³è¯·æ—¶å�ªéœ€è¦�æ��申请一æ¥å°±å®Œæˆ�了。 å®�际上 æ��请å�‡ç”³è¯·æ—¶ç³»ç»Ÿä¼šå¸®ä½ 创建好æµ�程然å��è‡ªåŠ¨æ›¿ä½ å®Œæˆ�审批。为什么工作æµ�引æ“�è¦�区分为两æ¥å‘¢æ‰€æœ‰çš„æµ�程图都需è¦�ç»�过 开始节点也都需è¦�结æ�ŸèŠ‚ç‚¹å¦‚æ¤è®¾è®¡æ–¹å¼�å�¯ä»¥è®©å·¥ä½œæµ�引æ“�的抽象层次更高。它å�¯ä»¥åœ¨å¼€å§‹å’Œç»“æ�Ÿæ—¶ç‚¹å»ºç«‹äº‹ä»¶é€šçŸ¥ç»´æŠ¤æµ�程状æ€�的完整性。æ�¥ä¸‹æ�¥zhang3 通过taskService完æˆ�该任务并且设置å�˜é‡� day4å�³è¯·å�‡å¤©æ•°æ˜¯4天。一级主管审批任务Task secondTask taskService.createTaskQuery().taskAssignee(li
.singleResult(); taskService.setVariable(secondTask.getId(), result1, true);æ�¥ä¸‹æ�¥zhang3å’Œ 领导li4 说â€�我家里有事è¦�请å�‡è¾›è‹¦4哥审批一下“领导在自己的审批å��å�°æŸ¥è¯¢ 审批任务查到å��通过了审批任务。有人会疑问æ€�ä¹ˆæ ‡è¯† 审批通过和ä¸�通过呢 result1 是什么东西系统默认的还是在何处甚至的å�˜é‡�? 在æµ�程图上é…�置的工作æµ�引æ“�没有审批通过ä¸�通过的概念。当æµ�程上å˜åœ¨ A å’Œ B 两个分支时æµ�程图上å�¯ä»¥ä½¿ç”¨æ�’他网关进行分支判定。如请å�‡æµ�程图ä¸ä¸€çº§å®¡æ‰¹ç»“æ�œå°±æ˜¯ä¸€ä¸ªæ�’他网关。在网关的下游分支上é…�置如æ�œè¦�èµ°A分支应该满足哪些æ�¡ä»¶èµ°B分支è¦�满足哪个æ�¡ä»¶è€Œæ�’他网关上并没有é…�置路由æ�¡ä»¶ã€‚例如在一级主管审批å��æµ�程上设置新的å�˜é‡� result1ç»�过æ�’他网关时A分支 是 #{result1true} 判定通过äº�是走了A分支。工作æµ�引æ“�负责检查网关的下级分支的æ�¡ä»¶æ˜¯å�¦æ»¡è¶³å“ªä¸ªæ�¡ä»¶æ»¡è¶³èµ°å“ªä¸ªåˆ†æ”¯ã€‚也就是说上一个任务在处ç�†æ—¶å¹¶ä¸�知é�“æ�¥ä¸‹æ�¥èµ°å“ªä¸ªåˆ†æ”¯ä¹Ÿæ²¡æœ‰æŒ‡å®šèµ°å“ªä¸ªåˆ†æ”¯è€Œæ˜¯å°†è‡ªå·±çš„处ç�†ç»“æ�œæ”¾åˆ°æµ�程å�˜é‡�ä¸åœ¨æ�’他网关的下游分支æ�¡ä»¶ä¸Šæ ¹æ�®æµ�程å�˜é‡�è¿›è¡Œåˆ¤æ–æ�¥ä¸‹æ�¥èµ°å“ªä¸ªåˆ†æ”¯è¿™å°±æ˜¯å·¥ä½œæµ�引æ“�对äº�æµ�程的抽象。工作æµ�引æ“�负责驱动æµ�程到æ�’他网关至äº�走哪个分支由分支上的æ�¡ä»¶å†³å®š 这个æ€�维一定è¦�è®°ä½�哦~ç»§ç»å‰©ä½™çš„æµ�程一级主管审批通过å��需è¦�åˆ¤æ–æ˜¯å�¦éœ€è¦�二级审批这时å�ˆæœ‰ä¸€ä¸ªæ�’他网关使用的æ�¡ä»¶å°±æ˜¯#{day3}或者#{day3}在第2æ¥ä¸zhang3 申请了 4天的å�‡æœŸäº�是走到了二级主管审批页é�¢ã€‚二级主管wang5 åœ¨å®¡æ‰¹ä»»åŠ¡åˆ—è¡¨ä¸æ‰¾åˆ°äº†zhang3的请å�‡ç”³è¯·ç„¶å��点击了通过。Task thirdTask taskService.createTaskQuery().taskAssignee(wang
.singleResult(); if (thirdTask ! null) { taskService.setVariable(thirdTask.getId(), result2, true); log.warn(用户任务完æˆ�æµ�程ID:{}, 任务å��ç§°:{}, id:{}, assignee:{}, thirdTask.getProcessInstanceId(), thirdTask.getName(), thirdTask.getId(), thirdTask.getAssignee(), thirdTask.getDelegationState()); taskService.complete(thirdTask.getId()); } else { log.warn(没有查到二级主管审批任务); }æ�¥ä¸‹æ�¥æµ�程上没有其他审批任务但是引æ“�ä¾�然会继ç»é©±åЍæµ�程如下图ä¸äºŒçº§ä¸»ç®¡å®¡æ‰¹ç»“æ�œé€šè¿‡æˆ–æ‹’ç»�分别进入到两个ä¸�å�Œçš„终点。值得一æ��的是上é�¢çš„代ç �仅仅是å�„个审批人在处ç�†å®¡æ‰¹ä»»åŠ¡æ—¶å¿…è¦�的代ç �ã€�通用的代ç �。如审批是å�¦é€šè¿‡è¿™ä¸€æµ�程å�˜é‡�完全å�¯ä»¥ç»Ÿä¸€è§„èŒƒæ— éœ€äºŒæ¬¡å¼€å�‘。例如 二级主管审批通过设置了 result2å®�际上å�¯ä»¥ä½¿ç”¨ 二级主管审批这个节点的id å��缀如 result_10æ�¥ä»£è¡¨æ‰§è¡Œç»“æ�œè§„范以å��æµ�程审批代ç �更为统一。新å¢�æµ�程模版时在审批任务节点审批通过或审批拒ç»�å�‡ä¸�需è¦�å†�次开å�‘代ç �。惊喜的事情是我们没有开å�‘任何一行æµ�程驱动和分支判定相关的代ç �。但是我们ä¾�然需è¦�处ç�†å‰�端页é�¢ã€‚å› ä¸ºè¯·å�‡ç”³è¯·é¡µé�¢ä¸Šä¸�å�Œçš„å�‡æœŸç±»å�‹éœ€è¦�的表å�•å�‚æ•°ä¸�å�Œéœ€è¦�æ–°å¢�å‰�端页é�¢æ–°å¢�å�‘èµ·æµ�程的å��端æ�¥å�£ã€‚相比整体的æµ�程æ�§åˆ¶ä»£ç �这部分开å�‘工作é‡�大大é™�ä½�难度更是大大é™�ä½�。æ�¥ä¸‹æ�¥æˆ‘æ��出一个问题如æ�œæ–°å¢�一个需求è¦�求请病å�‡çš„æ—¶å€™éœ€è¦�HRå®¡æ‰¹ä½ çŸ¥é�“如何修改æµ�程图支æŒ�新的处ç�†æµ�程å�—?很简å�•在审批通过终节点的å‰�é�¢å†�åŠ ä¸€ä¸ªæ�’他网关判æ–请å�‡ç±»å�‹ â€�带薪病å�‡â€œå¦‚æ�œæ�¡ä»¶é€šè¿‡åˆ™å¢�åŠ HR审批节点如æ�œæ�¡ä»¶ä¸�通过则直æ�¥èµ°åˆ° 审批通过的 终点。ä¸�需è¦�å¼€å�‘一行代ç �就能支æŒ�需求哦~有了工作æµ�引æ“� activiti ,æ–°å¢�和修改æµ�程 都å�˜å¾—é��常简å�•它帮我们完æˆ�了所有的æµ�程驱动和分支判定工作。 这就是工作æµ�引æ“�的价值之一。如何查看完整的执行æµ�程图通过æµ�程引æ“�ProcessEngineè�·å�–HistoryService通过æµ�程å®�例id拿到æµ�程执行的所有节点。执行记录如下图å�¯å®Œæ•´çœ‹åˆ°æµ�程执行的完整过程。ListHistoricActivityInstance activityInstanceList historyService.createHistoricActivityInstanceQuery().processInstanceId(instance.getId()).list(); for (HistoricActivityInstance historicActivityInstance : activityInstanceList) { log.warn(activityName:{},activityType:{}, assignee:{}, taskId:{}, historicActivityInstance.getActivityName(), historicActivityInstance.getActivityType(), historicActivityInstance.getAssignee(), historicActivityInstance.getTaskId());activiti 项目基础é…�置首先引入activiti pomdependency groupIdorg.activiti/groupId artifactIdactiviti-spring-boot-starter-basic/artifactId version
5.
2
0/version /dependency我使用的是activiti
x�套的Springboot starter parent是parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version
2.
4/version relativePath/ /parenté…�置数æ�®æº�和工作æµ�引æ“�é…�置类activiti 需è¦�使用方æ��供数æ�®åº“é…�置在项目å�¯åŠ¨æ—¶activiti 会自动检查数æ�®åº“是å�¦åŒ…å�«activiti 相关的表如æ�œä¸�包å�«ä¼šè‡ªåŠ¨å¸®ä½ å»ºè¡¨ã€‚åœ¨å¦ä¹ activiti çš„è¿‡ç¨‹ä¸æˆ‘没有安装MySQL而是使用H2 å†…å˜æ•°æ�®åº“该数æ�®åº“在Java进程ä¸éš�JVMå�Œç”Ÿå…±æ»æ— 需担心é‡�å¤�å�¯åŠ¨æ•°æ�®è¢«æ±¡æŸ“ç‰é—®é¢˜é��常适å�ˆå¦ä¹ activiti 的时候使用?xml version
0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beans xmlns:xsihttp://www.w
org/2001/XMLSchema-instance xmlns:contexthttp://www.springframework.org/schema/context xsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd bean iddataSource classorg.apache.commons.dbcp.BasicDataSource property namedriverClassName valueorg.h
Driver/ !--property nameurl valuejdbc:h2:mem:testdb;DB_CLOSE_DELAY-1;modeMySQL;TRACE_LEVEL_SYSTEM_OUT2/-- property nameurl valuejdbc:h2:mem:testdb;DB_CLOSE_DELAY-1;modeMySQL;/ /bean bean idprocessEngineConfiguration classorg.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration property namedataSource refdataSource/ property namedatabaseSchemaUpdate valuetrue/ /bean context:component-scan base-packagecom.muppet.activiti/ /beansH2 需è¦�çš„POM如下dependency groupIdcom.h2database/groupId artifactIdh2/artifactId scoperuntime/scope /dependency全部示例代ç �SpringBootTest(classes {ActivitiStartApplication.class}) class ActivitiStartApplicationTests { publicstaticfinal Logger log LoggerFactory.getLogger(ActivitiStartApplicationTests.class); Autowired private ApplyTaskListener applyTaskListener; Test void contextLoads() { System.out.println(å�¯åЍæˆ�功); ProcessEngine engine ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService engine.getRepositoryService(); RuntimeService runtimeService engine.getRuntimeService(); TaskService taskService engine.getTaskService(); HistoryService historyService engine.getHistoryService(); repositoryService.createDeployment().addClasspathResource(processes/apply.bpmn).deploy(); MapString, Object variableMap new HashMap(); variableMap.put(applyUser, zhang
; variableMap.put(supervisor, li
; variableMap.put(upperSupervisor, wang
; ProcessInstance instance runtimeService.startProcessInstanceByKey(apply_processor_1, variableMap); Task firstTask taskService.createTaskQuery().taskAssignee(zhang
.singleResult(); log.warn(用户任务完��程ID:{}, 任务�称 :{}, id:{}, assignee:{}, firstTask.getProcessInstanceId(), firstTask.getName(), firstTask.getId(), firstTask.getAssignee()); taskService.complete(firstTask.getId(), Maps.newHashMap(day,
); Task secondTask taskService.createTaskQuery().taskAssignee(li
.singleResult(); taskService.setVariable(secondTask.getId(), result1, true); log.warn(用户任务完��程ID:{}, 任务�称 :{}, id:{}, assignee:{}, secondTask.getProcessInstanceId(), secondTask.getName(), secondTask.getId(), secondTask.getAssignee()); taskService.complete(secondTask.getId()); Task thirdTask taskService.createTaskQuery().taskAssignee(wang
.singleResult(); if (thirdTask ! null) { taskService.setVariable(thirdTask.getId(), result2, true); log.warn(用户任务完æˆ�æµ�程ID:{}, 任务å��ç§°:{}, id:{}, assignee:{}, thirdTask.getProcessInstanceId(), thirdTask.getName(), thirdTask.getId(), thirdTask.getAssignee(), thirdTask.getDelegationState()); taskService.complete(thirdTask.getId()); } else { log.warn(没有查到二级主管审批任务); } log.warn(æµ�程执行过程如下); ListHistoricActivityInstance activityInstanceList historyService.createHistoricActivityInstanceQuery().processInstanceId(instance.getId()).list(); for (HistoricActivityInstance historicActivityInstance : activityInstanceList) { log.warn(activityName:{},activityType:{}, assignee:{}, taskId:{}, historicActivityInstance.getActivityName(), historicActivityInstance.getActivityType(), historicActivityInstance.getAssignee(), historicActivityInstance.getTaskId()); } } }activiti 工作æµ�引æ“�æ•°æ�®åº“设计为了ä¿�è¯�æµ�程的å�¯é� 性和å�¯æ�¢å¤�性工作æµ�引æ“�通常会将æµ�程å®�例的状æ€�和数æ�®æŒ�久化å˜å‚¨åˆ°ä¸ã€‚在æµ�程执行过程ä¸å¼•æ“�会ä¸�æ–地更新数æ�®åº“ä¸çš„状æ€�æ•°æ�®ã€‚activiti 共包å�«äº†ä¸€ç³»åˆ—用äº�å˜å‚¨æµ�程定义ã€�è¿�行时数æ�®ä»¥å�Šå�†å�²è®°å½•的表。
æµ�程定义相关表ACT_RE_*系列表主è¦�包括æµ�程定义Process Definitionsã€�æµ�程资æº�Resources和其他é�™æ€�ä¿¡æ�¯çš„å˜å‚¨ã€‚
è¿�行时数æ�®è¡¨ACT_RU_*ç³»åˆ—è¡¨è¿™äº›è¡¨å˜æ”¾äº†æµ�程å®�例执行过程ä¸çš„å®�æ—¶æ•°æ�®å¦‚任务Tasksã€�æµ�程å®�例Process Instancesã€�å�˜é‡�Variablesã€�执行对象Executionsç‰ã€‚
å�†å�²æ•°æ�®è¡¨ACT_HI_*系列表当æµ�程å®�例结æ�Ÿæˆ–达到特定æ�¡ä»¶æ—¶ç›¸å…³çš„è¿�行时数æ�®ä¼šè¢«è¿�移到å�†å�²è¡¨ä¸ä»¥ä¾›å��期审计ã€�报告分æ��之用。
身份和æ�ƒé™�表ACT_ID_*系列表主è¦�用äº�å˜å‚¨ç”¨æˆ·ã€�组以å�Šç›¸å…³çš„身份和æ�ƒé™�ä¿¡æ�¯ã€‚
其他辅助表包括事件日志表Event Logã€�作业å�Šå®šæ—¶å™¨è¡¨Job and Timer entitiesç‰å®ƒä»¬æœ�务äº�调度ã€�异æ¥å¤„ç�†ç‰åŠŸèƒ½éœ€æ±‚ã€‚å·¥ä½œæµ�引æ“�API 介ç»�ProcessEngine:表示Activiti工作æµ�引æ“�的入å�£ç”¨äº�è�·å�–å�„ç§�管ç�†APIæ“�作的对象。RepositoryService:用äº�管ç�†æµ�程定义的API包括æµ�ç¨‹çš„éƒ¨ç½²å’Œåˆ é™¤ç‰æ“�作。RuntimeService:用äº�管ç�†æµ�程å®�例的API包括å�¯åЍã€�æš‚å�œå’Œåˆ 除æµ�程å®�ä¾‹ç‰æ“�作。TaskService:用äº�管ç�†ä»»åŠ¡çš„API包括创建ã€�完æˆ�å’ŒæŸ¥è¯¢ä»»åŠ¡ç‰æ“�作。HistoryService:用äº�查询å�†å�²è®°å½•çš„API包括查询已完æˆ�的任务ã€�æµ�程å®�例和å�˜é‡�ç‰ä¿¡æ�¯ã€‚è¿™5个Service我们已ç»�很熟悉了ç�°åœ¨è·Ÿå¤§å®¶ä»‹ç»�这部分API大家应该更容易ç�†è§£äº†ã€‚å…¶ä¸ProcessEngine我们用æ�¥è�·å�–å�„ç±»Serviceç±»RepositoryService用æ�¥éƒ¨ç½²æµ�程图RuntimeService用æ�¥åˆ›å»ºæµ�程图å®�例ã€�TaskService用æ�¥æŸ¥è¯¢ä»»åŠ¡å’Œå®Œæˆ�任务HistoryService用æ�¥æŸ¥çœ‹æµ�程执行过程。什么是BPMNæµ�程图BPMN‌Business Process Modeling Notation‌是一ç§�æµ�ç¨‹å»ºæ¨¡çš„é€šç”¨å’Œæ ‡å‡†è¯è¨€â€Œç”¨æ�¥ç»˜åˆ¶ä¸šåŠ¡æµ�程图‌以便更好地让å�„部门之间ç�†è§£ä¸šåŠ¡æµ�程和相互关系。‌BPMN
0规范�2004年5月对外�布‌而BPMN
0æ ‡å‡†ç”±OMGäº�2011å¹´æ�¨å‡ºâ€Œå¯¹BPMN进行了é‡�新定义。‌Activiti 是由 jBPM 的创建者 Tom Baeyens 离开 JBoss 之å��建立的项目æ�„建在开å�‘ jBPM 版本 1 到 4 时积累的多年ç»�验的基础之上旨在创建下一代的 BPM 解决方案。å�Œæ—¶ Activiti 选择了 Apache 许å�¯ä¸€æ–¹é�¢æ˜¯å¸Œæœ› Activiti èƒ½æœ‰æ›´é•¿ä¹…çš„ç”Ÿå‘½åŠ›å› ä¸ºå®ƒä¸�å�—任何个人或是公å�¸çš„æ�§åˆ¶è€Œæ˜¯å±�äº�整个社区å�¦ä¸€æ–¹é�¢æ›´æ˜¯å¸Œæœ›è¿™ä¸ªå®½æ�¾çš„许å�¯èƒ½å¤Ÿè®© Activiti BPM 引æ“�å’Œ BPMN
0 被更广泛的采纳�使用和商业化。Idea actiBPM �件如何安装https://www.cnblogs.com/No2-explorer/p/
htmlIdea新建的æµ�程图是什么本质是一个XMLå�¯ä»¥é€šè¿‡BPMN å�¯è§†åŒ–工具解æ��如下XML代ç �是 请å�‡æµ�程图创建一个二级主管审批节点userTask activiti:assignee${upperSupervisor} activiti:asyncfalse activiti:exclusivetrue id_10 name二级主管审批/创建一个审批结æ�œçš„分支分支上包å�«è¿�æ�¥äº†å“ªä¸¤ä¸ªèŠ‚ç‚¹ä»¥å�Šåˆ†æ”¯çš„æ�¡ä»¶è¡¨è¾¾å¼�#{result2true}sequenceFlow id_19 sourceRef_17 targetRef_8 conditionExpression xsi:typetFormalExpression![CDATA[#{result2false}]]/conditionExpression /sequenceFlow sequenceFlow id_20 sourceRef_17 targetRef_11 conditionExpression xsi:typetFormalExpression![CDATA[#{result2true}]]/conditionExpression /sequenceFlow请å�‡æµ�程图完整XML?xml version
0 encodingUTF-8 standaloneyes? definitions xmlnshttp://www.omg.org/spec/BPMN/20100524/MODEL xmlns:activitihttp://activiti.org/bpmn xmlns:bpmndihttp://www.omg.org/spec/BPMN/20100524/DI xmlns:omgdchttp://www.omg.org/spec/DD/20100524/DC xmlns:omgdihttp://www.omg.org/spec/DD/20100524/DI xmlns:tnshttp://www.activiti.org/test xmlns:xsdhttp://www.w
org/2001/XMLSchema xmlns:xsihttp://www.w
org/2001/XMLSchema-instance expressionLanguagehttp://www.w
org/1999/XPath idm1723259512248 name targetNamespacehttp://www.activiti.org/test typeLanguagehttp://www.w
org/2001/XMLSchema process idapply_processor_1 isClosedfalse isExecutabletrue processTypeNone startEvent id_4 name开始 extensionElements activiti:executionListener classcom.muppet.activiti.listener.ApplyTaskListener eventend/ /extensionElements /startEvent userTask activiti:assignee#{applyUser} activiti:asyncfalse activiti:exclusivetrue id_5 name请�申请/ userTask activiti:assignee${supervisor} activiti:asyncfalse activiti:exclusivetrue id_6 name主管审批 extensionElements activiti:executionListener classcom.muppet.activiti.listener.ApplyTaskListener eventend/ /extensionElements /userTask exclusiveGateway gatewayDirectionUnspecified id_7 name一级审批结�/ endEvent id_8 name审批�通过 extensionElements activiti:executionListener classcom.muppet.activiti.listener.ApplyTaskListener eventend/ /extensionElements /endEvent exclusiveGateway gatewayDirectionUnspecified id_9 name天数验�2/ userTask activiti:assignee${upperSupervisor} activiti:asyncfalse activiti:exclusivetrue id_10 name二级主管审批/ endEvent id_11 name审批通过 extensionElements activiti:executionListener classcom.muppet.activiti.listener.ApplyTaskListener eventend/ /extensionElements /endEvent sequenceFlow id_2 sourceRef_4 targetRef_5/ sequenceFlow id_3 sourceRef_5 targetRef_6/ sequenceFlow id_12 sourceRef_6 targetRef_7/ sequenceFlow id_13 sourceRef_7 targetRef_8 conditionExpression xsi:typetFormalExpression![CDATA[#{result1false}]]/conditionExpression /sequenceFlow sequenceFlow id_14 sourceRef_7 targetRef_9 conditionExpression xsi:typetFormalExpression![CDATA[#{result1true}]]/conditionExpression /sequenceFlow sequenceFlow id_15 sourceRef_9 targetRef_10 conditionExpression xsi:typetFormalExpression![CDATA[#{day3}]]/conditionExpression /sequenceFlow sequenceFlow id_16 sourceRef_9 targetRef_11 conditionExpression xsi:typetFormalExpression![CDATA[#{day3}]]/conditionExpression /sequenceFlow exclusiveGateway gatewayDirectionUnspecified id_17 name审批结�2/ sequenceFlow id_18 sourceRef_10 targetRef_17/ sequenceFlow id_19 sourceRef_17 targetRef_8 conditionExpression xsi:typetFormalExpression![CDATA[#{result2false}]]/conditionExpression /sequenceFlow sequenceFlow id_20 sourceRef_17 targetRef_11 conditionExpression xsi:typetFormalExpression![CDATA[#{result2true}]]/conditionExpression /sequenceFlow /process bpmndi:BPMNDiagram documentationbackground#3C3F41;count1;horizontalcount1;orientation0;width
8
4;height
1
2;imageableWidth
8
4;imageableHeight
1
2;imageableX
0;imageableY
0 idDiagram-_1 nameNew Diagram bpmndi:BPMNPlane bpmnElementapply_processor_1 bpmndi:BPMNShape bpmnElement_4 idShape-_4 omgdc:Bounds height
3
0 width
3
0 x
5
0 y
1
0/ bpmndi:BPMNLabel omgdc:Bounds height
3
0 width
3
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNShape bpmndi:BPMNShape bpmnElement_5 idShape-_5 omgdc:Bounds height
5
0 width
8
0 x
4
0 y
2
0/ bpmndi:BPMNLabel omgdc:Bounds height
5
0 width
8
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNShape bpmndi:BPMNShape bpmnElement_6 idShape-_6 omgdc:Bounds height
5
0 width
8
0 x
5
0 y
3
0/ bpmndi:BPMNLabel omgdc:Bounds height
5
0 width
8
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNShape bpmndi:BPMNShape bpmnElement_7 idShape-_7 isMarkerVisiblefalse omgdc:Bounds height
3
0 width
3
0 x
5
0 y
4
0/ bpmndi:BPMNLabel omgdc:Bounds height
3
0 width
3
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNShape bpmndi:BPMNShape bpmnElement_8 idShape-_8 omgdc:Bounds height
3
0 width
3
0 x
2
0 y
8
0/ bpmndi:BPMNLabel omgdc:Bounds height
3
0 width
3
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNShape bpmndi:BPMNShape bpmnElement_9 idShape-_9 isMarkerVisiblefalse omgdc:Bounds height
3
0 width
3
0 x
5
0 y
6
0/ bpmndi:BPMNLabel omgdc:Bounds height
3
0 width
3
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNShape bpmndi:BPMNShape bpmnElement_10 idShape-_10 omgdc:Bounds height
5
0 width
9
0 x
4
0 y
7
0/ bpmndi:BPMNLabel omgdc:Bounds height
5
0 width
9
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNShape bpmndi:BPMNShape bpmnElement_11 idShape-_11 omgdc:Bounds height
3
0 width
3
0 x
7
0 y
6
0/ bpmndi:BPMNLabel omgdc:Bounds height
3
0 width
3
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNShape bpmndi:BPMNShape bpmnElement_17 idShape-_17 isMarkerVisiblefalse omgdc:Bounds height
3
0 width
3
0 x
5
0 y
8
0/ bpmndi:BPMNLabel omgdc:Bounds height
3
0 width
3
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNShape bpmndi:BPMNEdge bpmnElement_13 idBPMNEdge__13 sourceElement_7 targetElement_8 omgdi:waypoint x
5
1953352769677 y
5
0000000000001/ omgdi:waypoint x
3
0 y
7
0/ omgdi:waypoint x
3
0 y
8
0808012104277/ bpmndi:BPMNLabel omgdc:Bounds height
0 width
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNEdge bpmndi:BPMNEdge bpmnElement_12 idBPMNEdge__12 sourceElement_6 targetElement_7 omgdi:waypoint x
5
9999999999999 y
4
97894395853575/ omgdi:waypoint x
5
9999999999999 y
4
19533527696785/ bpmndi:BPMNLabel omgdc:Bounds height
0 width
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNEdge bpmndi:BPMNEdge bpmnElement_15 idBPMNEdge__15 sourceElement_9 targetElement_10 omgdi:waypoint x
5
9999999999999 y
6
3606171769437/ omgdi:waypoint x
5
9999999999999 y
7
6793002915451/ bpmndi:BPMNLabel omgdc:Bounds height
0 width
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNEdge bpmndi:BPMNEdge bpmnElement_14 idBPMNEdge__14 sourceElement_7 targetElement_9 omgdi:waypoint x
5
4999999999999 y
5
4297052154194/ omgdi:waypoint x
5
4999999999999 y
6
2445273261599/ bpmndi:BPMNLabel omgdc:Bounds height
0 width
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNEdge bpmndi:BPMNEdge bpmnElement_16 idBPMNEdge__16 sourceElement_9 targetElement_11 omgdi:waypoint x
5
8934865508442 y
6
0/ omgdi:waypoint x
7
6793107624761 y
6
0/ bpmndi:BPMNLabel omgdc:Bounds height
0 width
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNEdge bpmndi:BPMNEdge bpmnElement_19 idBPMNEdge__19 sourceElement_17 targetElement_8 omgdi:waypoint x
5
0000000000001 y
8
0919987042433/ omgdi:waypoint x
4
0 y
8
0/ omgdi:waypoint x
3
0 y
8
0256933063517/ bpmndi:BPMNLabel omgdc:Bounds height
0 width
0 x
0 y-
1
0/ /bpmndi:BPMNLabel /bpmndi:BPMNEdge bpmndi:BPMNEdge bpmnElement_18 idBPMNEdge__18 sourceElement_10 targetElement_17 omgdi:waypoint x
5
0000000000001 y
7
9649065975595/ omgdi:waypoint x
5
0000000000001 y
8
6344887161214/ bpmndi:BPMNLabel omgdc:Bounds height
0 width
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNEdge bpmndi:BPMNEdge bpmnElement_2 idBPMNEdge__2 sourceElement_4 targetElement_5 omgdi:waypoint x
5
0 y
2
23782176749842/ omgdi:waypoint x
5
0 y
2
1689882302127/ bpmndi:BPMNLabel omgdc:Bounds height
0 width
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNEdge bpmndi:BPMNEdge bpmnElement_3 idBPMNEdge__3 sourceElement_5 targetElement_6 omgdi:waypoint x
5
0 y
3
5907569376957/ omgdi:waypoint x
5
0 y
3
6933376525213/ bpmndi:BPMNLabel omgdc:Bounds height
0 width
0 x
0 y
0/ /bpmndi:BPMNLabel /bpmndi:BPMNEdge bpmndi:BPMNEdge bpmnElement_20 idBPMNEdge__20 sourceElement_17 targetElement_11 omgdi:waypoint x
5
3655112838787 y
8
0/ omgdi:waypoint x
6
0 y
7
0/ omgdi:waypoint x
7
6793107624761 y
6
0/ bpmndi:BPMNLabel omgdc:Bounds height
0 width
1
0 x
0 y
7