foolflow
经常遇到一种场景,整个业务涉及多个状态,每个环节涉及的业务可能由用户触发,可能同步或者异步的,或者可能是定时任务触发。代码散落在各个位置,而且文档丢失,想梳理整个流程的时候就无从下手。该组件就是解决这种痛点的
源码
https://gitee.com/cangjingge/foolflow
介绍
傻瓜工作流;放弃复杂设计,放弃bpmn规范,傻瓜式,足够简单;类似一个有限状态机,比状态机强,介于状态机和工作流之间。
在应对一些状态较多的简单场景,又不想引入繁重的工作流引擎的时候可以使用。不用学习bpmn规范,没有心智负担;使用后使代码条理性更强,整个业务的各个阶段的代码不再散落在项目的各个位置。方便管理
模型
由点node和line来组成一个工作流,整个流程驱动方式为通过当前节点+动作的方式进行驱动;支持单任务和批量任务;
业务逻辑通过ActionExecutor接口进行实现
使用方式
<dependency>
<groupId>com.chungkui</groupId>
<artifactId>foolflow</artifactId>
<version>1.0</version>
</dependency>
使用说明
实现一下接口来写每个动作的逻辑
public interface ActionExecutor<S, A> {
ActionResult execute(ActionContext actionContext, Node<S> from, Node<S> target, Line<S, A> line);
}
字符串驱动
Flow flow = new FlowBuilder<String, String>().id("请假")
.addNode("1", "填写请假表单")
.addNode("2", "部门领导审批")
.addNode("3", "中心领导审批")
.addNode("4", "完成")
.addLine("1", "2", "submit", "提交", submitFormAction)
.addLine("2", "3", "yes", "同意", shenpiAction)
.addLine("3", "4", "yes", "同意", shenpiAction)
.addLine("3", "2", "no", "拒绝", shenpiAction).build();
FlowEngine flowEngine = new DefaultFlowEngineImpl();
flowEngine.work(flow, "3", "yes").getStatus().name()
枚举驱动
Flow<StatusEnum, ActionEnum> flow = new FlowBuilder<StatusEnum, ActionEnum>().id("请假")
.addNode(StatusEnum.S1, "填写请假表单")
.addNode(StatusEnum.S2, "部门领导审批")
.addNode(StatusEnum.S3, "完成")
.addLine(StatusEnum.S1, StatusEnum.S2, ActionEnum.A1, "提交", submitfillform)
.addLine(StatusEnum.S2, StatusEnum.S3, ActionEnum.A2, "同意", lingdaoshenp)
.build();
FlowEngine<StatusEnum, ActionEnum> flowEngine = new DefaultFlowEngineImpl();
flowEngine.work(flow, StatusEnum.S1, ActionEnum.A1, new ActionContext())
flowEngine.work(flow, StatusEnum.S2, ActionEnum.A2, new ActionContext())
其中的各个action动作就是你的业务代码;只需要实现ActionExecutor接口在execute中实现业务逻辑即可
public interface ActionExecutor<S, A> {
ActionResult execute(ActionContext actionContext, Node<S> from, Node<S> target, Line<S, A> line);
}
spring 中使用
注册两个bean
@Bean
FlowContext flowContext() {
return new SpringFlowContext();
}
@Bean
FlowEngine flowEngine() {
return new DefaultFlowEngineImpl(flowContext());
}
注册动作执行器
@Service
public class TestActionImpl implements ActionExecutor {
@Override
public ActionResult execute(ActionContext actionContext, Node node, Node node1, Line line) {
System.out.println(node.getName() + "-" + line.getName() + "->" + node1.getName());
return DefaultActionResult.completed(actionContext,node1);
}
}
注册流程实例
@Component
public class QingjiaFlow extends FlowFactoryBean {
@Autowired
ActionExecutor testActionImpl;
@Override
public Flow buildFlow() {
return new FlowBuilder<String, String>().id("f1")
.addNode("1", "填写请假表单")
.addNode("2", "部门领导审批")
.addNode("3", "中心领导审批")
.addNode("4", "完成")
.addLine("1", "2", "submit", "提交", testActionImpl)
.addLine("2", "3", "yes", "同意", testActionImpl)
.addLine("3", "4", "yes", "同意", testActionImpl)
.addLine("3", "2", "no", "拒绝", testActionImpl).build();
}
}
触发流程
@Autowired
FlowEngine flowEngine;
@GetMapping(path = "/")
public Object index(ModelMap map) {
return flowEngine.work("qingjiaFlow","1","submit",null);
}