大家好,我是陶朱公Boy。
前言
于是就有小伙伴私信我,自己项目也考虑引入cola-statemachine这款状态机,但网上资料实在太少,能不能系统的介绍一下如何使用这款工具。
读者有需求,是必须要满足的,谁叫



StateMachineBuilder<ProcessStatusEnum, NodeTypeEnum, Context> builder = StateMachineBuilderFactory.create(); builder.internalTransition().within(ProcessStatusEnum.INIT).on(NodeTypeEnum.HEAD).when(alwaysTrue()).perform(doNextProcessStatus()); builder.externalTransition().from(ProcessStatusEnum.INIT).to(END).on(NodeTypeEnum.HEAD).when(checkNextNodeIfEndComponet()).perform(doNextProcessStatus()); builder.externalTransition().from(ProcessStatusEnum.SOURCE_YUNYIN).to(ProcessStatusEnum.SUBMIT_APPLY_PASS).on(NodeTypeEnum.SUBMIT_APPLY_COMPONET).when(checkIfPass()).perform(doNextProcessStatus()); builder.externalTransition().from(ProcessStatusEnum.SOURCE_YUNYIN).to(ProcessStatusEnum.SUBMIT_APPLY_NOT_PASS).on(NodeTypeEnum.SUBMIT_APPLY_COMPONET).when(checkIfNotPass()).perform(doNextProcessStatus()); builder.externalTransition().from(ProcessStatusEnum.SOURCE_FK).to(ProcessStatusEnum.FK_PASS).on(NodeTypeEnum.FK_COMPONET).when(checkIfPass()).perform(doNextProcessStatus()); builder.externalTransition().from(ProcessStatusEnum.SOURCE_FK).to(ProcessStatusEnum.FK_AUDIT_NOT_PASS).on(NodeTypeEnum.FK_COMPONET).when(checkIfNotPass()).perform(doNextProcessStatus()); builder.externalTransition().from(ProcessStatusEnum.SOURCE_FK).to(ProcessStatusEnum.FK_REFUSE).on(NodeTypeEnum.FK_COMPONET).when(checkIfRefuse()).perform(doNextProcessStatus()); builder.externalTransition().from(ProcessStatusEnum.SOURCE_CW).to(ProcessStatusEnum.CW_PASS).on(NodeTypeEnum.CW_COMPONET).when(checkIfPass()).perform(doNextProcessStatus()); builder.externalTransition().from(ProcessStatusEnum.SOURCE_CW).to(ProcessStatusEnum.CW_NOT_PASS).on(NodeTypeEnum.CW_COMPONET).when(checkIfNotPass()).perform(doNextProcessStatus()); builder.externalTransition().from(ProcessStatusEnum.SOURCE_CW).to(ProcessStatusEnum.CW_REFUSE).on(NodeTypeEnum.CW_COMPONET).when(checkIfRefuse()).perform(doNextProcessStatus()); builder.externalTransition().from(ProcessStatusEnum.SOURCE_AUDIT_COMPLETE).to(ProcessStatusEnum.AUDIT_TERMINATE).on(NodeTypeEnum.AUDIT_TERMINATE).when(alwaysTrue()).perform(doNextProcessStatus()); builder.externalTransition().from(SOURCE_OP_CHANGE_LICENSE).to(ProcessStatusEnum.UPDATE_LICENSE_SUCCESS).on(NodeTypeEnum.CHANGE_LICENSE_COMPONET).when(checkIfPass()).perform(doNextProcessStatus()); builder.externalTransition().from(SOURCE_OP_CHANGE_LICENSE).to(ProcessStatusEnum.UPDATE_LICENSE_FAILURE).on(NodeTypeEnum.CHANGE_LICENSE_COMPONET).when(checkIfNotPass()).perform(doNextProcessStatus()); builder.externalTransition().from(SOURCE_END).to(END).on(NodeTypeEnum.TAIL).when(checkCurrentNodeIfEndComponet()).perform(doNextProcessStatus()); return builder.build("processStatusMachine");
github地址:https://github.com/alibaba/COLA/tree/master/cola-components/cola-component-statemachine目前在github上:Fork:2.4k;Star:8.8k

<dependency> <groupId>com.alibaba.cola</groupId> <artifactId>cola-component-statemachine</artifactId> <version>4.3.1</version> </dependency>
@Configuration public class StateMachineRegist { private final String STATE_MACHINE_ID="stateMachineId"; /** * 构建状态机实例 */ @Bean public StateMachine<ApplyStatusEnum, Event, LeaveContext> stateMachine() { StateMachineBuilder<ApplyStatusEnum, Event, LeaveContext> stateMachineBuilder = StateMachineBuilderFactory.create(); //员工请假触发事件 //源状态和目标状态一致,我们可以用内部流转表示 stateMachineBuilder.internalTransition().within(ApplyStatusEnum.LEAVE_SUBMIT).on(Event.EMPLOYEE_SUBMIT).perform(doAction()); //部门主管审批触发事件(依赖上一个源状态:LEAVE_SUBMIT) stateMachineBuilder.externalTransition().from(ApplyStatusEnum.LEAVE_SUBMIT).to(ApplyStatusEnum.LEADE_AUDIT_PASS).on(Event.DIRECTLEADER_AUDIT).when(checkIfPass()).perform(doAction()); stateMachineBuilder.externalTransition().from(ApplyStatusEnum.LEAVE_SUBMIT).to(ApplyStatusEnum.LEADE_AUDIT_REFUSE).on(Event.DIRECTLEADER_AUDIT).when(checkIfNotPass()).perform(doAction()); //hr事件触发(依赖上一个源状态:LEADE_AUDIT_PASS) stateMachineBuilder.externalTransition().from(ApplyStatusEnum.LEADE_AUDIT_PASS).to(ApplyStatusEnum.HR_PASS).on(Event.HR_AUDIT).when(checkIfPass()).perform(doAction()); stateMachineBuilder.externalTransition().from(ApplyStatusEnum.LEADE_AUDIT_PASS).to(ApplyStatusEnum.HR_REFUSE).on(Event.HR_AUDIT).when(checkIfNotPass()).perform(doAction()); return stateMachineBuilder.build(STATE_MACHINE_ID); } }

StateMachine<ApplyStatusEnum, Event, LeaveContext> stateMachine = StateMachineFactory.get("leaveStateMachineId");
ApplyStatusEnum state=stateMachine.fireEvent(ApplyStatusEnum.LEAVE_SUBMIT, Event.EMPLOYEE_SUBMIT,context);
@DisplayName("员工提交请假申请单") @Test public void employSubmitRequest(){ StateMachine<ApplyStatusEnum, Event, LeaveContext> stateMachine = StateMachineFactory.get("leaveStateMachineId"); LeaveContext context = new LeaveContext(); ApplyStatusEnum state=stateMachine.fireEvent(ApplyStatusEnum.LEAVE_SUBMIT, Event.EMPLOYEE_SUBMIT,context); Assert.assertEquals(ApplyStatusEnum.LEAVE_SUBMIT.getCode(),state.getCode()); } @DisplayName("部门主管审批通过") @Test public void leaderAuditPass(){ StateMachine<ApplyStatusEnum, Event, LeaveContext> stateMachine = StateMachineFactory.get("leaveStateMachineId"); LeaveContext context = new LeaveContext(); //主管审批通过 context.setIdea(0); ApplyStatusEnum state=stateMachine.fireEvent(ApplyStatusEnum.LEAVE_SUBMIT, Event.DIRECTLEADER_AUDIT,context); Assert.assertEquals(ApplyStatusEnum.LEADE_AUDIT_PASS.getCode(),state.getCode()); } @DisplayName("部门主管审批不通过") @Test public void leaderAuditNotPass(){ StateMachine<ApplyStatusEnum, Event, LeaveContext> stateMachine = StateMachineFactory.get("leaveStateMachineId"); LeaveContext context = new LeaveContext(); //主管审批不通过 context.setIdea(1); ApplyStatusEnum state=stateMachine.fireEvent(ApplyStatusEnum.LEAVE_SUBMIT, Event.DIRECTLEADER_AUDIT,context); Assert.assertEquals(ApplyStatusEnum.LEADE_AUDIT_REFUSE.getCode(),state.getCode()); } @DisplayName("HR审批通过") @Test public void hrAuditPass(){ StateMachine<ApplyStatusEnum, Event, LeaveContext> stateMachine = StateMachineFactory.get("leaveStateMachineId"); LeaveContext context = new LeaveContext(); //HR通过 context.setIdea(0); ApplyStatusEnum state=stateMachine.fireEvent(ApplyStatusEnum.LEADE_AUDIT_PASS, Event.HR_AUDIT,context); Assert.assertEquals(ApplyStatusEnum.HR_PASS.getCode(),state.getCode()); } @DisplayName("HR审批不通过") @Test public void hrAuditNotPass(){ StateMachine<ApplyStatusEnum, Event, LeaveContext> stateMachine = StateMachineFactory.get("leaveStateMachineId"); LeaveContext context = new LeaveContext(); //HR审批不通过 context.setIdea(1); ApplyStatusEnum state=stateMachine.fireEvent(ApplyStatusEnum.LEADE_AUDIT_PASS, Event.HR_AUDIT,context); Assert.assertEquals(ApplyStatusEnum.HR_REFUSE.getCode(),state.getCode()); }
LEAVE_SUBMIT(1,"已申请"), LEADE_AUDIT_PASS(2,"直属领导审批通过"), LEADE_AUDIT_REFUSE(3,"直属领导审批失败"), HR_PASS(4,"HR审批通过"), HR_REFUSE(5,"HR审批拒绝");

//StateMachine public class StateMachineImpl<S,E,C> implements StateMachine<S, E, C> { private String machineId; //一个状态机持有多个状态(from、to) private final Map<S, State<S,E,C>> stateMap; ... } //State public class StateImpl<S,E,C> implements State<S,E,C> { protected final S stateId; //同一个Event可以触发多个Transition private Map<E, List<Transition<S, E,C>>> transitions = new HashMap<>(); ... } //Transition public class TransitionImpl<S,E,C> implements Transition<S,E,C> { //源状态 private State<S, E, C> source; //目标状态 private State<S, E, C> target; //事件 private E event; //条件 private Condition<C> condition; //动作 private Action<S,E,C> action; ... }
@Override public S fireEvent(S sourceStateId, E event, C ctx) { isReady(); //根据sourceStateId找到符合条件的Transition Transition<S, E, C> transition = routeTransition(sourceStateId, event, ctx); if (transition == null) { Debugger.debug("There is no Transition for " + event); failCallback.onFail(sourceStateId, event, ctx); return sourceStateId; } //找到transition后执行transit方法(最终执行Action后返回目标State) return transition.transit(ctx, false).getId(); }
/** * 路由Transition * @param sourceStateId 源状态ID * @param event 事件 * @param ctx 上下文参数 * @return */ private Transition<S, E, C> routeTransition(S sourceStateId, E event, C ctx) { //根据源状态ID查找源状态实例 State sourceState = getState(sourceStateId); //查找源状态实例下的流转列表 List<Transition<S, E, C>> transitions = sourceState.getEventTransitions(event); if (transitions == null || transitions.size() == 0) { return null; } Transition<S, E, C> transit = null; for (Transition<S, E, C> transition : transitions) { if (transition.getCondition() == null) { transit = transition; } else if (transition.getCondition().isSatisfied(ctx)) { //一旦匹配when函数内的触发条件,返回transition transit = transition; break; } } return transit; }
@Override public State<S, E, C> transit(C ctx, boolean checkCondition) { Debugger.debug("Do transition: "+this); this.verify(); //checkCondition为false或不指定when触发条件亦或匹配when触发条件;都将执行自定义的perform函数 if (!checkCondition || condition == null || condition.isSatisfied(ctx)) { //如果自定义的perform函数有指定,将执行perform函数 if(action != null){ action.execute(source.getId(), target.getId(), event, ctx); } return target; } Debugger.debug("Condition is not satisfied, stay at the "+source+" state "); return source; }
如果这篇文章你看了对你有帮助或启发,麻烦点赞、关注一下作者。你的肯定是作者创作源源不断的动力。

里面不仅汇集了硬核的干货技术、还汇集了像左耳朵耗子、张朝阳总结的高效学习方法论、职场升迁窍门、软技能。希望能辅助你达到你想梦想之地!
公众号内回复关键字“电子书”下载pdf格式的电子书籍(JAVAEE、Spring、JVM、并发编程、Mysql、Linux、kafka、分布式等)、“开发手册”获取阿里开发手册2本、"面试"获取面试PDF资料。
评论已关闭。