业务可视化-让你的流程图"Run"起来 - nobuglady
source link: https://www.cnblogs.com/nobuglady/p/16423995.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
前言
最近在研究业务可视化的问题,在日常的工作中,流程图和代码往往是分开管理的。
一个被维护多次的系统,到最后流程图和代码是否匹配这个都很难说。
一转眼三年过去了,目前这个想法已经逐步落地实现变成代码。
问题
对于简单的流程
a -> b -> c |
可以很容易用代码来实现
// 执行a a(); // 执行b b(); // 执行c c(); |
对于并行的流程
a -> b a -> c |
这个就要多线程框架来实现
// 执行a a(); // a结束后执行b new Thread(b).start(); // a结束后执行c new Thread(c).start(); |
对于分支合并的流程
a -> b a -> c b -> d c -> d |
// 执行a a(); // a结束后执行b new Thread(b).start(); // a结束后执行c new Thread(c).start(); // 等待b,c结束 waitComplete(b,c); // 执行d d(); |
a(); b(); c(); d(); |
调查
实现
首先要有一个绘制流程图的界面。并且能够将流程图转化为json格式。
这里我选择了Vis.js的network。
可以编辑简单流程,如下
还可以实现流程图和json之间的互转。
我们把这些节点的基本信息拿到,就可以得到一张图,然后通过程序遍历这张图的每个节点,即可达到运行流程图的效果。
接下来就是流程图的节点与Java的方法绑定了。
我做了一个Annotation来绑定流程图节点,
public @interface Node { String id() default "" ; String label() default "" ; } |
节点得到运行开始事件后,拿到要运行的节点ID和名称,查找对应的类的Annotation对应的方法,如找到则运行该方法。
public int execute(String flowId, String nodeId, String historyId, HistoryNodeEntity nodeEntity) throws Exception{ String nodeName = nodeEntity.getNodeName(); System.out.println( "execute:" + nodeId); System.out.println( "node name:" + nodeEntity.getNodeName()); Method methods[] = this .getClass().getMethods(); if (methods != null ) { for (Method method:methods) { Node node = method.getAnnotation(Node. class ); if (node != null ) { if (node.id().equals(nodeId) || node.label().equals(nodeName)) { try { method.invoke( this ); return 0 ; } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); throw e; } } } } } return 0 ; } |
我们需要做一个继承自FlowRunner的类,里面的方法和flow的节点绑定,和一个flow的配置文件,放在相同的目录下。
MyFlow1.java
public class MyFlow1 extends FlowRunner { @Node (label= "a" ) public void process_a() { System.out.println( "processing a" ); } @Node (label= "b" ) public void process_b() { System.out.println( "processing b" ); } @Node (label= "c" ) public void process_c() { System.out.println( "processing c" ); } @Node (label= "d" ) public void process_c() { System.out.println( "processing d" ); } } |
MyFlow1.json
{ "flowId" : "123" , "nodes" : [ { "id" : "1" , "label" : "start" }, { "id" : "2" , "label" : "a" }, { "id" : "0b5ba9df-b6c7-4752-94e2-debb6104015c" , "label" : "b" }, { "id" : "29bc32c7-acd8-4893-9410-e9895da38b2e" , "label" : "c" } ], "edges" : [ { "id" : "1" , "from" : "1" , "to" : "2" , "arrows" : "to" }, { "id" : "078ffa82-5eff-4d33-974b-53890f2c9a18" , "from" : "1" , "to" : "0b5ba9df-b6c7-4752-94e2-debb6104015c" , "arrows" : "to" }, { "id" : "90663193-7077-4aca-9011-55bc8745403f" , "from" : "2" , "to" : "29bc32c7-acd8-4893-9410-e9895da38b2e" , "arrows" : "to" }, { "id" : "a6882e25-c07a-4abd-907e-e269d4eda0ec" , "from" : "0b5ba9df-b6c7-4752-94e2-debb6104015c" , "to" : "29bc32c7-acd8-4893-9410-e9895da38b2e" , "arrows" : "to" } ] } |
然后通过下面的代码来启动流程。
MyFlow1 myFlow1 = new MyFlow1(); myFlow1.startFlow(); |
系统关闭时,通过下面的代码关闭流程管理器
FlowStarter.shutdown(); |
运行
正常结束日志如下
Ready queue thread started.
Complete queue thread started.
json:
{"flowId":"123","nodes":[{"id":"1","label":"a"},{"id":"2","label":"b"},{"id":"0b5ba9df-b6c7-4752-94e2-debb6104015c","label":"c"},{"id":"29bc32c7-acd8-4893-9410-e9895da38b2e","label":"d"}],"edges":[{"id":"1","from":"1","to":"2","arrows":"to"},{"id":"078ffa82-5eff-4d33-974b-53890f2c9a18","from":"1","to":"0b5ba9df-b6c7-4752-94e2-debb6104015c","arrows":"to"},{"id":"90663193-7077-4aca-9011-55bc8745403f","from":"2","to":"29bc32c7-acd8-4893-9410-e9895da38b2e","arrows":"to"},{"id":"a6882e25-c07a-4abd-907e-e269d4eda0ec","from":"0b5ba9df-b6c7-4752-94e2-debb6104015c","to":"29bc32c7-acd8-4893-9410-e9895da38b2e","arrows":"to"}]}
execute:1
node name:a
processing a
execute:2
node name:b
processing b
execute:0b5ba9df-b6c7-4752-94e2-debb6104015c
node name:c
processing c
execute:29bc32c7-acd8-4893-9410-e9895da38b2e
node name:d
processing d
Complete success.
json:
{"nodes":[{"id": "1","label": "a" ,"color": "#36AE7C"},{"id": "2","label": "b" ,"color": "#36AE7C"},{"id": "0b5ba9df-b6c7-4752-94e2-debb6104015c","label": "c" ,"color": "#36AE7C"},{"id": "29bc32c7-acd8-4893-9410-e9895da38b2e","label": "d" ,"color": "#36AE7C"}],"edges":[{"id": "1","from": "1","to": "2","arrows": "to"},{"id": "078ffa82-5eff-4d33-974b-53890f2c9a18","from": "1","to": "0b5ba9df-b6c7-4752-94e2-debb6104015c","arrows": "to"},{"id": "90663193-7077-4aca-9011-55bc8745403f","from": "2","to": "29bc32c7-acd8-4893-9410-e9895da38b2e","arrows": "to"},{"id": "a6882e25-c07a-4abd-907e-e269d4eda0ec","from": "0b5ba9df-b6c7-4752-94e2-debb6104015c","to": "29bc32c7-acd8-4893-9410-e9895da38b2e","arrows": "to"}]}
流程执行结束后,会输出执行结果和运行后的流程图状态。
可以直接将json贴到下面的位置,查看看结果(绿色表示正常结束,红色表示异常结束,白色表示等待执行)。
异常结束日志如下
Ready queue thread started.
Complete queue thread started.
json:
{"flowId":"123","nodes":[{"id":"1","label":"a"},{"id":"2","label":"b"},{"id":"0b5ba9df-b6c7-4752-94e2-debb6104015c","label":"c"},{"id":"29bc32c7-acd8-4893-9410-e9895da38b2e","label":"d"}],"edges":[{"id":"1","from":"1","to":"2","arrows":"to"},{"id":"078ffa82-5eff-4d33-974b-53890f2c9a18","from":"1","to":"0b5ba9df-b6c7-4752-94e2-debb6104015c","arrows":"to"},{"id":"90663193-7077-4aca-9011-55bc8745403f","from":"2","to":"29bc32c7-acd8-4893-9410-e9895da38b2e","arrows":"to"},{"id":"a6882e25-c07a-4abd-907e-e269d4eda0ec","from":"0b5ba9df-b6c7-4752-94e2-debb6104015c","to":"29bc32c7-acd8-4893-9410-e9895da38b2e","arrows":"to"}]}
execute:1
node name:a
processing a
execute:2
node name:b
processing b
execute:0b5ba9df-b6c7-4752-94e2-debb6104015c
node name:c
processing c
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at io.github.nobuglady.network.fw.FlowRunner.execute(FlowRunner.java:49)
at io.github.nobuglady.network.fw.executor.NodeRunner.run(NodeRunner.java:93)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.RuntimeException: test
at io.github.nobuglady.network.MyFlow1.process_b(MyFlow1.java:16)
... 11 more
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at io.github.nobuglady.network.fw.FlowRunner.execute(FlowRunner.java:49)
at io.github.nobuglady.network.fw.executor.NodeRunner.run(NodeRunner.java:93)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.RuntimeException: test
at io.github.nobuglady.network.MyFlow1.process_b(MyFlow1.java:16)
... 11 more
Complete error.
json:
{"nodes":[{"id": "1","label": "a" ,"color": "#36AE7C"},{"id": "2","label": "b" ,"color": "#EB5353"},{"id": "0b5ba9df-b6c7-4752-94e2-debb6104015c","label": "c" ,"color": "#36AE7C"},{"id": "29bc32c7-acd8-4893-9410-e9895da38b2e","label": "d" ,"color": "#E8F9FD"}],"edges":[{"id": "1","from": "1","to": "2","arrows": "to"},{"id": "078ffa82-5eff-4d33-974b-53890f2c9a18","from": "1","to": "0b5ba9df-b6c7-4752-94e2-debb6104015c","arrows": "to"},{"id": "90663193-7077-4aca-9011-55bc8745403f","from": "2","to": "29bc32c7-acd8-4893-9410-e9895da38b2e","arrows": "to"},{"id": "a6882e25-c07a-4abd-907e-e269d4eda0ec","from": "0b5ba9df-b6c7-4752-94e2-debb6104015c","to": "29bc32c7-acd8-4893-9410-e9895da38b2e","arrows": "to"}]}
流程执行结束后,会输出执行结果和运行后的流程图状态。
可以直接将json贴到下面的位置,查看看结果(绿色表示正常结束,红色表示异常结束,白色表示等待执行)。
源码:https://github.com/nobuglady/nobuglady-network
感谢阅读。欢迎Star。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK