ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

业务可视化-让你的流程图"Run"起来

2022-07-01 21:36:56  阅读:176  来源: 互联网

标签:Run 流程图 b6c7 arrows label base 可视化 java id


前言

最近在研究业务可视化的问题,在日常的工作中,流程图和代码往往是分开管理的。

一个被维护多次的系统,到最后流程图和代码是否匹配这个都很难说。

于是一直有一个想法,让程序直接读流程图,根据流程图的配置来决定程序运行的顺序。

一转眼三年过去了,目前这个想法已经逐步落地实现变成代码。

问题

对于简单的流程

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();
去除了Fork-Join的麻烦,也没有改变业务执行顺序,但和流程图稍有出入。   于是想到能不能有个框架来控制a,b,c,d的运行顺序呢? 也就我们只需要编写a,b,c,d的单体,执行顺序变成可配置。  

调查 

于是想到各种工作流框架和job执行框架可以满足这个需求,但是太重了。 为了简单的需求,引入庞大的工作流或者job执行引擎,无疑是每个项目都不能接受的。   于是,决定手写一个轻量的,即可以控制程序执行流程,又可以通过图形界面编辑程序流程的框架。  

实现

首先要有一个绘制流程图的界面。并且能够将流程图转化为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。

 

标签:Run,流程图,b6c7,arrows,label,base,可视化,java,id
来源: https://www.cnblogs.com/nobuglady/p/16423995.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有