├── .gitignore ├── README.md ├── doc ├── function.png └── wechat.jpg ├── pom.xml ├── service-flow-denpendencies └── pom.xml ├── service-flow-sample ├── pom.xml ├── service-flow-sample-common │ ├── pom.xml │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── service │ │ │ └── flow │ │ │ └── sample │ │ │ └── common │ │ │ ├── component │ │ │ └── TestComponent.java │ │ │ ├── hash │ │ │ ├── HashNodeHandler.java │ │ │ └── HashTest.java │ │ │ ├── model │ │ │ ├── TestInput.java │ │ │ ├── TestOutput.java │ │ │ └── TestTemp.java │ │ │ ├── test1 │ │ │ ├── Test1Component.java │ │ │ ├── Test1Input.java │ │ │ ├── Test1Output.java │ │ │ └── Test1Temp.java │ │ │ ├── test2 │ │ │ ├── Test2Component.java │ │ │ ├── Test2Input.java │ │ │ ├── Test2Output.java │ │ │ └── Test2Temp.java │ │ │ ├── test3 │ │ │ ├── Test3Component.java │ │ │ ├── Test3Input.java │ │ │ ├── Test3Output.java │ │ │ └── Test3Temp.java │ │ │ └── test4 │ │ │ ├── MethodComponent.java │ │ │ ├── RefundRequest.java │ │ │ ├── RefundResponse.java │ │ │ └── RefundTemp.java │ └── target │ │ └── classes │ │ └── com │ │ └── service │ │ └── flow │ │ └── sample │ │ └── common │ │ ├── component │ │ └── TestComponent.class │ │ └── model │ │ ├── TestInput.class │ │ ├── TestOutput.class │ │ └── TestTemp.class ├── service-flow-sample-web1 │ ├── pom.xml │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── service │ │ │ │ └── flow │ │ │ │ └── sample │ │ │ │ └── TestApplication.java │ │ │ └── resources │ │ │ └── flow │ │ │ ├── demo1.flow.yml │ │ │ ├── demo2.flow.yml │ │ │ ├── refund.flow.yml │ │ │ ├── test1.flow.yml │ │ │ ├── test2.flow.yml │ │ │ ├── test3.flow.yml │ │ │ ├── test4.flow.yml │ │ │ ├── test5.flow.yml │ │ │ └── test6.flow.yml │ └── target │ │ └── classes │ │ ├── com │ │ └── service │ │ │ └── flow │ │ │ └── sample │ │ │ └── TestApplication.class │ │ └── flow │ │ ├── test1.flow.yml │ │ └── test2.flow.yml └── service-flow-sample-web2 │ └── pom.xml ├── service-flow-sdk ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── service │ │ └── flow │ │ ├── api │ │ ├── DTO.java │ │ ├── Flow.java │ │ ├── FlowHandlerInterceptor.java │ │ ├── FlowTypeEnum.java │ │ └── IFlowHandler.java │ │ ├── constant │ │ └── FlowConstants.java │ │ ├── exception │ │ ├── BaseException.java │ │ ├── BasicErrorCode.java │ │ ├── BizException.java │ │ ├── ErrorCodeI.java │ │ ├── FlowException.java │ │ └── SysException.java │ │ ├── index │ │ ├── ReflectionsScan.java │ │ ├── component │ │ │ ├── BaseComponentClassLoader.java │ │ │ └── ComponentDefinition.java │ │ └── dto │ │ │ ├── DTOClassLoader.java │ │ │ └── DTODefinition.java │ │ ├── model │ │ ├── BaseInput.java │ │ ├── BaseOutput.java │ │ ├── BaseTemp.java │ │ ├── FlowDefintion.java │ │ └── Node.java │ │ ├── parseing │ │ ├── FlowParser.java │ │ ├── FlowParserHandler.java │ │ └── component │ │ │ ├── AbstractNodeComponent.java │ │ │ ├── NodeComponentFactory.java │ │ │ ├── NodeParser.java │ │ │ ├── NodeParserEnum.java │ │ │ ├── bean │ │ │ └── BeanNodeComponent.java │ │ │ ├── condition │ │ │ └── ConditionNodeComponent.java │ │ │ ├── method │ │ │ └── MethodNodeComponent.java │ │ │ ├── service │ │ │ ├── SampleServiceProxy.java │ │ │ ├── ServiceModel.java │ │ │ ├── ServiceNodeComponent.java │ │ │ └── ServiceProxy.java │ │ │ └── subflow │ │ │ └── SubFlowNodeComponent.java │ │ ├── support │ │ ├── FlowDefintionRegistry.java │ │ ├── FlowDefintitionFactory.java │ │ └── yml │ │ │ ├── TempNode.java │ │ │ ├── YmlFlow.java │ │ │ └── YmlFlowDefintionRegistry.java │ │ └── util │ │ ├── BeanUtils.java │ │ ├── ClassUtil.java │ │ ├── SpleUtils.java │ │ └── SpringContextUtil.java │ └── test │ ├── java │ └── com │ │ └── service │ │ └── flow │ │ ├── parseing │ │ ├── FlowParserTest.java │ │ ├── TestComponent.java │ │ ├── TestInput.java │ │ ├── TestOutput.java │ │ └── TestTemp.java │ │ └── support │ │ └── FlowDefintitionFactoryTest.java │ └── resources │ └── flow │ ├── test1.flow.yml │ └── test2.flow.yml └── service-flow-spring-boot-starter ├── pom.xml └── src └── main └── java └── com └── service └── flow └── web ├── TestApplication.java ├── api ├── AbstractFlowHandler.java ├── AnnotationFlowHandler.java └── FlowHandler.java ├── config └── FlowConfiguration.java ├── context ├── ComponentContext.java ├── DtoContext.java └── FlowContext.java └── controller └── FlowController.java /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # service-flow 2 | 微服务流程编排框架,支持方法节点、bean节点、条件节点(循环节点)、服务节点、子流程节点 3 | ![功能视图](/doc/function.png) 4 | 5 | # 快速入门 6 | ## 依赖 7 | 版本按实际情况给定 8 | ``` 9 | 10 | com.service.flow 11 | service-flow-spring-boot-starter 12 | 13 | ``` 14 | 15 | ## 定义输出参数DTO 16 | 需要继承BaseInput 17 | ``` 18 | public class TestInput extends BaseInput 19 | ``` 20 | ## 定义输出参数DTO 21 | 需要继承BaseOutPut 22 | ``` 23 | public class TestOutput extends BaseOutput 24 | ``` 25 | ## 定义流程临时变量 26 | 需要继承BaseTemp 27 | ``` 28 | public class TestTemp extends BaseTemp 29 | ``` 30 | ## 定义组件 31 | ``` 32 | @Component("testComponent") 33 | public class TestComponent { 34 | 35 | public TestOutput test1(TestInput test){ 36 | TestOutput testOutput = new TestOutput(); 37 | BeanUtils.copyProperties(test,testOutput); 38 | System.out.println("1111111111"+testOutput); 39 | return testOutput; 40 | } 41 | ...... 42 | 43 | } 44 | ``` 45 | # 流程定义 46 | ## 新增流程文件 47 | 在resources/flow下新建test.flow.yml 48 | **非注解方式** 49 | ``` 50 | name: openAccount 51 | id: test 52 | desc: 条件执行 53 | input: com.service.flow.sample.common.model.TestInput 54 | output: com.service.flow.sample.common.model.TestOutput 55 | temp: com.service.flow.sample.common.model.TestTemp 56 | startNode: node1 57 | nodes: 58 | - node: 59 | id: node1 60 | name: methodInvoke 61 | component: com.service.flow.sample.common.component.TestComponent:test1 62 | desc: 单节点执行 63 | input: com.service.flow.sample.common.model.TestInput 64 | type: method 65 | next: node2 66 | - node: 67 | id: node2 68 | name: beanInvoke 69 | component: testComponent:test2 70 | desc: 单节点执行 71 | input: com.service.flow.sample.common.model.TestInput 72 | type: bean 73 | next: node3 74 | - node: 75 | id: node3 76 | name: conditionByAge 77 | component: age>20:node4,age<20:node5 78 | desc: 条件节点执行 79 | type: condition 80 | - node: 81 | id: node4 82 | name: beanInvoke 83 | component: testComponent:test4 84 | desc: bean节点执行 85 | input: com.service.flow.sample.common.model.TestInput 86 | type: bean 87 | - node: 88 | id: node5 89 | name: beanInvoke 90 | component: testComponent:test5 91 | desc: bean节点执行 92 | input: com.service.flow.sample.common.model.TestInput 93 | type: bean 94 | next: node6 95 | - node: 96 | id: node6 97 | name: serviceInvoke 98 | component: /test:post:testApplication 99 | desc: 服务节点 100 | input: com.service.flow.sample.common.model.TestInput 101 | type: service 102 | next: node7 103 | - node: 104 | id: node7 105 | name: subFlow 106 | component: test2 107 | desc: 子流程节点 108 | input: com.service.flow.sample.common.model.TestInput 109 | type: subflow 110 | ``` 111 | **注解方式** 112 | ``` 113 | name: addCount 114 | id: test6 115 | desc: 方法节点执行 116 | input: Test1Input 117 | output: Test1Output 118 | temp: Test1Temp 119 | startNode: methodNode1 120 | nodes: 121 | - node: 122 | id: methodNode1 123 | name: methodNode1 124 | component: count 125 | desc: 数量+1 126 | input: Test1Input 127 | type: method 128 | next: methodNode2 129 | - node: 130 | id: methodNode2 131 | name: methodNode2 132 | component: count 133 | desc: 数量+1 134 | input: Test1Input 135 | type: method 136 | next: methodNode3 137 | - node: 138 | id: methodNode3 139 | name: methodNode3 140 | component: count 141 | desc: 数量+1 142 | input: Test1Input 143 | type: method 144 | 145 | 146 | ``` 147 | ## 执行结果 148 | ``` 149 | 2020-06-22 22:43:30.607 INFO 7276 --- [ main] com.service.flow.web.api.FlowHandler : result:Test{name='zhangsan', age=18} 150 | 2020-06-22 22:43:30.607 INFO 7276 --- [ main] com.service.flow.web.api.FlowHandler : record:Flow:test2->Node:node1 151 | 2020-06-22 22:43:30.607 INFO 7276 --- [ main] com.service.flow.web.api.FlowHandler : totalTime:0ms 152 | 2020-06-22 22:43:30.607 INFO 7276 --- [ main] com.service.flow.web.api.FlowHandler : result:Test{name='zhangsan', age=18} 153 | 2020-06-22 22:43:30.607 INFO 7276 --- [ main] com.service.flow.web.api.FlowHandler : record:Flow:test->Node:node1->Node:node2->Node:node3->Node:node5->Node:node6->Node:node7 154 | 2020-06-22 22:43:30.607 INFO 7276 --- [ main] com.service.flow.web.api.FlowHandler : totalTime:52ms 155 | 156 | ``` 157 | ## 相关示例 158 | * 方法节点:[/service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test1.flow.yml](/service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test1.flow.yml) 159 | * bean节点:[/service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test2.flow.yml](/service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test2.flow.yml) 160 | * 条件节点(循环节点):[/service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test3.flow.yml](/service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test3.flow.yml) 161 | * 服务调用节点:[/service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test4.flow.yml](/service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test4.flow.yml) 162 | * 子流程节点:[/service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test5.flow.yml](/service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test5.flow.yml) 163 | 164 | --------------------------------------------------------------------------------------------------------- 165 | # 相关文章 166 | * [实战项目:设计实现一个流程编排框架(分析)](https://mp.weixin.qq.com/s/veLQZJqYNKbYvuCi7Pf_nA) 167 | * [实战项目:设计实现一个流程编排框架(设计)](https://mp.weixin.qq.com/s/vL_ExJci7eiym9aizChtAQ) 168 | * [实战项目:设计实现一个流程编排框架(实现)](https://mp.weixin.qq.com/s/2MOWIZ4emkQltEgFzja4SA) 169 | ![wechat](/doc/wechat.jpg) 170 | -------------------------------------------------------------------------------- /doc/function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itrickzhang/service-flow/e6e27b1297fc1b5df993c0c680036e95ed04ed51/doc/function.png -------------------------------------------------------------------------------- /doc/wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itrickzhang/service-flow/e6e27b1297fc1b5df993c0c680036e95ed04ed51/doc/wechat.jpg -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | com.service.flow 6 | service-flow-parent 7 | 1.0.0-SNAPSHOT 8 | pom 9 | 4.0.0 10 | 11 | service-flow-sdk 12 | service-flow-sample 13 | service-flow-denpendencies 14 | service-flow-spring-boot-starter 15 | 16 | 17 | 18 | ${project.version} 19 | 20 | 21 | 22 | 23 | 24 | 25 | com.service.flow 26 | service-flow-denpendencies 27 | ${service.flow.dependencies.version} 28 | pom 29 | import 30 | 31 | 32 | 33 | com.service.flow 34 | service-flow-sdk 35 | ${project.version} 36 | 37 | 38 | 39 | com.service.flow 40 | service-flow-spring-boot-starter 41 | ${project.version} 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /service-flow-denpendencies/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | com.service.flow 6 | service-flow-denpendencies 7 | 1.0.0-SNAPSHOT 8 | pom 9 | 4.0.0 10 | 11 | 12 | 2.2.0.RELEASE 13 | Hoxton.SR4 14 | 2.1.0.RELEASE 15 | 1.2.68 16 | 0.9.12 17 | 3.26.0-GA 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-dependencies 24 | ${spring.boot.dependencies.version} 25 | pom 26 | import 27 | 28 | 29 | org.springframework.cloud 30 | spring-cloud-dependencies 31 | ${spring.cloud.dependencies.version} 32 | pom 33 | import 34 | 35 | 36 | com.alibaba.cloud 37 | spring-cloud-alibaba-dependencies 38 | ${spring.cloud.alibaba.dependencies.version} 39 | pom 40 | import 41 | 42 | 43 | com.alibaba 44 | fastjson 45 | ${fatjson.version} 46 | 47 | 48 | org.reflections 49 | reflections 50 | ${reflections.version} 51 | 52 | 53 | org.javassist 54 | javassist 55 | ${javassist.version} 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /service-flow-sample/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.service.flow 7 | service-flow-parent 8 | 1.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | service-flow-sample 13 | pom 14 | 15 | service-flow-sample-common 16 | service-flow-sample-web1 17 | service-flow-sample-web2 18 | 19 | 20 | 21 | 22 | 23 | com.service.flow 24 | service-flow-sample-common 25 | ${project.version} 26 | 27 | 28 | com.service.flow 29 | service-flow-sample-web1 30 | ${project.version} 31 | 32 | 33 | com.service.flow 34 | service-flow-sample-web2 35 | ${project.version} 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | service-flow-sample 7 | com.service.flow 8 | 1.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | service-flow-sample-common 13 | 14 | 15 | 16 | com.service.flow 17 | service-flow-spring-boot-starter 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/component/TestComponent.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.component; 2 | 3 | import com.service.flow.model.BaseOutput; 4 | import com.service.flow.sample.common.model.TestInput; 5 | import com.service.flow.sample.common.model.TestOutput; 6 | import org.springframework.beans.BeanUtils; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author zhangcb 11 | * @ClassName TestComponent.java 12 | * @Description TODO 13 | * @createTime 2020年06月17日 17:06:00 14 | */ 15 | @Component("testComponent") 16 | public class TestComponent { 17 | 18 | public TestOutput test1(TestInput test){ 19 | TestOutput testOutput = new TestOutput(); 20 | BeanUtils.copyProperties(test,testOutput); 21 | System.out.println("1111111111"+testOutput); 22 | return testOutput; 23 | } 24 | 25 | public BaseOutput test2(TestInput test){ 26 | TestOutput testOutput = new TestOutput(); 27 | BeanUtils.copyProperties(test,testOutput); 28 | testOutput.setAge(22); 29 | System.out.println("222222222222"+testOutput); 30 | return testOutput; 31 | } 32 | 33 | public BaseOutput test3(TestInput test){ 34 | TestOutput testOutput = new TestOutput(); 35 | BeanUtils.copyProperties(test,testOutput); 36 | testOutput.setAge(33); 37 | System.out.println("3333333333"+testOutput); 38 | return testOutput; 39 | } 40 | public BaseOutput test4(TestInput test){ 41 | TestOutput testOutput = new TestOutput(); 42 | BeanUtils.copyProperties(test,testOutput); 43 | testOutput.setAge(44); 44 | System.out.println("444444444444444"+testOutput); 45 | return testOutput; 46 | } 47 | public BaseOutput test5(TestInput test){ 48 | TestOutput testOutput = new TestOutput(); 49 | BeanUtils.copyProperties(test,testOutput); 50 | testOutput.setAge(55); 51 | System.out.println("555555555555"+testOutput); 52 | return testOutput; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/hash/HashNodeHandler.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.hash; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName HashNodeHandler.java 8 | * @Description TODO 9 | * @createTime 2020年07月05日 16:00:00 10 | */ 11 | public class HashNodeHandler { 12 | 13 | private List nodes; 14 | 15 | private TreeMap virtualNodes = new TreeMap<>(); 16 | 17 | private TreeMap serverVisit = new TreeMap<>(); 18 | 19 | private int nodeNum; 20 | 21 | public HashNodeHandler(List nodes,Integer nodeNum){ 22 | this.nodes = nodes; 23 | this.nodeNum = nodeNum; 24 | } 25 | 26 | public void calculation(){ 27 | nodes.forEach(s -> { 28 | serverVisit.put(s, 0); 29 | for (int i = 0; i < nodeNum; i++) { 30 | virtualNodes.put(hash(s + "NODE=" + i), s); 31 | } 32 | }); 33 | 34 | } 35 | 36 | public void put(Object object){ 37 | int hash = hash(object); 38 | SortedMap integerStringSortedMap = virtualNodes.tailMap(hash); 39 | String server = ""; 40 | if (integerStringSortedMap.isEmpty()) { 41 | // 如果没有比reqHash大的值,则返回第一个虚拟服务器节点 42 | server = virtualNodes.get(virtualNodes.firstKey()); 43 | } else { 44 | // greaterMap第一个值就是顺时针下离reqHash最近的虚拟服务器节点 45 | server = integerStringSortedMap.get(integerStringSortedMap.firstKey()); 46 | } 47 | serverVisit.put(server, serverVisit.get(server) + 1); 48 | } 49 | 50 | private int hash(Object key) { 51 | int h; 52 | return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 53 | } 54 | 55 | public double calculationStandard() { 56 | Integer[] visitData = new Integer[serverVisit.size()]; 57 | serverVisit.values().toArray(visitData); 58 | double avg = Arrays.stream(visitData).mapToInt(Integer::intValue).average().orElse(0d); 59 | double avgStd = Arrays.stream(visitData).map(count -> Math.pow(count - avg, 2)).mapToDouble(Double::doubleValue).average().orElse(0d); 60 | double std = Math.sqrt(avgStd); 61 | return std; 62 | } 63 | 64 | public TreeMap getServerVisit() { 65 | return serverVisit; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/hash/HashTest.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.hash; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName HashTest.java 9 | * @Description TODO 10 | * @createTime 2020年07月05日 15:53:00 11 | */ 12 | public class HashTest { 13 | public static void main(String[] args) { 14 | List list = new ArrayList<>(); 15 | list.add("192.168.0.1"); 16 | list.add("192.168.0.2"); 17 | list.add("192.168.0.3"); 18 | list.add("192.168.0.4"); 19 | list.add("192.168.0.5"); 20 | list.add("192.168.0.6"); 21 | list.add("192.168.0.7"); 22 | list.add("192.168.0.8"); 23 | list.add("192.168.0.9"); 24 | list.add("192.168.0.10"); 25 | list.add("192.168.0.11"); 26 | list.add("192.168.0.12"); 27 | list.add("192.168.0.13"); 28 | int num = 200; 29 | HashNodeHandler hashNodeHandler = new HashNodeHandler(list, num); 30 | hashNodeHandler.calculation(); 31 | test1000000(hashNodeHandler); 32 | } 33 | 34 | private static void test1000000(HashNodeHandler hashNodeHandler) { 35 | int num = 1000000; 36 | loop(hashNodeHandler,num); 37 | } 38 | 39 | private static void loop(HashNodeHandler hashNodeHandler,int num) { 40 | for (int i = 0; i < num; i++) { 41 | hashNodeHandler.put(i+"nodeDa"); 42 | } 43 | System.out.println(hashNodeHandler.getServerVisit()); 44 | System.out.println(hashNodeHandler.calculationStandard()); 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/model/TestInput.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.model; 2 | 3 | import com.service.flow.model.BaseInput; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Test.java 8 | * @Description TODO 9 | * @createTime 2020年06月17日 17:09:00 10 | */ 11 | public class TestInput extends BaseInput { 12 | private String name; 13 | 14 | private Integer age; 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public Integer getAge() { 25 | return age; 26 | } 27 | 28 | public void setAge(Integer age) { 29 | this.age = age; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return "Test{" + 35 | "name='" + name + '\'' + 36 | ", age=" + age + 37 | '}'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/model/TestOutput.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.model; 2 | 3 | import com.service.flow.model.BaseOutput; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Test.java 8 | * @Description TODO 9 | * @createTime 2020年06月17日 17:09:00 10 | */ 11 | public class TestOutput extends BaseOutput { 12 | private String name; 13 | 14 | private Integer age; 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public Integer getAge() { 25 | return age; 26 | } 27 | 28 | public void setAge(Integer age) { 29 | this.age = age; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return "Test{" + 35 | "name='" + name + '\'' + 36 | ", age=" + age + 37 | '}'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/model/TestTemp.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.model; 2 | 3 | 4 | import com.service.flow.model.BaseTemp; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName TestComponent.java 9 | * @Description TODO 10 | * @createTime 2020年06月17日 17:06:00 11 | */ 12 | public class TestTemp extends BaseTemp { 13 | 14 | private String name; 15 | 16 | private Integer age; 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public void setName(String name) { 23 | this.name = name; 24 | } 25 | 26 | public Integer getAge() { 27 | return age; 28 | } 29 | 30 | public void setAge(Integer age) { 31 | this.age = age; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | return "Test{" + 37 | "name='" + name + '\'' + 38 | ", age=" + age + 39 | '}'; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test1/Test1Component.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test1; 2 | 3 | 4 | import com.service.flow.api.Flow; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName Test1Component.java 9 | * @Description TODO 10 | * @createTime 2020年06月25日 07:03:00 11 | */ 12 | public class Test1Component { 13 | @Flow(name = "count") 14 | public Test1Output count(Test1Input input){ 15 | Test1Output output = new Test1Output(); 16 | int count = input.getCount(); 17 | count++; 18 | output.setCount(count); 19 | return output; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test1/Test1Input.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test1; 2 | 3 | import com.service.flow.api.DTO; 4 | import com.service.flow.model.BaseInput; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName Test1Input.java 9 | * @Description TODO 10 | * @createTime 2020年06月25日 07:01:00 11 | */ 12 | @DTO 13 | public class Test1Input extends BaseInput { 14 | private int count; 15 | 16 | public int getCount() { 17 | return count; 18 | } 19 | 20 | public void setCount(int count) { 21 | this.count = count; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "Test1Input{" + 27 | "count=" + count + 28 | '}'; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test1/Test1Output.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test1; 2 | 3 | import com.service.flow.api.DTO; 4 | import com.service.flow.model.BaseInput; 5 | import com.service.flow.model.BaseOutput; 6 | 7 | /** 8 | * @author zhangcb 9 | * @ClassName Test1Input.java 10 | * @Description TODO 11 | * @createTime 2020年06月25日 07:01:00 12 | */ 13 | @DTO 14 | public class Test1Output extends BaseOutput { 15 | private int count; 16 | 17 | public int getCount() { 18 | return count; 19 | } 20 | 21 | public void setCount(int count) { 22 | this.count = count; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return "Test1Input{" + 28 | "count=" + count + 29 | '}'; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test1/Test1Temp.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test1; 2 | 3 | import com.service.flow.api.DTO; 4 | import com.service.flow.model.BaseOutput; 5 | import com.service.flow.model.BaseTemp; 6 | 7 | /** 8 | * @author zhangcb 9 | * @ClassName Test1Input.java 10 | * @Description TODO 11 | * @createTime 2020年06月25日 07:01:00 12 | */ 13 | @DTO 14 | public class Test1Temp extends BaseTemp { 15 | 16 | private int count; 17 | 18 | public int getCount() { 19 | return count; 20 | } 21 | 22 | public void setCount(int count) { 23 | this.count = count; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return "Test1Input{" + 29 | "count=" + count + 30 | '}'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test2/Test2Component.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test2; 2 | 3 | 4 | import org.springframework.stereotype.Component; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName Test1Component.java 9 | * @Description TODO 10 | * @createTime 2020年06月25日 07:03:00 11 | */ 12 | @Component 13 | public class Test2Component { 14 | 15 | public Test2Output count(Test2Input input){ 16 | Test2Output output = new Test2Output(); 17 | int count = input.getCount(); 18 | count++; 19 | output.setCount(count); 20 | return output; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test2/Test2Input.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test2; 2 | 3 | import com.service.flow.model.BaseInput; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Test1Input.java 8 | * @Description TODO 9 | * @createTime 2020年06月25日 07:01:00 10 | */ 11 | public class Test2Input extends BaseInput { 12 | private int count; 13 | 14 | public int getCount() { 15 | return count; 16 | } 17 | 18 | public void setCount(int count) { 19 | this.count = count; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return "Test1Input{" + 25 | "count=" + count + 26 | '}'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test2/Test2Output.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test2; 2 | 3 | import com.service.flow.model.BaseOutput; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Test1Input.java 8 | * @Description TODO 9 | * @createTime 2020年06月25日 07:01:00 10 | */ 11 | public class Test2Output extends BaseOutput { 12 | private int count; 13 | 14 | public int getCount() { 15 | return count; 16 | } 17 | 18 | public void setCount(int count) { 19 | this.count = count; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return "Test1Input{" + 25 | "count=" + count + 26 | '}'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test2/Test2Temp.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test2; 2 | 3 | import com.service.flow.model.BaseTemp; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Test1Input.java 8 | * @Description TODO 9 | * @createTime 2020年06月25日 07:01:00 10 | */ 11 | public class Test2Temp extends BaseTemp { 12 | 13 | private int count; 14 | 15 | public int getCount() { 16 | return count; 17 | } 18 | 19 | public void setCount(int count) { 20 | this.count = count; 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return "Test1Input{" + 26 | "count=" + count + 27 | '}'; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test3/Test3Component.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test3; 2 | 3 | 4 | import org.springframework.stereotype.Component; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName Test1Component.java 9 | * @Description TODO 10 | * @createTime 2020年06月25日 07:03:00 11 | */ 12 | @Component 13 | public class Test3Component { 14 | 15 | public Test3Output count(Test3Input input){ 16 | Test3Output output = new Test3Output(); 17 | int count = input.getCount(); 18 | count++; 19 | output.setCount(count); 20 | return output; 21 | } 22 | 23 | public Test3Output count5(Test3Input input){ 24 | Test3Output output = new Test3Output(); 25 | int count = input.getCount(); 26 | count = count +5; 27 | output.setCount(count); 28 | return output; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test3/Test3Input.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test3; 2 | 3 | import com.service.flow.model.BaseInput; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Test1Input.java 8 | * @Description TODO 9 | * @createTime 2020年06月25日 07:01:00 10 | */ 11 | public class Test3Input extends BaseInput { 12 | private int count; 13 | 14 | public int getCount() { 15 | return count; 16 | } 17 | 18 | public void setCount(int count) { 19 | this.count = count; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return "Test1Input{" + 25 | "count=" + count + 26 | '}'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test3/Test3Output.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test3; 2 | 3 | import com.service.flow.model.BaseOutput; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Test1Input.java 8 | * @Description TODO 9 | * @createTime 2020年06月25日 07:01:00 10 | */ 11 | public class Test3Output extends BaseOutput { 12 | private int count; 13 | 14 | public int getCount() { 15 | return count; 16 | } 17 | 18 | public void setCount(int count) { 19 | this.count = count; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return "Test1Input{" + 25 | "count=" + count + 26 | '}'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test3/Test3Temp.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test3; 2 | 3 | import com.service.flow.model.BaseTemp; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Test1Input.java 8 | * @Description TODO 9 | * @createTime 2020年06月25日 07:01:00 10 | */ 11 | public class Test3Temp extends BaseTemp { 12 | 13 | private int count; 14 | 15 | public int getCount() { 16 | return count; 17 | } 18 | 19 | public void setCount(int count) { 20 | this.count = count; 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return "Test1Input{" + 26 | "count=" + count + 27 | '}'; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test4/MethodComponent.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test4; 2 | 3 | import com.service.flow.api.Flow; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | /** 8 | * @author zhangcb 9 | * @ClassName MethodComponent.java 10 | * @Description TODO 11 | * @createTime 2020年07月06日 07:30:00 12 | */ 13 | public class MethodComponent { 14 | 15 | private Logger logger = LoggerFactory.getLogger(MethodComponent.class); 16 | 17 | @Flow(name = "refundApp") 18 | public RefundResponse refundApp(RefundRequest refundRequest){ 19 | logger.info("执行退款申请"); 20 | return new RefundResponse(); 21 | } 22 | 23 | @Flow(name = "paramCheck") 24 | public RefundResponse paramCheck(RefundRequest refundRequest){ 25 | logger.info("执行参数检查"); 26 | return new RefundResponse(); 27 | } 28 | 29 | @Flow(name = "configCheck") 30 | public RefundResponse configCheck(RefundRequest refundRequest){ 31 | logger.info("检查退款的特殊配置"); 32 | RefundResponse refundResponse = new RefundResponse(); 33 | refundResponse.setConfig("cache"); 34 | return refundResponse; 35 | } 36 | 37 | @Flow(name = "routeChannel") 38 | public RefundResponse routeChannel(RefundRequest refundRequest){ 39 | logger.info("路由通道"); 40 | return new RefundResponse(); 41 | } 42 | 43 | @Flow(name = "cacheRefundConfig") 44 | public RefundResponse cacheRefundConfig(RefundRequest refundRequest){ 45 | logger.info("缓存退款配置"); 46 | RefundResponse refundResponse = new RefundResponse(); 47 | refundResponse.setConfig("loop"); 48 | return refundResponse; 49 | } 50 | 51 | @Flow(name = "loopRefundApp") 52 | public RefundResponse loopRefundApp(RefundRequest refundRequest){ 53 | logger.info("轮询退款申请"); 54 | return new RefundResponse(); 55 | } 56 | 57 | @Flow(name = "noSupport") 58 | public RefundResponse noSupport(RefundRequest refundRequest){ 59 | logger.info("不支持退款"); 60 | return new RefundResponse(); 61 | } 62 | 63 | @Flow(name = "packageChannel") 64 | public RefundResponse packageChannel(RefundRequest refundRequest){ 65 | logger.info("组装报文通道"); 66 | return new RefundResponse(); 67 | } 68 | 69 | @Flow(name = "saveRefundInfo") 70 | public RefundResponse saveRefundInfo(RefundRequest refundRequest){ 71 | logger.info("保存退款信息"); 72 | return new RefundResponse(); 73 | } 74 | 75 | @Flow(name = "packageSign") 76 | public RefundResponse packageSign(RefundRequest refundRequest){ 77 | logger.info("报文签名"); 78 | return new RefundResponse(); 79 | } 80 | 81 | @Flow(name = "signature") 82 | public RefundResponse signature(RefundRequest refundRequest){ 83 | logger.info("接受银行报文并验签"); 84 | return new RefundResponse(); 85 | } 86 | 87 | @Flow(name = "updateRefundInfo") 88 | public RefundResponse updateRefundInfo(RefundRequest refundRequest){ 89 | logger.info("更新退款响应"); 90 | return new RefundResponse(); 91 | } 92 | 93 | @Flow(name = "returnRefund") 94 | public RefundResponse returnRefund(RefundRequest refundRequest){ 95 | logger.info("返回退款响应"); 96 | RefundResponse refundResponse = new RefundResponse(); 97 | refundResponse.setCode("200"); 98 | refundResponse.setMessage("处理成功"); 99 | return refundResponse; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test4/RefundRequest.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test4; 2 | 3 | import com.service.flow.api.DTO; 4 | import com.service.flow.model.BaseInput; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName RefundRequest.java 9 | * @Description TODO 10 | * @createTime 2020年07月06日 07:27:00 11 | */ 12 | @DTO 13 | public class RefundRequest extends BaseInput { 14 | 15 | private String name; 16 | 17 | private String account; 18 | 19 | private String money; 20 | 21 | public String getName() { 22 | return name; 23 | } 24 | 25 | public void setName(String name) { 26 | this.name = name; 27 | } 28 | 29 | public String getAccount() { 30 | return account; 31 | } 32 | 33 | public void setAccount(String account) { 34 | this.account = account; 35 | } 36 | 37 | public String getMoney() { 38 | return money; 39 | } 40 | 41 | public void setMoney(String money) { 42 | this.money = money; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "RefundRequest{" + 48 | "name='" + name + '\'' + 49 | ", account='" + account + '\'' + 50 | ", money='" + money + '\'' + 51 | '}'; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test4/RefundResponse.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test4; 2 | 3 | import com.service.flow.api.DTO; 4 | import com.service.flow.model.BaseOutput; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName RefundResponse.java 9 | * @Description TODO 10 | * @createTime 2020年07月06日 07:28:00 11 | */ 12 | @DTO 13 | public class RefundResponse extends BaseOutput { 14 | private String name; 15 | 16 | private String account; 17 | 18 | private String money; 19 | 20 | private String code; 21 | 22 | private String message; 23 | 24 | private String config; 25 | 26 | public String getName() { 27 | return name; 28 | } 29 | 30 | public void setName(String name) { 31 | this.name = name; 32 | } 33 | 34 | public String getMoney() { 35 | return money; 36 | } 37 | 38 | public void setMoney(String money) { 39 | this.money = money; 40 | } 41 | 42 | public String getCode() { 43 | return code; 44 | } 45 | 46 | public void setCode(String code) { 47 | this.code = code; 48 | } 49 | 50 | public String getMessage() { 51 | return message; 52 | } 53 | 54 | public void setMessage(String message) { 55 | this.message = message; 56 | } 57 | 58 | public String getAccount() { 59 | return account; 60 | } 61 | 62 | public void setAccount(String account) { 63 | this.account = account; 64 | } 65 | 66 | public String getConfig() { 67 | return config; 68 | } 69 | 70 | public void setConfig(String config) { 71 | this.config = config; 72 | } 73 | 74 | @Override 75 | public String toString() { 76 | return "RefundResponse{" + 77 | "name='" + name + '\'' + 78 | ", account='" + account + '\'' + 79 | ", money='" + money + '\'' + 80 | ", code='" + code + '\'' + 81 | ", message='" + message + '\'' + 82 | ", config='" + config + '\'' + 83 | '}'; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/src/main/java/com/service/flow/sample/common/test4/RefundTemp.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample.common.test4; 2 | 3 | import com.service.flow.api.DTO; 4 | import com.service.flow.model.BaseTemp; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName RefundTemp.java 9 | * @Description TODO 10 | * @createTime 2020年07月06日 07:30:00 11 | */ 12 | @DTO 13 | public class RefundTemp extends BaseTemp { 14 | 15 | private String name; 16 | 17 | private String account; 18 | 19 | private String money; 20 | 21 | private String code; 22 | 23 | private String message; 24 | 25 | private String config; 26 | 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | 35 | public String getMoney() { 36 | return money; 37 | } 38 | 39 | public void setMoney(String money) { 40 | this.money = money; 41 | } 42 | 43 | public String getCode() { 44 | return code; 45 | } 46 | 47 | public void setCode(String code) { 48 | this.code = code; 49 | } 50 | 51 | public String getMessage() { 52 | return message; 53 | } 54 | 55 | public void setMessage(String message) { 56 | this.message = message; 57 | } 58 | 59 | public String getAccount() { 60 | return account; 61 | } 62 | 63 | public void setAccount(String account) { 64 | this.account = account; 65 | } 66 | 67 | public String getConfig() { 68 | return config; 69 | } 70 | 71 | public void setConfig(String config) { 72 | this.config = config; 73 | } 74 | 75 | 76 | @Override 77 | public String toString() { 78 | return "RefundTemp{" + 79 | "name='" + name + '\'' + 80 | ", account='" + account + '\'' + 81 | ", money='" + money + '\'' + 82 | ", code='" + code + '\'' + 83 | ", message='" + message + '\'' + 84 | ", config='" + config + '\'' + 85 | '}'; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/target/classes/com/service/flow/sample/common/component/TestComponent.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itrickzhang/service-flow/e6e27b1297fc1b5df993c0c680036e95ed04ed51/service-flow-sample/service-flow-sample-common/target/classes/com/service/flow/sample/common/component/TestComponent.class -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/target/classes/com/service/flow/sample/common/model/TestInput.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itrickzhang/service-flow/e6e27b1297fc1b5df993c0c680036e95ed04ed51/service-flow-sample/service-flow-sample-common/target/classes/com/service/flow/sample/common/model/TestInput.class -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/target/classes/com/service/flow/sample/common/model/TestOutput.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itrickzhang/service-flow/e6e27b1297fc1b5df993c0c680036e95ed04ed51/service-flow-sample/service-flow-sample-common/target/classes/com/service/flow/sample/common/model/TestOutput.class -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-common/target/classes/com/service/flow/sample/common/model/TestTemp.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itrickzhang/service-flow/e6e27b1297fc1b5df993c0c680036e95ed04ed51/service-flow-sample/service-flow-sample-common/target/classes/com/service/flow/sample/common/model/TestTemp.class -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | service-flow-sample 7 | com.service.flow 8 | 1.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | service-flow-sample-web1 13 | 14 | 15 | 16 | com.service.flow 17 | service-flow-sample-common 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-web 22 | 23 | 24 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/src/main/java/com/service/flow/sample/TestApplication.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.sample; 2 | 3 | import com.service.flow.api.IFlowHandler; 4 | import com.service.flow.sample.common.model.TestInput; 5 | import com.service.flow.sample.common.test1.Test1Input; 6 | import com.service.flow.sample.common.test2.Test2Input; 7 | import com.service.flow.sample.common.test3.Test3Input; 8 | import com.service.flow.sample.common.test4.RefundRequest; 9 | import com.service.flow.util.SpringContextUtil; 10 | import com.service.flow.web.api.AnnotationFlowHandler; 11 | import org.springframework.boot.SpringApplication; 12 | import org.springframework.boot.autoconfigure.SpringBootApplication; 13 | import org.springframework.context.ApplicationContext; 14 | import org.springframework.context.ConfigurableApplicationContext; 15 | 16 | import java.io.IOException; 17 | 18 | /** 19 | * @author zhangcb 20 | * @ClassName TestApplication.java 21 | * @Description TODO 22 | * @createTime 2020年06月19日 08:00:00 23 | */ 24 | @SpringBootApplication(scanBasePackages = {"com.service.flow"}) 25 | public class TestApplication { 26 | public static void main(String[] args) throws IOException { 27 | ConfigurableApplicationContext applicationContext = SpringApplication.run(TestApplication.class, args); 28 | //test1(applicationContext); 29 | //test2(applicationContext); 30 | //test3(applicationContext); 31 | //test4(applicationContext); 32 | //test5(applicationContext); 33 | //test6(applicationContext); 34 | testRefund(applicationContext); 35 | } 36 | 37 | private static void testRefund(ConfigurableApplicationContext applicationContext) { 38 | RefundRequest refundRequest = new RefundRequest(); 39 | refundRequest.setAccount("1111"); 40 | refundRequest.setName("zhangsan"); 41 | refundRequest.setMoney("20"); 42 | IFlowHandler flowHandler = applicationContext.getBean(AnnotationFlowHandler.class); 43 | flowHandler.execute("refund", refundRequest); 44 | } 45 | 46 | private static void test6(ConfigurableApplicationContext applicationContext) { 47 | Test3Input input = new Test3Input(); 48 | input.setCount(0); 49 | IFlowHandler flowHandler = applicationContext.getBean(AnnotationFlowHandler.class); 50 | flowHandler.execute("test6", input); 51 | } 52 | 53 | private static void test5(ConfigurableApplicationContext applicationContext) { 54 | Test3Input input = new Test3Input(); 55 | input.setCount(0); 56 | IFlowHandler flowHandler = applicationContext.getBean(IFlowHandler.class); 57 | flowHandler.execute("test5", input); 58 | } 59 | 60 | private static void test4(ConfigurableApplicationContext applicationContext) { 61 | Test3Input input = new Test3Input(); 62 | input.setCount(0); 63 | IFlowHandler flowHandler = applicationContext.getBean(IFlowHandler.class); 64 | flowHandler.execute("test4", input); 65 | } 66 | 67 | private static void test3(ConfigurableApplicationContext applicationContext) { 68 | Test3Input input = new Test3Input(); 69 | input.setCount(0); 70 | IFlowHandler flowHandler = applicationContext.getBean(IFlowHandler.class); 71 | flowHandler.execute("test3", input); 72 | } 73 | 74 | 75 | public static void test1(ApplicationContext applicationContext){ 76 | Test1Input input = new Test1Input(); 77 | input.setCount(0); 78 | IFlowHandler flowHandler = applicationContext.getBean(IFlowHandler.class); 79 | flowHandler.execute("test1", input); 80 | } 81 | 82 | private static void test2(ApplicationContext applicationContext) { 83 | Test2Input input = new Test2Input(); 84 | input.setCount(0); 85 | IFlowHandler flowHandler = applicationContext.getBean(IFlowHandler.class); 86 | flowHandler.execute("test2", input); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/src/main/resources/flow/demo1.flow.yml: -------------------------------------------------------------------------------- 1 | name: openAccount 2 | id: demo1 3 | desc: 条件执行 4 | input: com.service.flow.sample.common.model.TestInput 5 | output: com.service.flow.sample.common.model.TestOutput 6 | temp: com.service.flow.sample.common.model.TestTemp 7 | startNode: node1 8 | nodes: 9 | - node: 10 | id: node1 11 | name: methodInvoke 12 | component: com.service.flow.sample.common.component.TestComponent:test1 13 | desc: 单节点执行 14 | input: com.service.flow.sample.common.model.TestInput 15 | type: method 16 | next: node2 17 | - node: 18 | id: node2 19 | name: beanInvoke 20 | component: testComponent:test2 21 | desc: 单节点执行 22 | input: com.service.flow.sample.common.model.TestInput 23 | type: bean 24 | next: node3 25 | - node: 26 | id: node3 27 | name: conditionByAge 28 | component: age>20:node4,age<20:node5 29 | desc: 条件节点执行 30 | type: condition 31 | - node: 32 | id: node4 33 | name: beanInvoke 34 | component: testComponent:test4 35 | desc: bean节点执行 36 | input: com.service.flow.sample.common.model.TestInput 37 | type: bean 38 | - node: 39 | id: node5 40 | name: beanInvoke 41 | component: testComponent:test5 42 | desc: bean节点执行 43 | input: com.service.flow.sample.common.model.TestInput 44 | type: bean 45 | next: node6 46 | - node: 47 | id: node6 48 | name: serviceInvoke 49 | component: /test:post:testApplication 50 | desc: 方法节点调用 51 | input: com.service.flow.sample.common.model.TestInput 52 | type: service 53 | next: node7 54 | - node: 55 | id: node7 56 | name: subFlow 57 | component: test2 58 | desc: 方法节点调用 59 | input: com.service.flow.sample.common.model.TestInput 60 | type: subflow -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/src/main/resources/flow/demo2.flow.yml: -------------------------------------------------------------------------------- 1 | name: openAccount 2 | id: demo2 3 | desc: 条件执行 4 | input: com.service.flow.sample.common.model.TestInput 5 | output: com.service.flow.sample.common.model.TestOutput 6 | temp: com.service.flow.sample.common.model.TestTemp 7 | startNode: node1 8 | nodes: 9 | - node: 10 | id: node1 11 | name: methodInvoke 12 | component: com.service.flow.sample.common.component.TestComponent:test1 13 | desc: 单节点执行 14 | input: com.service.flow.sample.common.model.TestInput 15 | type: method 16 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/src/main/resources/flow/refund.flow.yml: -------------------------------------------------------------------------------- 1 | name: refund 2 | id: refund 3 | desc: 网银支付退款 4 | input: RefundRequest 5 | output: RefundResponse 6 | temp: RefundTemp 7 | startNode: refundApp 8 | nodes: 9 | - node: 10 | id: refundApp 11 | name: refundApp 12 | component: refundApp 13 | desc: 执行退款申请 14 | input: RefundRequest 15 | type: method 16 | next: paramCheck 17 | - node: 18 | id: paramCheck 19 | name: paramCheck 20 | component: paramCheck 21 | desc: 执行参数检查 22 | input: RefundRequest 23 | type: method 24 | next: configCheck 25 | - node: 26 | id: configCheck 27 | name: configCheck 28 | component: configCheck 29 | desc: 检查退款的特殊配置 30 | input: RefundRequest 31 | type: method 32 | next: condition 33 | - node: 34 | id: condition 35 | name: condition 36 | component: config == 'cache':cacheRefundConfig 37 | desc: 检查退款配置 38 | type: condition 39 | - node: 40 | id: cacheRefundConfig 41 | name: cacheRefundConfig 42 | component: cacheRefundConfig 43 | desc: 退款缓存配置 44 | input: RefundRequest 45 | type: method 46 | next: loopRefundApp 47 | - node: 48 | id: loopRefundApp 49 | name: loopRefundApp 50 | component: loopRefundApp 51 | desc: 轮询退款申请 52 | input: RefundRequest 53 | type: method 54 | next: routeChannel 55 | - node: 56 | id: routeChannel 57 | name: routeChannel 58 | component: routeChannel 59 | desc: 路由通道 60 | input: RefundRequest 61 | type: method 62 | next: packageChannel 63 | - node: 64 | id: packageChannel 65 | name: packageChannel 66 | component: packageChannel 67 | desc: 组装报文通道 68 | input: RefundRequest 69 | type: method 70 | next: saveRefundInfo 71 | - node: 72 | id: saveRefundInfo 73 | name: saveRefundInfo 74 | component: saveRefundInfo 75 | desc: 保存退款信息 76 | input: RefundRequest 77 | type: method 78 | next: packageSign 79 | - node: 80 | id: packageSign 81 | name: packageSign 82 | component: packageSign 83 | desc: 报文签名 84 | input: RefundRequest 85 | type: method 86 | next: service 87 | - node: 88 | id: service 89 | name: service 90 | component: /test:post:testApplication 91 | desc: 发送报文到银行 92 | input: RefundRequest 93 | type: service 94 | next: signature 95 | - node: 96 | id: signature 97 | name: signature 98 | component: signature 99 | desc: 接受银行报文并验签 100 | input: RefundRequest 101 | type: method 102 | next: updateRefundInfo 103 | - node: 104 | id: updateRefundInfo 105 | name: updateRefundInfo 106 | component: updateRefundInfo 107 | desc: 更新退款响应 108 | input: RefundRequest 109 | type: method 110 | next: returnRefund 111 | - node: 112 | id: returnRefund 113 | name: returnRefund 114 | component: returnRefund 115 | desc: 返回退款响应 116 | input: RefundRequest 117 | type: method -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test1.flow.yml: -------------------------------------------------------------------------------- 1 | name: addCount 2 | id: test1 3 | desc: 方法节点执行 4 | input: com.service.flow.sample.common.test1.Test1Input 5 | output: com.service.flow.sample.common.test1.Test1Output 6 | temp: com.service.flow.sample.common.test1.Test1Temp 7 | startNode: methodNode1 8 | nodes: 9 | - node: 10 | id: methodNode1 11 | name: methodNode1 12 | component: com.service.flow.sample.common.test1.Test1Component:count 13 | desc: 数量+1 14 | input: com.service.flow.sample.common.test1.Test1Input 15 | type: method 16 | next: methodNode2 17 | - node: 18 | id: methodNode2 19 | name: methodNode2 20 | component: com.service.flow.sample.common.test1.Test1Component:count 21 | desc: 数量+1 22 | input: com.service.flow.sample.common.test1.Test1Input 23 | type: method 24 | next: methodNode3 25 | - node: 26 | id: methodNode3 27 | name: methodNode3 28 | component: com.service.flow.sample.common.test1.Test1Component:count 29 | desc: 数量+1 30 | input: com.service.flow.sample.common.test1.Test1Input 31 | type: method 32 | 33 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test2.flow.yml: -------------------------------------------------------------------------------- 1 | name: addCount 2 | id: test2 3 | desc: bean节点执行 4 | input: com.service.flow.sample.common.test2.Test2Input 5 | output: com.service.flow.sample.common.test2.Test2Output 6 | temp: com.service.flow.sample.common.test2.Test2Temp 7 | startNode: beanNode1 8 | nodes: 9 | - node: 10 | id: beanNode1 11 | name: beanNode1 12 | component: test2Component:count 13 | desc: 数量+1 14 | input: com.service.flow.sample.common.test2.Test2Input 15 | type: bean 16 | next: beanNode2 17 | - node: 18 | id: beanNode2 19 | name: beanNode2 20 | component: test2Component:count:count 21 | desc: 数量+1 22 | input: com.service.flow.sample.common.test2.Test2Input 23 | type: bean 24 | next: beanNode3 25 | - node: 26 | id: beanNode3 27 | name: beanNode3 28 | component: test2Component:count 29 | desc: 数量+1 30 | input: com.service.flow.sample.common.test2.Test2Input 31 | type: bean 32 | 33 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test3.flow.yml: -------------------------------------------------------------------------------- 1 | name: loop 2 | id: test3 3 | desc: 循环点执行 4 | input: com.service.flow.sample.common.test3.Test3Input 5 | output: com.service.flow.sample.common.test3.Test3Output 6 | temp: com.service.flow.sample.common.test3.Test3Temp 7 | startNode: conditionNode1 8 | nodes: 9 | - node: 10 | id: conditionNode1 11 | name: conditionNode1 12 | component: count<5:methodNode2,count>=5:methodNode3 13 | desc: 数量条件判断 14 | type: condition 15 | - node: 16 | id: methodNode2 17 | name: methodNode2 18 | component: test3Component:count 19 | desc: 数量+1 20 | input: com.service.flow.sample.common.test3.Test3Input 21 | type: bean 22 | next: conditionNode1 23 | - node: 24 | id: methodNode3 25 | name: methodNode3 26 | component: test3Component:count5 27 | desc: 数量+5 28 | input: com.service.flow.sample.common.test3.Test3Input 29 | type: bean 30 | 31 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test4.flow.yml: -------------------------------------------------------------------------------- 1 | name: service 2 | id: test4 3 | desc: 服务节点执行 4 | input: com.service.flow.sample.common.test3.Test3Input 5 | output: com.service.flow.sample.common.test3.Test3Output 6 | temp: com.service.flow.sample.common.test3.Test3Temp 7 | startNode: serviceNode1 8 | nodes: 9 | - node: 10 | id: serviceNode1 11 | name: serviceNode1 12 | component: /test:post:testApplication 13 | desc: 方法节点调用 14 | input: com.service.flow.sample.common.test3.Test3Input 15 | type: service 16 | 17 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test5.flow.yml: -------------------------------------------------------------------------------- 1 | name: subflow 2 | id: test5 3 | desc: 子流程节点执行 4 | input: com.service.flow.sample.common.test3.Test3Input 5 | output: com.service.flow.sample.common.test3.Test3Output 6 | temp: com.service.flow.sample.common.test3.Test3Temp 7 | startNode: subFlowNode1 8 | nodes: 9 | - node: 10 | id: subFlowNode1 11 | name: subFlowNode1 12 | component: test1 13 | desc: 子流程节点 14 | input: com.service.flow.sample.common.test3.Test3Input 15 | type: subflow 16 | 17 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/src/main/resources/flow/test6.flow.yml: -------------------------------------------------------------------------------- 1 | name: addCount 2 | id: test6 3 | desc: 方法节点执行 4 | input: Test1Input 5 | output: Test1Output 6 | temp: Test1Temp 7 | startNode: methodNode1 8 | nodes: 9 | - node: 10 | id: methodNode1 11 | name: methodNode1 12 | component: count 13 | desc: 数量+1 14 | input: Test1Input 15 | type: method 16 | next: methodNode2 17 | - node: 18 | id: methodNode2 19 | name: methodNode2 20 | component: count 21 | desc: 数量+1 22 | input: Test1Input 23 | type: method 24 | next: methodNode3 25 | - node: 26 | id: methodNode3 27 | name: methodNode3 28 | component: count 29 | desc: 数量+1 30 | input: Test1Input 31 | type: method 32 | 33 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/target/classes/com/service/flow/sample/TestApplication.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itrickzhang/service-flow/e6e27b1297fc1b5df993c0c680036e95ed04ed51/service-flow-sample/service-flow-sample-web1/target/classes/com/service/flow/sample/TestApplication.class -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/target/classes/flow/test1.flow.yml: -------------------------------------------------------------------------------- 1 | name: addCount 2 | id: test1 3 | desc: 方法节点执行 4 | input: com.service.flow.sample.common.test1.Test1Input 5 | output: com.service.flow.sample.common.test1.Test1Output 6 | temp: com.service.flow.sample.common.test1.Test1Temp 7 | startNode: methodNode1 8 | nodes: 9 | - node: 10 | id: methodNode1 11 | name: methodNode1 12 | component: com.service.flow.sample.common.test1.Test1Component:count 13 | desc: 数量+1 14 | input: com.service.flow.sample.common.test1.Test1Input 15 | type: method 16 | next: methodNode2 17 | - node: 18 | id: methodNode2 19 | name: methodNode2 20 | component: com.service.flow.sample.common.test1.Test1Component:count 21 | desc: 数量+1 22 | input: com.service.flow.sample.common.test1.Test1Input 23 | type: method 24 | next: methodNode3 25 | - node: 26 | id: methodNode3 27 | name: methodNode3 28 | component: com.service.flow.sample.common.test1.Test1Component:count 29 | desc: 数量+1 30 | input: com.service.flow.sample.common.test1.Test1Input 31 | type: method 32 | 33 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web1/target/classes/flow/test2.flow.yml: -------------------------------------------------------------------------------- 1 | name: addCount 2 | id: test2 3 | desc: bean节点执行 4 | input: com.service.flow.sample.common.test2.Test2Input 5 | output: com.service.flow.sample.common.test2.Test2Output 6 | temp: com.service.flow.sample.common.test2.Test2Temp 7 | startNode: beanNode1 8 | nodes: 9 | - node: 10 | id: beanNode1 11 | name: beanNode1 12 | component: test2Component:count 13 | desc: 数量+1 14 | input: com.service.flow.sample.common.test2.Test2Input 15 | type: bean 16 | next: beanNode2 17 | - node: 18 | id: beanNode2 19 | name: beanNode2 20 | component: test2Component:count:count 21 | desc: 数量+1 22 | input: com.service.flow.sample.common.test2.Test2Input 23 | type: bean 24 | next: beanNode3 25 | - node: 26 | id: beanNode3 27 | name: beanNode3 28 | component: test2Component:count 29 | desc: 数量+1 30 | input: com.service.flow.sample.common.test2.Test2Input 31 | type: bean 32 | 33 | -------------------------------------------------------------------------------- /service-flow-sample/service-flow-sample-web2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | service-flow-sample 7 | com.service.flow 8 | 1.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | service-flow-sample-web2 13 | 14 | 15 | -------------------------------------------------------------------------------- /service-flow-sdk/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.service.flow 7 | service-flow-parent 8 | 1.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | service-flow-sdk 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-configuration-processor 22 | true 23 | 24 | 25 | com.alibaba 26 | fastjson 27 | 28 | 29 | org.slf4j 30 | slf4j-api 31 | 32 | 33 | 34 | org.reflections 35 | reflections 36 | 37 | 38 | 39 | 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-test 47 | test 48 | 49 | 50 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/api/DTO.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.api; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Flow.java 8 | * @Description TODO 9 | * @createTime 2020年06月21日 15:38:00 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(value = {ElementType.TYPE}) 13 | @Documented 14 | public @interface DTO { 15 | 16 | String value() default ""; 17 | 18 | String desc() default ""; 19 | } 20 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/api/Flow.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.api; 2 | 3 | import org.springframework.core.annotation.Order; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * @author zhangcb 9 | * @ClassName Flow.java 10 | * @Description TODO 11 | * @createTime 2020年06月21日 15:38:00 12 | */ 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target(value = {ElementType.METHOD}) 15 | @Documented 16 | public @interface Flow { 17 | 18 | String name(); 19 | 20 | FlowTypeEnum type() default FlowTypeEnum.METHOD; 21 | 22 | String desc() default ""; 23 | } 24 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/api/FlowHandlerInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.api; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName FlowHandlerInterceptor.java 8 | * @Description 自定义拦截器接口 9 | * @createTime 2020年06月22日 06:49:00 10 | */ 11 | public interface FlowHandlerInterceptor { 12 | 13 | Map beforeHandle(); 14 | 15 | Map afterHandle(); 16 | 17 | Map ExceptionHandle(); 18 | } 19 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/api/FlowTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.api; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName FlowTypeEnum.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 15:38:00 8 | */ 9 | public enum FlowTypeEnum { 10 | 11 | METHOD("method"), 12 | SERVICE("service"); 13 | 14 | private String value; 15 | 16 | FlowTypeEnum(String value){ 17 | this.value = value; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/api/IFlowHandler.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.api; 2 | 3 | import com.service.flow.model.BaseInput; 4 | import com.service.flow.model.BaseOutput; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName IFlowHandler.java 9 | * @Description TODO 10 | * @createTime 2020年06月22日 07:17:00 11 | */ 12 | public interface IFlowHandler { 13 | BaseOutput execute(String flowId, BaseInput baseInput); 14 | } 15 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/constant/FlowConstants.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.constant; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName FlowConstants.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 19:21:00 8 | */ 9 | public class FlowConstants { 10 | public static String FLOW = "Flow"; 11 | 12 | public static String COLON = ":"; 13 | 14 | public static String COMMA = ","; 15 | 16 | public static String NODEKEY = "->"; 17 | 18 | public static String NODE = "Node"; 19 | } 20 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/exception/BaseException.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.exception; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName BaseException.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 19:47:00 8 | */ 9 | public abstract class BaseException extends RuntimeException{ 10 | 11 | private static final long serialVersionUID = 1L; 12 | 13 | private ErrorCodeI errCode; 14 | 15 | public BaseException(String errMessage){ 16 | super(errMessage); 17 | } 18 | 19 | public BaseException(String errMessage, Throwable e) { 20 | super(errMessage, e); 21 | } 22 | 23 | public ErrorCodeI getErrCode() { 24 | return errCode; 25 | } 26 | 27 | public void setErrCode(ErrorCodeI errCode) { 28 | this.errCode = errCode; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/exception/BasicErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.exception; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName BasicErrorCode.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 19:45:00 8 | */ 9 | public enum BasicErrorCode implements ErrorCodeI { 10 | 11 | BIZ_ERROR("BIZ_ERROR" , "通用的业务逻辑错误"), 12 | 13 | FLOW_ERROR("FLOW_ERROR" , "框架错误"), 14 | 15 | SYS_ERROR("SYS_ERROR" , "未知的系统错误" ); 16 | 17 | private String errCode; 18 | 19 | private String errDesc; 20 | 21 | private BasicErrorCode(String errCode, String errDesc){ 22 | this.errCode = errCode; 23 | this.errDesc = errDesc; 24 | } 25 | 26 | @Override 27 | public String getErrCode() { 28 | return errCode; 29 | } 30 | 31 | @Override 32 | public String getErrDesc() { 33 | return errDesc; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/exception/BizException.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.exception; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName BizException.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 19:48:00 8 | */ 9 | public class BizException extends BaseException { 10 | 11 | private static final long serialVersionUID = 1L; 12 | 13 | public BizException(String errMessage){ 14 | super(errMessage); 15 | this.setErrCode(BasicErrorCode.BIZ_ERROR); 16 | } 17 | 18 | public BizException(ErrorCodeI errCode, String errMessage){ 19 | super(errMessage); 20 | this.setErrCode(errCode); 21 | } 22 | 23 | public BizException(String errMessage, Throwable e) { 24 | super(errMessage, e); 25 | this.setErrCode(BasicErrorCode.BIZ_ERROR); 26 | } 27 | } -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/exception/ErrorCodeI.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.exception; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName ErrorCodeI.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 19:44:00 8 | */ 9 | public interface ErrorCodeI { 10 | 11 | public String getErrCode(); 12 | 13 | public String getErrDesc(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/exception/FlowException.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.exception; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName FlowException.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 19:47:00 8 | */ 9 | public class FlowException extends BaseException { 10 | 11 | private static final long serialVersionUID = 1L; 12 | 13 | public FlowException(String errMessage){ 14 | super(errMessage); 15 | this.setErrCode(BasicErrorCode.FLOW_ERROR); 16 | } 17 | 18 | public FlowException(String errMessage, Throwable e) { 19 | super(errMessage, e); 20 | this.setErrCode(BasicErrorCode.FLOW_ERROR); 21 | } 22 | } -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/exception/SysException.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.exception; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName SysException.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 19:49:00 8 | */ 9 | public class SysException extends BaseException { 10 | 11 | private static final long serialVersionUID = 4355163994767354840L; 12 | 13 | public SysException(String errMessage){ 14 | super(errMessage); 15 | this.setErrCode(BasicErrorCode.SYS_ERROR); 16 | } 17 | 18 | public SysException(ErrorCodeI errCode, String errMessage) { 19 | super(errMessage); 20 | this.setErrCode(errCode); 21 | } 22 | 23 | public SysException(String errMessage, Throwable e) { 24 | super(errMessage, e); 25 | this.setErrCode(BasicErrorCode.SYS_ERROR); 26 | } 27 | 28 | public SysException(String errMessage, ErrorCodeI errorCode, Throwable e) { 29 | super(errMessage, e); 30 | this.setErrCode(errorCode); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/index/ReflectionsScan.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.index; 2 | 3 | import org.reflections.Reflections; 4 | import org.reflections.scanners.FieldAnnotationsScanner; 5 | import org.reflections.scanners.MethodAnnotationsScanner; 6 | import org.reflections.scanners.MethodParameterScanner; 7 | import org.reflections.scanners.SubTypesScanner; 8 | import org.reflections.util.ConfigurationBuilder; 9 | 10 | /** 11 | * @author zhangcb 12 | * @ClassName ReflectionsScan.java 13 | * @Description TODO 14 | * @createTime 2020年06月29日 21:25:00 15 | */ 16 | public class ReflectionsScan { 17 | public static Reflections scan(String scanName){ 18 | // 扫包 19 | Reflections reflections = new Reflections(new ConfigurationBuilder() 20 | .forPackages(scanName) // 指定路径URL 21 | .addScanners(new SubTypesScanner()) // 添加子类扫描工具 22 | .addScanners(new FieldAnnotationsScanner()) // 添加 属性注解扫描工具 23 | .addScanners(new MethodAnnotationsScanner() ) // 添加 方法注解扫描工具 24 | .addScanners(new MethodParameterScanner() ) // 添加方法参数扫描工具 25 | ); 26 | return reflections; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/index/component/BaseComponentClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.index.component; 2 | 3 | import com.service.flow.api.DTO; 4 | import com.service.flow.api.Flow; 5 | import com.service.flow.api.FlowTypeEnum; 6 | import com.service.flow.exception.FlowException; 7 | import com.service.flow.index.ReflectionsScan; 8 | import com.service.flow.index.dto.DTODefinition; 9 | import org.reflections.Reflections; 10 | import org.reflections.scanners.*; 11 | import org.reflections.util.ConfigurationBuilder; 12 | 13 | import java.lang.reflect.Method; 14 | import java.util.HashMap; 15 | import java.util.Iterator; 16 | import java.util.Map; 17 | import java.util.Set; 18 | 19 | /** 20 | * @author zhangcb 21 | * @ClassName BaseComponentClassLoader.java 22 | * @Description TODO 23 | * @createTime 2020年06月29日 20:29:00 24 | */ 25 | public class BaseComponentClassLoader { 26 | 27 | private Map componentDefinitionMap; 28 | 29 | public BaseComponentClassLoader(){ 30 | this.componentDefinitionMap = new HashMap<>(); 31 | } 32 | 33 | public void load(String scanName) { 34 | // 扫包 35 | Reflections reflections = ReflectionsScan.scan(scanName); 36 | // 获取带有特定注解对应的方法 37 | Set methods = reflections.getMethodsAnnotatedWith(Flow.class ) ; 38 | Iterator iterator = methods.iterator(); 39 | while (iterator.hasNext()){ 40 | Method method = iterator.next(); 41 | Flow annotation = method.getAnnotation(Flow.class); 42 | String name = annotation.name(); 43 | FlowTypeEnum type = annotation.type(); 44 | String desc = annotation.desc(); 45 | String methodName = method.getName(); 46 | String className = method.getDeclaringClass().getName(); 47 | ComponentDefinition componentDefinition = new ComponentDefinition(); 48 | componentDefinition.setValue(name); 49 | componentDefinition.setClassName(className); 50 | componentDefinition.setMethodName(methodName); 51 | componentDefinition.setDesc(desc); 52 | if(componentDefinitionMap.containsKey(name)){ 53 | throw new FlowException(name+"重复定义:"+className+","+componentDefinitionMap.get(name).getClassName()); 54 | } 55 | this.componentDefinitionMap.put(name,componentDefinition); 56 | } 57 | } 58 | 59 | public Map getComponentDefinitionMap(){ 60 | return this.componentDefinitionMap; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/index/component/ComponentDefinition.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.index.component; 2 | 3 | 4 | import com.service.flow.index.dto.DTODefinition; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName ComponentDefinition.java 9 | * @Description TODO 10 | * @createTime 2020年06月29日 07:15:00 11 | */ 12 | public class ComponentDefinition { 13 | 14 | private String value; 15 | 16 | private String desc; 17 | 18 | private String className; 19 | 20 | private String methodName; 21 | 22 | private DTODefinition dtoDefinition; 23 | 24 | public String getValue() { 25 | return value; 26 | } 27 | 28 | public void setValue(String value) { 29 | this.value = value; 30 | } 31 | 32 | public String getDesc() { 33 | return desc; 34 | } 35 | 36 | public void setDesc(String desc) { 37 | this.desc = desc; 38 | } 39 | 40 | public String getClassName() { 41 | return className; 42 | } 43 | 44 | public void setClassName(String className) { 45 | this.className = className; 46 | } 47 | 48 | public String getMethodName() { 49 | return methodName; 50 | } 51 | 52 | public void setMethodName(String methodName) { 53 | this.methodName = methodName; 54 | } 55 | 56 | public DTODefinition getDtoDefinition() { 57 | return dtoDefinition; 58 | } 59 | 60 | public void setDtoDefinition(DTODefinition dtoDefinition) { 61 | this.dtoDefinition = dtoDefinition; 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | return "ComponentDefinition{" + 67 | "value='" + value + '\'' + 68 | ", desc='" + desc + '\'' + 69 | ", className='" + className + '\'' + 70 | ", methodName='" + methodName + '\'' + 71 | ", dtoDefinition=" + dtoDefinition + 72 | '}'; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/index/dto/DTOClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.index.dto; 2 | 3 | import com.service.flow.api.DTO; 4 | import com.service.flow.exception.FlowException; 5 | import com.service.flow.index.ReflectionsScan; 6 | import org.reflections.Reflections; 7 | import org.springframework.core.annotation.AnnotationUtils; 8 | import org.springframework.util.ReflectionUtils; 9 | import org.springframework.util.StringUtils; 10 | 11 | import java.util.HashMap; 12 | import java.util.Iterator; 13 | import java.util.Map; 14 | import java.util.Set; 15 | 16 | /** 17 | * @author zhangcb 18 | * @ClassName DTOClassLoader.java 19 | * @Description TODO 20 | * @createTime 2020年06月29日 07:21:00 21 | */ 22 | public class DTOClassLoader { 23 | 24 | private Map dtoDefinitionMap; 25 | 26 | public DTOClassLoader(){ 27 | this.dtoDefinitionMap = new HashMap<>(); 28 | } 29 | 30 | public void load(String scanName) { 31 | Reflections reflections = ReflectionsScan.scan(scanName); 32 | Set> typesAnnotatedWith = reflections.getTypesAnnotatedWith(DTO.class); 33 | Iterator> iterator = typesAnnotatedWith.iterator(); 34 | while (iterator.hasNext()){ 35 | Class clazz = iterator.next(); 36 | DTO annotation = clazz.getAnnotation(DTO.class); 37 | String simpleName = clazz.getSimpleName(); 38 | String value = StringUtils.isEmpty(annotation.value())?simpleName:annotation.value();; 39 | String desc = annotation.desc(); 40 | DTODefinition dtoDefinition = new DTODefinition(); 41 | dtoDefinition.setClassName(clazz.getName()); 42 | dtoDefinition.setValue(value); 43 | dtoDefinition.setDesc(desc); 44 | if(dtoDefinitionMap.containsKey(value)){ 45 | throw new FlowException(value+"重复定义:"+clazz.getName()+","+dtoDefinitionMap.get(value).getClassName()); 46 | } 47 | dtoDefinitionMap.put(value,dtoDefinition); 48 | } 49 | } 50 | 51 | public Map getDtoDefinitionMap(){ 52 | return this.dtoDefinitionMap; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/index/dto/DTODefinition.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.index.dto; 2 | 3 | 4 | /** 5 | * @author zhangcb 6 | * @ClassName DTODefinition.java 7 | * @Description TODO 8 | * @createTime 2020年06月29日 07:15:00 9 | */ 10 | public class DTODefinition { 11 | 12 | private String value; 13 | 14 | private String desc; 15 | 16 | private String className; 17 | 18 | public String getValue() { 19 | return value; 20 | } 21 | 22 | public void setValue(String value) { 23 | this.value = value; 24 | } 25 | 26 | public String getDesc() { 27 | return desc; 28 | } 29 | 30 | public void setDesc(String desc) { 31 | this.desc = desc; 32 | } 33 | 34 | 35 | public String getClassName() { 36 | return className; 37 | } 38 | 39 | public void setClassName(String className) { 40 | this.className = className; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "DTODefinition{" + 46 | "value='" + value + '\'' + 47 | ", desc='" + desc + '\'' + 48 | ", className='" + className + '\'' + 49 | '}'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/model/BaseInput.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.model; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName BaseInput.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 15:38:00 8 | */ 9 | public class BaseInput { 10 | } 11 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/model/BaseOutput.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.model; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName BaseOutput.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 15:38:00 8 | */ 9 | public class BaseOutput { 10 | } 11 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/model/BaseTemp.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.model; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName BaseTemp.java 8 | * @Description TODO 9 | * @createTime 2020年06月21日 15:38:00 10 | */ 11 | public class BaseTemp { 12 | 13 | private Long totalTime; 14 | 15 | private StringBuffer flowRecord; 16 | 17 | private Map context; 18 | 19 | public Long getTotalTime() { 20 | return totalTime; 21 | } 22 | 23 | public void setTotalTime(Long totalTime) { 24 | this.totalTime = totalTime; 25 | } 26 | 27 | public StringBuffer getFlowRecord() { 28 | return flowRecord; 29 | } 30 | 31 | public void setFlowRecord(StringBuffer flowRecord) { 32 | this.flowRecord = flowRecord; 33 | } 34 | 35 | public Map getContext() { 36 | return context; 37 | } 38 | 39 | public void setContext(Map context) { 40 | this.context = context; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "BaseTemp{" + 46 | "totalTime=" + totalTime + 47 | ", flowRecord=" + flowRecord + 48 | ", context=" + context + 49 | '}'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/model/FlowDefintion.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.model; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName FlowDefintition.java 8 | * @Description TODO 9 | * @createTime 2020年06月21日 15:38:00 10 | */ 11 | public class FlowDefintion { 12 | //流程标识 13 | private String id; 14 | 15 | //流程名称 16 | private String name; 17 | 18 | //请求参数 19 | private String input; 20 | 21 | //输出参数 22 | private String output; 23 | 24 | //临时变量 25 | private String temp; 26 | 27 | //流程描述 28 | private String desc; 29 | 30 | //开启节点 31 | private String startNode; 32 | 33 | //子流程节点 34 | private Map nodeMap; 35 | 36 | public String getId() { 37 | return id; 38 | } 39 | 40 | public void setId(String id) { 41 | this.id = id; 42 | } 43 | 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | public void setName(String name) { 49 | this.name = name; 50 | } 51 | 52 | public String getInput() { 53 | return input; 54 | } 55 | 56 | public void setInput(String input) { 57 | this.input = input; 58 | } 59 | 60 | public String getOutput() { 61 | return output; 62 | } 63 | 64 | public void setOutput(String output) { 65 | this.output = output; 66 | } 67 | 68 | public String getTemp() { 69 | return temp; 70 | } 71 | 72 | public void setTemp(String temp) { 73 | this.temp = temp; 74 | } 75 | 76 | public String getDesc() { 77 | return desc; 78 | } 79 | 80 | public void setDesc(String desc) { 81 | this.desc = desc; 82 | } 83 | 84 | public String getStartNode() { 85 | return startNode; 86 | } 87 | 88 | public void setStartNode(String startNode) { 89 | this.startNode = startNode; 90 | } 91 | 92 | public Map getNodeMap() { 93 | return nodeMap; 94 | } 95 | 96 | public void setNodeMap(Map nodeMap) { 97 | this.nodeMap = nodeMap; 98 | } 99 | 100 | @Override 101 | public String toString() { 102 | return "FlowDefintition{" + 103 | "id='" + id + '\'' + 104 | ", name='" + name + '\'' + 105 | ", input='" + input + '\'' + 106 | ", output='" + output + '\'' + 107 | ", temp='" + temp + '\'' + 108 | ", desc='" + desc + '\'' + 109 | ", startNode='" + startNode + '\'' + 110 | ", nodeMap=" + nodeMap + 111 | '}'; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/model/Node.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.model; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName Node.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 15:38:00 8 | */ 9 | public class Node { 10 | 11 | //节点标识 12 | private String id; 13 | 14 | //节点名称 15 | private String name; 16 | 17 | //节点描述 18 | private String desc; 19 | 20 | //节点输入 21 | private String input; 22 | 23 | //节点类型 24 | private String type; 25 | 26 | //下一个节点标识 27 | private String next; 28 | 29 | //路径 30 | private String component; 31 | 32 | public String getId() { 33 | return id; 34 | } 35 | 36 | public void setId(String id) { 37 | this.id = id; 38 | } 39 | 40 | public String getName() { 41 | return name; 42 | } 43 | 44 | public void setName(String name) { 45 | this.name = name; 46 | } 47 | 48 | public String getDesc() { 49 | return desc; 50 | } 51 | 52 | public void setDesc(String desc) { 53 | this.desc = desc; 54 | } 55 | 56 | public String getInput() { 57 | return input; 58 | } 59 | 60 | public void setInput(String input) { 61 | this.input = input; 62 | } 63 | 64 | public String getType() { 65 | return type; 66 | } 67 | 68 | public void setType(String type) { 69 | this.type = type; 70 | } 71 | 72 | public String getNext() { 73 | return next; 74 | } 75 | 76 | public void setNext(String next) { 77 | this.next = next; 78 | } 79 | 80 | public String getComponent() { 81 | return component; 82 | } 83 | 84 | public void setComponent(String component) { 85 | this.component = component; 86 | } 87 | 88 | @Override 89 | public String toString() { 90 | return "Node{" + 91 | "id='" + id + '\'' + 92 | ", name='" + name + '\'' + 93 | ", desc='" + desc + '\'' + 94 | ", input='" + input + '\'' + 95 | ", type='" + type + '\'' + 96 | ", next='" + next + '\'' + 97 | ", component='" + component + '\'' + 98 | '}'; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/FlowParser.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing; 2 | 3 | import com.service.flow.constant.FlowConstants; 4 | import com.service.flow.model.*; 5 | import com.service.flow.util.BeanUtils; 6 | import com.service.flow.util.ClassUtil; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.util.StopWatch; 10 | 11 | import java.io.IOException; 12 | import java.util.Map; 13 | 14 | /** 15 | * @author zhangcb 16 | * @ClassName FlowParster.java 17 | * @Description 流程加载执行 18 | * @createTime 2020年06月21日 15:38:00 19 | */ 20 | public class FlowParser { 21 | 22 | private Map nodeMap; 23 | 24 | private BaseTemp baseTemp; 25 | 26 | private FlowDefintion defintition; 27 | 28 | private String record; 29 | 30 | private Long totalTime; 31 | 32 | private Logger logger = LoggerFactory.getLogger(FlowParser.class); 33 | 34 | public FlowParser(FlowDefintion defintition){ 35 | this.nodeMap = defintition.getNodeMap(); 36 | this.defintition = defintition; 37 | this.baseTemp = ClassUtil.newInstance(defintition.getTemp(), BaseTemp.class); 38 | } 39 | 40 | /** 41 | * 执行流程 42 | * @param baseInput 请求参数 43 | * @return 44 | * @throws IOException 45 | */ 46 | public BaseOutput execute(BaseInput baseInput) throws IOException { 47 | StopWatch stopWatch = new StopWatch(); 48 | stopWatch.start(); 49 | StringBuffer flowRecord = new StringBuffer(); 50 | flowRecord.append(FlowConstants.FLOW+FlowConstants.COLON +defintition.getId()); 51 | //输入参数 52 | BaseInput baseInputContext = ClassUtil.newInstance(defintition.getInput(), BaseInput.class); 53 | BeanUtils.copyProperties(baseInput,baseInputContext); 54 | BeanUtils.copyProperties(baseInputContext,baseTemp); 55 | baseTemp.setFlowRecord(flowRecord); 56 | BaseOutput baseOutput = ClassUtil.newInstance(defintition.getOutput(), BaseOutput.class); 57 | String startNode = defintition.getStartNode(); 58 | Node node = defintition.getNodeMap().get(startNode); 59 | FlowParserHandler flowParserHandler = new FlowParserHandler(); 60 | baseOutput = flowParserHandler.execNode(node,baseInputContext,baseTemp,nodeMap); 61 | stopWatch.stop(); 62 | record = baseTemp.getFlowRecord().toString(); 63 | totalTime = stopWatch.getTotalTimeMillis(); 64 | //服务节点调用 65 | return baseOutput; 66 | } 67 | 68 | /** 69 | * 获取执行记录 70 | * @return 71 | */ 72 | public String getRecord() { 73 | return record; 74 | } 75 | 76 | /** 77 | * 获取执行时间 78 | * @return 79 | */ 80 | public Long getTotalTime() { 81 | return totalTime; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/FlowParserHandler.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing; 2 | 3 | 4 | import com.service.flow.model.BaseInput; 5 | import com.service.flow.model.BaseOutput; 6 | import com.service.flow.model.BaseTemp; 7 | import com.service.flow.model.Node; 8 | import com.service.flow.parseing.component.NodeComponentFactory; 9 | import com.service.flow.parseing.component.NodeParser; 10 | import com.service.flow.util.BeanUtils; 11 | import org.springframework.util.StringUtils; 12 | 13 | import java.util.Map; 14 | 15 | /** 16 | * @author zhangcb 17 | * @ClassName FlowParserHandler.java 18 | * @Description 流程实行器 19 | * @createTime 2020年06月21日 15:38:00 20 | */ 21 | public class FlowParserHandler { 22 | 23 | /** 24 | * 执行流程节点 25 | * @param node 节点信息 26 | * @param baseInput 输出参数 27 | * @param baseTemp 临时上下文 28 | * @param nodeMap 节点集合 29 | * @return 输出参数 30 | */ 31 | public BaseOutput execNode(Node node, BaseInput baseInput, BaseTemp baseTemp, Map nodeMap){ 32 | String type = node.getType(); 33 | NodeParser nodeInstance = NodeComponentFactory.getNodeInstance(type); 34 | nodeInstance.setNodeMap(nodeMap); 35 | BaseOutput output = nodeInstance.parserNode(node, baseInput,baseTemp); 36 | BeanUtils.copyProperties(output,baseTemp); 37 | BeanUtils.copyProperties(baseTemp,baseInput); 38 | String nextNode = node.getNext(); 39 | if(!StringUtils.isEmpty(nextNode)){ 40 | Node nodeNext = nodeMap.get(nextNode); 41 | output = execNode(nodeNext,baseInput,baseTemp,nodeMap); 42 | } 43 | BeanUtils.copyProperties(baseTemp,output); 44 | return output; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/AbstractNodeComponent.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component; 2 | 3 | import com.service.flow.constant.FlowConstants; 4 | import com.service.flow.model.BaseInput; 5 | import com.service.flow.model.BaseOutput; 6 | import com.service.flow.model.BaseTemp; 7 | import com.service.flow.model.Node; 8 | import com.service.flow.util.BeanUtils; 9 | import com.service.flow.util.ClassUtil; 10 | 11 | import java.util.Map; 12 | 13 | /** 14 | * @author zhangcb 15 | * @ClassName MethodComponent.java 16 | * @Description TODO 17 | * @createTime 2020年06月19日 08:15:00 18 | */ 19 | public abstract class AbstractNodeComponent implements NodeParser{ 20 | 21 | public Map nodeMap; 22 | 23 | 24 | /** 25 | * 初始化参数 26 | * @param inputUrl 27 | * @param baseInput 28 | * @return 29 | */ 30 | public BaseInput initInput(String inputUrl, BaseInput baseInput){ 31 | BaseInput baseInputTarget = ClassUtil.newInstance(inputUrl, BaseInput.class); 32 | BeanUtils.copyProperties(baseInput,baseInputTarget); 33 | return baseInputTarget; 34 | } 35 | 36 | 37 | /** 38 | * 解析节点信息 39 | * @param node 节点信息 40 | * @param baseInput 请求参数 41 | * @param baseTemp 临时上下文 42 | * @return 43 | */ 44 | public BaseOutput parserNode(Node node, BaseInput baseInput, BaseTemp baseTemp){ 45 | baseTemp.setFlowRecord(baseTemp.getFlowRecord().append(FlowConstants.NODEKEY+FlowConstants.NODE+FlowConstants.COLON+node.getId())); 46 | BaseOutput baseOutput = parser(node, baseInput, baseTemp); 47 | return baseOutput; 48 | }; 49 | 50 | @Override 51 | public void setNodeMap(Map nodeMap) { 52 | this.nodeMap = nodeMap; 53 | } 54 | 55 | @Override 56 | public abstract BaseOutput parser(Node node, BaseInput baseInput, BaseTemp baseTemp); 57 | 58 | } 59 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/NodeComponentFactory.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component; 2 | 3 | import com.service.flow.parseing.component.bean.BeanNodeComponent; 4 | import com.service.flow.parseing.component.condition.ConditionNodeComponent; 5 | import com.service.flow.parseing.component.method.MethodNodeComponent; 6 | import com.service.flow.parseing.component.service.ServiceNodeComponent; 7 | import com.service.flow.parseing.component.subflow.SubFlowNodeComponent; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | /** 13 | * @author zhangcb 14 | * @ClassName NodeComponentFactory.java 15 | * @Description 节点解析工厂函数 16 | * @createTime 2020年06月19日 08:25:00 17 | */ 18 | public class NodeComponentFactory { 19 | 20 | private final static Map cacheParser = new HashMap<>(); 21 | 22 | static { 23 | cacheParser.put(NodeParserEnum.method.name(),new MethodNodeComponent()); 24 | cacheParser.put(NodeParserEnum.bean.name(),new BeanNodeComponent()); 25 | cacheParser.put(NodeParserEnum.condition.name(),new ConditionNodeComponent()); 26 | cacheParser.put(NodeParserEnum.service.name(),new ServiceNodeComponent()); 27 | cacheParser.put(NodeParserEnum.subflow.name(),new SubFlowNodeComponent()); 28 | } 29 | 30 | public static NodeParser getNodeInstance(String nodeName){ 31 | return cacheParser.get(nodeName); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/NodeParser.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component; 2 | 3 | import com.service.flow.model.BaseInput; 4 | import com.service.flow.model.BaseOutput; 5 | import com.service.flow.model.BaseTemp; 6 | import com.service.flow.model.Node; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * @author zhangcb 12 | * @ClassName NodeParser.java 13 | * @Description TODO 14 | * @createTime 2020年06月19日 08:16:00 15 | */ 16 | public interface NodeParser { 17 | 18 | BaseOutput parserNode(Node node, BaseInput baseInput, BaseTemp baseTemp); 19 | 20 | BaseOutput parser(Node node, BaseInput baseInput, BaseTemp baseTemp); 21 | 22 | void setNodeMap(Map nodeMap); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/NodeParserEnum.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName NodeParserEnum.java 6 | * @Description TODO 7 | * @createTime 2020年06月19日 08:28:00 8 | */ 9 | public enum NodeParserEnum { 10 | method("method"), 11 | bean("bean"), 12 | condition("condition"), 13 | service("service"), 14 | subflow("subflow"); 15 | 16 | private String value; 17 | 18 | NodeParserEnum(String value){ 19 | this.value = value; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/bean/BeanNodeComponent.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component.bean; 2 | 3 | import com.service.flow.constant.FlowConstants; 4 | import com.service.flow.model.BaseInput; 5 | import com.service.flow.model.BaseOutput; 6 | import com.service.flow.model.BaseTemp; 7 | import com.service.flow.model.Node; 8 | import com.service.flow.parseing.component.AbstractNodeComponent; 9 | import com.service.flow.util.ClassUtil; 10 | import com.service.flow.util.SpringContextUtil; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | /** 15 | * @author zhangcb 16 | * @ClassName MethodComponent.java 17 | * @Description bean节点解析 18 | * @createTime 2020年06月19日 08:15:00 19 | */ 20 | public class BeanNodeComponent extends AbstractNodeComponent { 21 | 22 | private Logger logger = LoggerFactory.getLogger(BeanNodeComponent.class); 23 | 24 | @Override 25 | public BaseOutput parser(Node node, BaseInput baseInput, BaseTemp baseTemp) { 26 | logger.debug("Start execution bean node{NodeId:{},NodeName:{}}",node.getId(),node.getName()); 27 | BaseInput initInput = initInput(node.getInput(), baseInput); 28 | String component = node.getComponent(); 29 | String[] split = component.split(FlowConstants.COLON); 30 | Object bean = SpringContextUtil.getBean(split[0]); 31 | String simpleName = bean.getClass().getName(); 32 | BaseOutput baseOutput = (BaseOutput)ClassUtil.methodInvoke(simpleName,split[1],initInput); 33 | logger.debug("End of execution bean node{NodeId:{},NodeName:{}}",node.getId(),node.getName()); 34 | return baseOutput; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/condition/ConditionNodeComponent.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component.condition; 2 | 3 | import com.service.flow.constant.FlowConstants; 4 | import com.service.flow.model.BaseInput; 5 | import com.service.flow.model.BaseOutput; 6 | import com.service.flow.model.BaseTemp; 7 | import com.service.flow.model.Node; 8 | import com.service.flow.parseing.FlowParserHandler; 9 | import com.service.flow.parseing.component.AbstractNodeComponent; 10 | import com.service.flow.parseing.component.NodeComponentFactory; 11 | import com.service.flow.parseing.component.NodeParser; 12 | import com.service.flow.util.SpleUtils; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | import org.springframework.util.StringUtils; 16 | 17 | import java.util.Arrays; 18 | import java.util.concurrent.atomic.AtomicReference; 19 | 20 | /** 21 | * @author zhangcb 22 | * @ClassName ConditionNodeComponent.java 23 | * @Description 条件节点解析 24 | * @createTime 2020年06月19日 19:25:00 25 | */ 26 | public class ConditionNodeComponent extends AbstractNodeComponent { 27 | 28 | private Logger logger = LoggerFactory.getLogger(ConditionNodeComponent.class); 29 | 30 | private int count = 0; 31 | 32 | @Override 33 | public BaseOutput parser(Node node, BaseInput baseInput, BaseTemp baseTemp) { 34 | logger.debug("Start execution condition node{NodeId:{},NodeName:{}}",node.getId(),node.getName()); 35 | String conditions = node.getComponent(); 36 | String[] condition = conditions.split(FlowConstants.COMMA); 37 | AtomicReference output = new AtomicReference<>(new BaseOutput()); 38 | Arrays.stream(condition).forEach(str->{ 39 | String[] split1 = str.split(FlowConstants.COLON); 40 | Object eval = SpleUtils.eval(split1[0], baseTemp); 41 | if(Boolean.parseBoolean(eval.toString())){ 42 | String nodeStr = split1[1]; 43 | Node nodeByCondition = nodeMap.get(nodeStr); 44 | String nextNode = nodeByCondition.getNext(); 45 | if(!StringUtils.isEmpty(nextNode)){ 46 | FlowParserHandler flowParserHandler = new FlowParserHandler(); 47 | output.set(flowParserHandler.execNode(nodeByCondition, baseInput, baseTemp, nodeMap)); 48 | }else{ 49 | //解决循环执行节点问题 50 | count++; 51 | if(count==1) { 52 | String type = nodeByCondition.getType(); 53 | NodeParser nodeInstance = NodeComponentFactory.getNodeInstance(type); 54 | nodeInstance.setNodeMap(nodeMap); 55 | output.set(nodeInstance.parserNode(nodeByCondition, baseInput, baseTemp)); 56 | } 57 | } 58 | } 59 | }); 60 | logger.debug("End of execution condition node{NodeId:{},NodeName:{}}",node.getId(),node.getName()); 61 | return output.get(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/method/MethodNodeComponent.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component.method; 2 | 3 | import com.service.flow.constant.FlowConstants; 4 | import com.service.flow.model.BaseInput; 5 | import com.service.flow.model.BaseOutput; 6 | import com.service.flow.model.BaseTemp; 7 | import com.service.flow.model.Node; 8 | import com.service.flow.parseing.component.AbstractNodeComponent; 9 | import com.service.flow.util.ClassUtil; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | /** 14 | * @author zhangcb 15 | * @ClassName MethodComponent.java 16 | * @Description 方法节点解析 17 | * @createTime 2020年06月19日 08:15:00 18 | */ 19 | public class MethodNodeComponent extends AbstractNodeComponent { 20 | 21 | private Logger logger = LoggerFactory.getLogger(MethodNodeComponent.class); 22 | 23 | @Override 24 | public BaseOutput parser(Node node, BaseInput baseInput, BaseTemp baseTemp) { 25 | logger.debug("Start execution method node{NodeId:{},NodeName:{}}",node.getId(),node.getName()); 26 | BaseInput initInput = initInput(node.getInput(), baseInput); 27 | String component = node.getComponent(); 28 | String[] split = component.split(FlowConstants.COLON); 29 | BaseOutput baseOutput = (BaseOutput)ClassUtil.methodInvoke(split[0],split[1],initInput); 30 | logger.debug("End of execution method node{NodeId:{},NodeName:{}}",node.getId(),node.getName()); 31 | return baseOutput; 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/service/SampleServiceProxy.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component.service; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName SampleServiceInvoke.java 6 | * @Description TODO 7 | * @createTime 2020年06月21日 12:14:00 8 | */ 9 | public class SampleServiceProxy implements ServiceProxy { 10 | 11 | private ServiceModel serviceModel; 12 | 13 | public SampleServiceProxy(ServiceModel serviceModel){ 14 | this.serviceModel = serviceModel; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/service/ServiceModel.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component.service; 2 | 3 | import com.service.flow.model.BaseInput; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName ServiceModel.java 8 | * @Description TODO 9 | * @createTime 2020年06月21日 12:05:00 10 | */ 11 | public class ServiceModel { 12 | 13 | private String applicationName; 14 | 15 | private String uri; 16 | 17 | private String requestType; 18 | 19 | private BaseInput baseInput; 20 | 21 | public String getApplicationName() { 22 | return applicationName; 23 | } 24 | 25 | public void setApplicationName(String applicationName) { 26 | this.applicationName = applicationName; 27 | } 28 | 29 | public String getUri() { 30 | return uri; 31 | } 32 | 33 | public void setUri(String uri) { 34 | this.uri = uri; 35 | } 36 | 37 | public String getRequestType() { 38 | return requestType; 39 | } 40 | 41 | public void setRequestType(String requestType) { 42 | this.requestType = requestType; 43 | } 44 | 45 | public BaseInput getBaseInput() { 46 | return baseInput; 47 | } 48 | 49 | public void setBaseInput(BaseInput baseInput) { 50 | this.baseInput = baseInput; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/service/ServiceNodeComponent.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component.service; 2 | 3 | import com.service.flow.constant.FlowConstants; 4 | import com.service.flow.model.BaseInput; 5 | import com.service.flow.model.BaseOutput; 6 | import com.service.flow.model.BaseTemp; 7 | import com.service.flow.model.Node; 8 | import com.service.flow.parseing.component.AbstractNodeComponent; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | /** 13 | * @author zhangcb 14 | * @ClassName MethodComponent.java 15 | * @Description 服务节点解析 16 | * @createTime 2020年06月19日 08:15:00 17 | */ 18 | public class ServiceNodeComponent extends AbstractNodeComponent { 19 | 20 | private Logger logger = LoggerFactory.getLogger(ServiceNodeComponent.class); 21 | 22 | @Override 23 | public BaseOutput parser(Node node, BaseInput baseInput, BaseTemp baseTemp) { 24 | logger.debug("Start execution service node{NodeId:{},NodeName:{}}",node.getId(),node.getName()); 25 | String component = node.getComponent(); 26 | String[] split = component.split(FlowConstants.COLON); 27 | ServiceModel serviceModel = new ServiceModel(); 28 | serviceModel.setUri(split[0]); 29 | serviceModel.setRequestType(split[1]); 30 | serviceModel.setApplicationName(split[1]); 31 | ServiceProxy serviceProxy =new SampleServiceProxy(serviceModel); 32 | logger.debug("End of execution service node{NodeId:{},NodeName:{}}",node.getId(),node.getName()); 33 | return serviceProxy.invoke(baseInput); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/service/ServiceProxy.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component.service; 2 | 3 | import com.service.flow.model.BaseInput; 4 | import com.service.flow.model.BaseOutput; 5 | import com.service.flow.parseing.component.method.MethodNodeComponent; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.BeanUtils; 9 | 10 | /** 11 | * @author zhangcb 12 | * @ClassName ServiceProxy.java 13 | * @Description TODO 14 | * @createTime 2020年06月21日 12:11:00 15 | */ 16 | public interface ServiceProxy { 17 | 18 | Logger logger = LoggerFactory.getLogger(ServiceProxy.class); 19 | 20 | default BaseOutput invoke(BaseInput baseInput){ 21 | logger.info("Execute default service node,input:{}",baseInput); 22 | return new BaseOutput(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/parseing/component/subflow/SubFlowNodeComponent.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing.component.subflow; 2 | 3 | import com.service.flow.api.IFlowHandler; 4 | import com.service.flow.model.BaseInput; 5 | import com.service.flow.model.BaseOutput; 6 | import com.service.flow.model.BaseTemp; 7 | import com.service.flow.model.Node; 8 | import com.service.flow.parseing.component.AbstractNodeComponent; 9 | import com.service.flow.util.SpringContextUtil; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | /** 14 | * @author zhangcb 15 | * @ClassName SubFlowNodeComponent.java 16 | * @Description 子流程节点解析 17 | * @createTime 2020年06月21日 15:38:00 18 | */ 19 | public class SubFlowNodeComponent extends AbstractNodeComponent { 20 | 21 | private Logger logger = LoggerFactory.getLogger(SubFlowNodeComponent.class); 22 | @Override 23 | public BaseOutput parser(Node node, BaseInput baseInput, BaseTemp baseTemp) { 24 | logger.debug("Start execution subFlow node{NodeId:{},NodeName:{}}",node.getId(),node.getName()); 25 | String component = node.getComponent(); 26 | IFlowHandler flowHandler = SpringContextUtil.getBean(IFlowHandler.class); 27 | BaseOutput baseOutput = flowHandler.execute(component, baseInput); 28 | logger.debug("End of execution subFlow node{NodeId:{},NodeName:{}}",node.getId(),node.getName()); 29 | return baseOutput; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/support/FlowDefintionRegistry.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.support; 2 | 3 | import com.service.flow.model.FlowDefintion; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * @author zhangcb 9 | * @ClassName FlowDefintionRegistry.java 10 | * @Description 流程模型加载接口 11 | * @createTime 2020年06月21日 15:38:00 12 | */ 13 | public interface FlowDefintionRegistry { 14 | /** 15 | * flow注册接口 16 | * @return 17 | * @throws Exception 18 | */ 19 | Map registry() throws Exception; 20 | } 21 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/support/FlowDefintitionFactory.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.support; 2 | 3 | import com.service.flow.exception.FlowException; 4 | import com.service.flow.model.FlowDefintion; 5 | import com.service.flow.support.yml.YmlFlowDefintionRegistry; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * @author zhangcb 14 | * @ClassName FlowDefintition.java 15 | * @Description 流程模型加载工厂 16 | * @createTime 2020年06月21日 15:38:00 17 | */ 18 | public class FlowDefintitionFactory { 19 | 20 | public static List flowDefintionRegistries = new ArrayList<>(); 21 | 22 | public static Map flowDefintitionMap = new HashMap<>(); 23 | 24 | static { 25 | flowDefintionRegistries.add(new YmlFlowDefintionRegistry()); 26 | } 27 | 28 | /** 29 | * 初始化流程加载 30 | */ 31 | public void initDefintionFactory() { 32 | flowDefintionRegistries.forEach(flowDefintionRegistry -> { 33 | try { 34 | flowDefintitionMap.putAll(flowDefintionRegistry.registry()); 35 | } catch (Exception e) { 36 | throw new FlowException("Flow loading exception",e); 37 | } 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/support/yml/TempNode.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.support.yml; 2 | 3 | import com.service.flow.model.Node; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName TempNode.java 8 | * @Description 对应uml格式的临时模型 9 | * @createTime 2020年06月21日 15:38:00 10 | */ 11 | public class TempNode { 12 | 13 | private Node node; 14 | 15 | public Node getNode() { 16 | return node; 17 | } 18 | 19 | public void setNode(Node node) { 20 | this.node = node; 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return "TempNode{" + 26 | "node=" + node + 27 | '}'; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/support/yml/YmlFlow.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.support.yml; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Flow.java 8 | * @Description 流程对应的yml模型 9 | * @createTime 2020年06月21日 15:38:00 10 | */ 11 | public class YmlFlow { 12 | 13 | //流程标识 14 | private String id; 15 | 16 | //流程名称 17 | private String name; 18 | 19 | //请求参数 20 | private String input; 21 | 22 | //输出参数 23 | private String output; 24 | 25 | //临时变量 26 | private String temp; 27 | 28 | //流程描述 29 | private String desc; 30 | 31 | //开启节点 32 | private String startNode; 33 | 34 | //流程节点 35 | private List nodes; 36 | 37 | public String getId() { 38 | return id; 39 | } 40 | 41 | public void setId(String id) { 42 | this.id = id; 43 | } 44 | 45 | public String getName() { 46 | return name; 47 | } 48 | 49 | public void setName(String name) { 50 | this.name = name; 51 | } 52 | 53 | public String getInput() { 54 | return input; 55 | } 56 | 57 | public void setInput(String input) { 58 | this.input = input; 59 | } 60 | 61 | public String getOutput() { 62 | return output; 63 | } 64 | 65 | public void setOutput(String output) { 66 | this.output = output; 67 | } 68 | 69 | public String getTemp() { 70 | return temp; 71 | } 72 | 73 | public void setTemp(String temp) { 74 | this.temp = temp; 75 | } 76 | 77 | public String getDesc() { 78 | return desc; 79 | } 80 | 81 | public void setDesc(String desc) { 82 | this.desc = desc; 83 | } 84 | 85 | public List getNodes() { 86 | return nodes; 87 | } 88 | 89 | public void setNodes(List nodes) { 90 | this.nodes = nodes; 91 | } 92 | 93 | 94 | public String getStartNode() { 95 | return startNode; 96 | } 97 | 98 | public void setStartNode(String startNode) { 99 | this.startNode = startNode; 100 | } 101 | 102 | @Override 103 | public String toString() { 104 | return "Flow{" + 105 | "id='" + id + '\'' + 106 | ", name='" + name + '\'' + 107 | ", input='" + input + '\'' + 108 | ", output='" + output + '\'' + 109 | ", temp='" + temp + '\'' + 110 | ", desc='" + desc + '\'' + 111 | ", startNode='" + startNode + '\'' + 112 | ", nodes=" + nodes + 113 | '}'; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/support/yml/YmlFlowDefintionRegistry.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.support.yml; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.JSONObject; 5 | import com.service.flow.model.FlowDefintion; 6 | import com.service.flow.model.Node; 7 | import com.service.flow.support.FlowDefintionRegistry; 8 | import org.springframework.beans.factory.config.YamlMapFactoryBean; 9 | import org.springframework.core.io.Resource; 10 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 11 | import org.springframework.core.io.support.ResourcePatternResolver; 12 | 13 | import java.util.Arrays; 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | 17 | /** 18 | * @author zhangcb 19 | * @ClassName YmlFlowDefintionRegistry.java 20 | * @Description 基于YML格式注册流程模型 21 | * @createTime 2020年06月21日 15:38:00 22 | */ 23 | public class YmlFlowDefintionRegistry implements FlowDefintionRegistry { 24 | 25 | private final String CLASSPATH_FLOW="flow/*.flow.yml"; 26 | 27 | @Override 28 | public Map registry() throws Exception{ 29 | return registryModel(); 30 | } 31 | 32 | /** 33 | * 注册流程模型 34 | * @return 35 | * @throws Exception 36 | */ 37 | public Map registryModel() throws Exception { 38 | ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); 39 | Resource[] resources = resolver.getResources(CLASSPATH_FLOW); 40 | Map flowMap = new HashMap<>(); 41 | Arrays.stream(resources).forEach(resource->{ 42 | YamlMapFactoryBean yamlMapFactoryBean = new YamlMapFactoryBean(); 43 | yamlMapFactoryBean.setResources(resource); 44 | yamlMapFactoryBean.afterPropertiesSet(); 45 | Map object = yamlMapFactoryBean.getObject(); 46 | YmlFlow flow = JSONObject.parseObject(JSON.toJSONString(object), YmlFlow.class); 47 | flowMap.put(flow.getId(),buildFlowDefintition(flow)); 48 | }); 49 | return flowMap; 50 | } 51 | 52 | private FlowDefintion buildFlowDefintition(YmlFlow flow){ 53 | FlowDefintion flowDefintition = new FlowDefintion(); 54 | flowDefintition.setId(flow.getId()); 55 | flowDefintition.setName(flow.getName()); 56 | flowDefintition.setDesc(flow.getDesc()); 57 | flowDefintition.setInput(flow.getInput()); 58 | flowDefintition.setOutput(flow.getOutput()); 59 | flowDefintition.setTemp(flow.getTemp()); 60 | flowDefintition.setStartNode(flow.getStartNode()); 61 | Map nodeMap = new HashMap<>(); 62 | flow.getNodes().forEach(tempNode -> { 63 | Node node = tempNode.getNode(); 64 | nodeMap.put(node.getId(),node); 65 | }); 66 | flowDefintition.setNodeMap(nodeMap); 67 | return flowDefintition; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/util/BeanUtils.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.util; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.FatalBeanException; 5 | import org.springframework.util.Assert; 6 | 7 | import java.beans.PropertyDescriptor; 8 | import java.lang.reflect.Method; 9 | import java.lang.reflect.Modifier; 10 | 11 | /** 12 | * @author zhangcb 13 | * @ClassName BeanUtils.java 14 | * @Description TODO 15 | * @createTime 2020年07月06日 08:28:00 16 | */ 17 | public class BeanUtils extends org.springframework.beans.BeanUtils { 18 | /** 19 | * 将source中不为空的字段,拷贝(覆盖)到target中 20 | * @param source 21 | * @param target 22 | * @throws BeansException 23 | */ 24 | public static void copyProperties(Object source, Object target) throws BeansException { 25 | Assert.notNull(source, "Source must not be null"); 26 | Assert.notNull(target, "Target must not be null"); 27 | Class actualEditable = target.getClass(); 28 | PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable); 29 | for (PropertyDescriptor targetPd : targetPds) { 30 | if (targetPd.getWriteMethod() != null) { 31 | PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName()); 32 | if (sourcePd != null && sourcePd.getReadMethod() != null) { 33 | try { 34 | Method readMethod = sourcePd.getReadMethod(); 35 | if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { 36 | readMethod.setAccessible(true); 37 | } 38 | Object value = readMethod.invoke(source); 39 | // 这里判断以下value是否为空 当然这里也能进行一些特殊要求的处理 例如绑定时格式转换等等 40 | if (value != null) { 41 | Method writeMethod = targetPd.getWriteMethod(); 42 | if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { 43 | writeMethod.setAccessible(true); 44 | } 45 | writeMethod.invoke(target, value); 46 | } 47 | } catch (Throwable ex) { 48 | throw new FatalBeanException("Could not copy properties from source to target", ex); 49 | } 50 | } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/util/ClassUtil.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.util; 2 | 3 | 4 | import org.springframework.lang.Nullable; 5 | import org.springframework.util.ClassUtils; 6 | import org.springframework.util.ReflectionUtils; 7 | 8 | import java.lang.reflect.Method; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * @author zhangcb 14 | * @ClassName ClassUtils.java 15 | * @Description 类反射工具类 16 | * @createTime 2020年06月21日 15:38:00 17 | */ 18 | public class ClassUtil { 19 | 20 | /** 21 | * 创建新的实例对象 22 | * @param className 类名 23 | * @param expected 转换目标对象 24 | * @param params 请求参数 25 | * @param 26 | * @return 27 | */ 28 | public static E newInstance(String className, Class expected, Object... params) { 29 | Class aClass = forName(className); 30 | return newInstance(aClass, expected, params); 31 | } 32 | 33 | /** 34 | * 根据类名映射类 35 | * @param className 类名 36 | * @return 37 | */ 38 | public static Class forName(String className) { 39 | try { 40 | return ClassUtils.forName(className, Thread.currentThread().getContextClassLoader()); 41 | } catch (ClassNotFoundException ex) { 42 | throw new IllegalArgumentException(ex); 43 | } 44 | } 45 | 46 | /** 47 | * 创建新的实例对象 48 | * @param clazz 类名 49 | * @param expected 转换目标对象 50 | * @param params 请求参数 51 | * @param 52 | * @return 53 | */ 54 | public static E newInstance(Class clazz, Class expected, Object... params) { 55 | if (expected != null && !expected.isAssignableFrom(clazz)) { 56 | throw new IllegalArgumentException( 57 | "'" + clazz.getSimpleName() + "'" + "'must implements interface:'" + expected.getName() + "'"); 58 | } 59 | if (params == null || params.length == 0) { 60 | try { 61 | return (E) clazz.newInstance(); 62 | } catch (Exception e) { 63 | throw new IllegalArgumentException(e); 64 | } 65 | } else { 66 | List> parameterTypes = getParamsType(params); 67 | try { 68 | return (E) clazz.getConstructor(parameterTypes.toArray(new Class[0])).newInstance(params); 69 | } catch (Exception e) { 70 | throw new IllegalArgumentException(e); 71 | } 72 | } 73 | } 74 | 75 | /** 76 | * 获取参数列表 77 | * @param params 78 | * @return 79 | */ 80 | public static List> getParamsType(@Nullable Object... params) { 81 | List> parameterTypes = new ArrayList<>(); 82 | if (params != null && params.length > 0) { 83 | for (Object o : params) { 84 | parameterTypes.add(o.getClass()); 85 | } 86 | 87 | } 88 | return parameterTypes; 89 | } 90 | 91 | /** 92 | * 根据类名获取方法的个数 93 | * @param className 类名 94 | * @param methodName 方法名 95 | * @return 96 | */ 97 | public static int getMethodCountForMame(String className, String methodName) { 98 | Class clazz = forName(className); 99 | return ClassUtils.getMethodCountForName(clazz, methodName); 100 | } 101 | 102 | /** 103 | * 判断是否有该方法 104 | * @param className 类名 105 | * @param methodName 方法名 106 | * @param paramTypes 参数 107 | * @return 108 | */ 109 | public static boolean hasMethod(String className, String methodName, @Nullable Class... paramTypes) { 110 | Class clazz = forName(className); 111 | return ClassUtils.hasMethod(clazz, methodName, paramTypes); 112 | } 113 | 114 | /** 115 | * 方法调用 116 | * @param className 类名 117 | * @param methodName 方法名 118 | * @param params 参数 119 | * @param 120 | * @return 121 | */ 122 | public static Object methodInvoke(String className, String methodName, @Nullable Object... params) { 123 | Class clazz = forName(className); 124 | Object target; 125 | try { 126 | target = clazz.newInstance(); 127 | } catch (InstantiationException | IllegalArgumentException | IllegalAccessException e) { 128 | throw new IllegalArgumentException(e); 129 | } 130 | return methodInvoke(target, methodName, params); 131 | } 132 | 133 | /** 134 | * 方法调用 135 | * @param target 类名 136 | * @param methodName 方法名 137 | * @param params 参数 138 | * @param 139 | * @return 140 | */ 141 | public static Object methodInvoke(Object target, String methodName, @Nullable Object... params) { 142 | List> parameterTypes = getParamsType(params); 143 | Method method = ReflectionUtils.findMethod(target.getClass(), methodName, 144 | parameterTypes.toArray(new Class[0])); 145 | Object ret = null; 146 | if (method == null) { 147 | throw new RuntimeException("方法不存在:" + methodName); 148 | } 149 | ret = ReflectionUtils.invokeMethod(method, target, params); 150 | return ret; 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/util/SpleUtils.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.util; 2 | 3 | import org.springframework.expression.ExpressionParser; 4 | import org.springframework.expression.spel.standard.SpelExpressionParser; 5 | import org.springframework.expression.spel.support.StandardEvaluationContext; 6 | 7 | /** 8 | * @author zhangcb 9 | * @ClassName SpleUtils.java 10 | * @Description SpringEl表达式验证工具类 11 | * @createTime 2020年06月21日 15:38:00 12 | */ 13 | public class SpleUtils { 14 | 15 | public static Object eval(String expr, Object contextValue) { 16 | StandardEvaluationContext conetxt = new StandardEvaluationContext(contextValue); 17 | ExpressionParser parser = new SpelExpressionParser(); 18 | return parser.parseExpression(expr).getValue(conetxt); 19 | } 20 | 21 | public static void evalSet(String expr, Object contextValue, Object value) { 22 | StandardEvaluationContext conetxt = new StandardEvaluationContext(contextValue); 23 | ExpressionParser parser = new SpelExpressionParser(); 24 | parser.parseExpression(expr).setValue(conetxt, value); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /service-flow-sdk/src/main/java/com/service/flow/util/SpringContextUtil.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.util; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * @author zhangcb 10 | * @ClassName SpringContextUtil.java 11 | * @Description 获取Spring上下文工具类 12 | * @createTime 2020年06月21日 15:38:00 13 | */ 14 | @Component 15 | public class SpringContextUtil implements ApplicationContextAware { 16 | 17 | private static ApplicationContext context; 18 | 19 | @Override 20 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 21 | SpringContextUtil.context = applicationContext; 22 | } 23 | 24 | public static ApplicationContext getApplicationContext() { 25 | return context; 26 | } 27 | 28 | public static Object getBean(String beanName) { 29 | return context.getBean(beanName); 30 | } 31 | 32 | public static T getBean(String beanName,Class requiredType) { 33 | return context.getBean(beanName,requiredType); 34 | } 35 | 36 | public static T getBean(Class requiredType) { 37 | return context.getBean(requiredType); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /service-flow-sdk/src/test/java/com/service/flow/parseing/FlowParserTest.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing; 2 | 3 | import com.service.flow.exception.FlowException; 4 | import com.service.flow.model.BaseInput; 5 | import com.service.flow.model.BaseOutput; 6 | import com.service.flow.model.FlowDefintion; 7 | import com.service.flow.support.FlowDefintitionFactory; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import java.io.IOException; 11 | import java.util.Map; 12 | 13 | /** 14 | * @author zhangcb 15 | * @ClassName FlowParserTest.java 16 | * @Description TODO 17 | * @createTime 2020年06月22日 21:49:00 18 | */ 19 | class FlowParserTest { 20 | 21 | @Test 22 | void execute() { 23 | FlowDefintitionFactory flowDefintitionFactory = new FlowDefintitionFactory(); 24 | flowDefintitionFactory.initDefintionFactory(); 25 | Map flowDefintitionMap = flowDefintitionFactory.flowDefintitionMap; 26 | FlowDefintion defintition = flowDefintitionMap.get("test"); 27 | 28 | BaseInput baseInput = new BaseInput(); 29 | FlowParser flowParser = new FlowParser(defintition); 30 | BaseOutput execute = null; 31 | try{ 32 | execute = flowParser.execute(baseInput); 33 | }catch (IOException e){ 34 | throw new FlowException("Flow execution exception"); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /service-flow-sdk/src/test/java/com/service/flow/parseing/TestComponent.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing; 2 | 3 | import com.service.flow.model.BaseOutput; 4 | import org.springframework.beans.BeanUtils; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * @author zhangcb 9 | * @ClassName TestComponent.java 10 | * @Description TODO 11 | * @createTime 2020年06月17日 17:06:00 12 | */ 13 | @Component("testComponent") 14 | public class TestComponent { 15 | 16 | public TestOutput test1(TestInput test){ 17 | TestOutput testOutput = new TestOutput(); 18 | BeanUtils.copyProperties(test,testOutput); 19 | System.out.println("1111111111"+testOutput); 20 | return testOutput; 21 | } 22 | 23 | public BaseOutput test2(TestInput test){ 24 | TestOutput testOutput = new TestOutput(); 25 | BeanUtils.copyProperties(test,testOutput); 26 | testOutput.setAge(22); 27 | System.out.println("222222222222"+testOutput); 28 | return testOutput; 29 | } 30 | 31 | public BaseOutput test3(TestInput test){ 32 | TestOutput testOutput = new TestOutput(); 33 | BeanUtils.copyProperties(test,testOutput); 34 | testOutput.setAge(33); 35 | System.out.println("3333333333"+testOutput); 36 | return testOutput; 37 | } 38 | public BaseOutput test4(TestInput test){ 39 | TestOutput testOutput = new TestOutput(); 40 | BeanUtils.copyProperties(test,testOutput); 41 | testOutput.setAge(44); 42 | System.out.println("444444444444444"+testOutput); 43 | return testOutput; 44 | } 45 | public BaseOutput test5(TestInput test){ 46 | TestOutput testOutput = new TestOutput(); 47 | BeanUtils.copyProperties(test,testOutput); 48 | testOutput.setAge(55); 49 | System.out.println("555555555555"+testOutput); 50 | return testOutput; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /service-flow-sdk/src/test/java/com/service/flow/parseing/TestInput.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing; 2 | 3 | import com.service.flow.model.BaseInput; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Test.java 8 | * @Description TODO 9 | * @createTime 2020年06月17日 17:09:00 10 | */ 11 | public class TestInput extends BaseInput { 12 | private String name; 13 | 14 | private Integer age; 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public Integer getAge() { 25 | return age; 26 | } 27 | 28 | public void setAge(Integer age) { 29 | this.age = age; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return "Test{" + 35 | "name='" + name + '\'' + 36 | ", age=" + age + 37 | '}'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /service-flow-sdk/src/test/java/com/service/flow/parseing/TestOutput.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing; 2 | 3 | import com.service.flow.model.BaseOutput; 4 | 5 | /** 6 | * @author zhangcb 7 | * @ClassName Test.java 8 | * @Description TODO 9 | * @createTime 2020年06月17日 17:09:00 10 | */ 11 | public class TestOutput extends BaseOutput { 12 | private String name; 13 | 14 | private Integer age; 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public Integer getAge() { 25 | return age; 26 | } 27 | 28 | public void setAge(Integer age) { 29 | this.age = age; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return "Test{" + 35 | "name='" + name + '\'' + 36 | ", age=" + age + 37 | '}'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /service-flow-sdk/src/test/java/com/service/flow/parseing/TestTemp.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.parseing; 2 | 3 | 4 | import com.service.flow.model.BaseTemp; 5 | 6 | /** 7 | * @author zhangcb 8 | * @ClassName TestComponent.java 9 | * @Description TODO 10 | * @createTime 2020年06月17日 17:06:00 11 | */ 12 | public class TestTemp extends BaseTemp { 13 | 14 | private String name; 15 | 16 | private Integer age; 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public void setName(String name) { 23 | this.name = name; 24 | } 25 | 26 | public Integer getAge() { 27 | return age; 28 | } 29 | 30 | public void setAge(Integer age) { 31 | this.age = age; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | return "Test{" + 37 | "name='" + name + '\'' + 38 | ", age=" + age + 39 | '}'; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /service-flow-sdk/src/test/java/com/service/flow/support/FlowDefintitionFactoryTest.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.support; 2 | 3 | import com.service.flow.model.FlowDefintion; 4 | import org.junit.Assert; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * @author zhangcb 11 | * @ClassName FlowDefintitionFactoryTest.java 12 | * @Description TODO 13 | * @createTime 2020年06月22日 14:07:00 14 | */ 15 | class FlowDefintitionFactoryTest { 16 | 17 | @Test 18 | void initDefintionFactory() { 19 | FlowDefintitionFactory flowDefintitionFactory = new FlowDefintitionFactory(); 20 | flowDefintitionFactory.initDefintionFactory(); 21 | Map flowDefintitionMap = flowDefintitionFactory.flowDefintitionMap; 22 | Assert.assertEquals(true,flowDefintitionMap.containsKey("test")); 23 | } 24 | } -------------------------------------------------------------------------------- /service-flow-sdk/src/test/resources/flow/test1.flow.yml: -------------------------------------------------------------------------------- 1 | name: openAccount 2 | id: test 3 | desc: 条件执行 4 | input: com.service.flow.parseing.TestInput 5 | output: com.service.flow.parseing.TestOutput 6 | temp: com.service.flow.parseing.TestTemp 7 | startNode: node1 8 | nodes: 9 | - node: 10 | id: node1 11 | name: methodInvoke 12 | component: com.service.flow.parseing.TestComponent:test1 13 | desc: 单节点执行 14 | input: com.service.flow.parseing.TestInput 15 | type: method 16 | next: node2 17 | - node: 18 | id: node2 19 | name: beanInvoke 20 | component: com.service.flow.parseing.TestComponent:test1 21 | desc: 单节点执行 22 | input: com.service.flow.parseing.TestInput 23 | type: method 24 | next: node3 25 | - node: 26 | id: node3 27 | name: conditionByAge 28 | component: age>20:node4,age<20:node5 29 | desc: 条件节点执行 30 | type: condition 31 | - node: 32 | id: node4 33 | name: beanInvoke 34 | component: com.service.flow.parseing.TestComponent:test1 35 | desc: bean节点执行 36 | input: com.service.flow.parseing.TestInput 37 | type: method 38 | - node: 39 | id: node5 40 | name: beanInvoke 41 | component: com.service.flow.parseing.TestComponent:test1 42 | desc: bean节点执行 43 | input: com.service.flow.parseing.TestInput 44 | type: method 45 | next: node6 46 | - node: 47 | id: node6 48 | name: serviceInvoke 49 | component: /test:post:testApplication 50 | desc: 方法节点调用 51 | input: com.service.flow.parseing.TestInput 52 | type: service 53 | -------------------------------------------------------------------------------- /service-flow-sdk/src/test/resources/flow/test2.flow.yml: -------------------------------------------------------------------------------- 1 | name: openAccount 2 | id: test2 3 | desc: 条件执行 4 | input: com.service.flow.parseing.TestInput 5 | output: com.service.flow.parseing.TestOutput 6 | temp: com.service.flow.parseing.TestTemp 7 | startNode: node1 8 | nodes: 9 | - node: 10 | id: node1 11 | name: methodInvoke 12 | component: com.service.flow.parseing.TestComponent:test1 13 | desc: 单节点执行 14 | input: com.service.flow.sample.common.model.TestInput 15 | type: method 16 | -------------------------------------------------------------------------------- /service-flow-spring-boot-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.service.flow 7 | service-flow-parent 8 | 1.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | service-flow-spring-boot-starter 13 | 14 | 15 | 16 | com.service.flow 17 | service-flow-sdk 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-web 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-test 26 | test 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /service-flow-spring-boot-starter/src/main/java/com/service/flow/web/TestApplication.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.web; 2 | 3 | /** 4 | * @author zhangcb 5 | * @ClassName TestApplication.java 6 | * @Description TODO 7 | * @createTime 2020年06月22日 07:03:00 8 | */ 9 | public class TestApplication { 10 | } 11 | -------------------------------------------------------------------------------- /service-flow-spring-boot-starter/src/main/java/com/service/flow/web/api/AbstractFlowHandler.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.web.api; 2 | 3 | import com.service.flow.api.IFlowHandler; 4 | import com.service.flow.exception.FlowException; 5 | import com.service.flow.model.BaseInput; 6 | import com.service.flow.model.BaseOutput; 7 | import com.service.flow.model.FlowDefintion; 8 | import com.service.flow.parseing.FlowParser; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.io.IOException; 13 | 14 | /** 15 | * @author zhangcb 16 | * @ClassName AbstractFlowHandler.java 17 | * @Description TODO 18 | * @createTime 2020年06月30日 07:17:00 19 | */ 20 | public abstract class AbstractFlowHandler implements IFlowHandler { 21 | 22 | private Logger logger = LoggerFactory.getLogger(AbstractFlowHandler.class); 23 | 24 | @Override 25 | public BaseOutput execute(String flowId, BaseInput baseInput) { 26 | FlowParser flowParser = new FlowParser(flowDefintion(flowId)); 27 | BaseOutput execute = null; 28 | try{ 29 | execute = flowParser.execute(baseInput); 30 | }catch (IOException e){ 31 | throw new FlowException("Flow execution exception"); 32 | } 33 | logger.info("result:{}",execute); 34 | logger.info("record:{}",flowParser.getRecord()); 35 | logger.info("totalTime:{}ms",flowParser.getTotalTime()); 36 | return execute; 37 | } 38 | 39 | public abstract FlowDefintion flowDefintion(String flowId); 40 | } 41 | -------------------------------------------------------------------------------- /service-flow-spring-boot-starter/src/main/java/com/service/flow/web/api/AnnotationFlowHandler.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.web.api; 2 | 3 | import com.service.flow.constant.FlowConstants; 4 | import com.service.flow.index.component.ComponentDefinition; 5 | import com.service.flow.index.dto.DTODefinition; 6 | import com.service.flow.model.FlowDefintion; 7 | import com.service.flow.model.Node; 8 | import com.service.flow.parseing.FlowParser; 9 | import com.service.flow.parseing.component.NodeParserEnum; 10 | import com.service.flow.web.context.ComponentContext; 11 | import com.service.flow.web.context.DtoContext; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Component; 14 | 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | /** 19 | * @author zhangcb 20 | * @ClassName AnnotationFlowHandler.java 21 | * @Description TODO 22 | * @createTime 2020年06月30日 07:13:00 23 | */ 24 | @Component 25 | public class AnnotationFlowHandler extends AbstractFlowHandler{ 26 | 27 | @Autowired 28 | private FlowHandler flowHandler; 29 | 30 | @Autowired 31 | private DtoContext dtoContext; 32 | 33 | @Autowired 34 | private ComponentContext componentContext; 35 | 36 | @Override 37 | public FlowDefintion flowDefintion(String flowId) { 38 | FlowDefintion flowDefintion = flowHandler.flowDefintion(flowId); 39 | String input = flowDefintion.getInput(); 40 | flowDefintion.setInput(dtoClassName(input)); 41 | String output = flowDefintion.getOutput(); 42 | flowDefintion.setOutput(dtoClassName(output)); 43 | String temp = flowDefintion.getTemp(); 44 | flowDefintion.setTemp(dtoClassName(temp)); 45 | Map nodeMap = flowDefintion.getNodeMap(); 46 | nodeClassName(nodeMap); 47 | return flowDefintion; 48 | } 49 | 50 | private String dtoClassName(String dto){ 51 | Map dtoDefinitionMap = dtoContext.getDtoDefinitionMap(); 52 | DTODefinition dtoDefinition = dtoDefinitionMap.get(dto); 53 | if(null != dtoDefinition){ 54 | dto = dtoDefinition.getClassName(); 55 | } 56 | return dto; 57 | } 58 | 59 | private void nodeClassName(Map nodeMap){ 60 | Map nodeMapNew = new HashMap<>(); 61 | Map componentDefinitionMap = componentContext.getComponentDefinitionMap(); 62 | nodeMap.forEach((nodeId,node)->{ 63 | String input = node.getInput(); 64 | node.setInput(dtoClassName(input)); 65 | if(NodeParserEnum.method.name().equals(node.getType())){ 66 | String component = node.getComponent(); 67 | ComponentDefinition componentDefinition = componentDefinitionMap.get(component); 68 | String compon = componentDefinition.getClassName() + FlowConstants.COLON + componentDefinition.getMethodName(); 69 | node.setComponent(compon); 70 | } 71 | }); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /service-flow-spring-boot-starter/src/main/java/com/service/flow/web/api/FlowHandler.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.web.api; 2 | 3 | import com.service.flow.api.IFlowHandler; 4 | import com.service.flow.exception.FlowException; 5 | import com.service.flow.model.BaseInput; 6 | import com.service.flow.model.BaseOutput; 7 | import com.service.flow.model.FlowDefintion; 8 | import com.service.flow.parseing.FlowParser; 9 | import com.service.flow.web.context.FlowContext; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Component; 14 | 15 | import java.io.IOException; 16 | 17 | /** 18 | * @author zhangcb 19 | * @ClassName FlowApi.java 20 | * @Description TODO 21 | * @createTime 2020年06月21日 15:38:00 22 | */ 23 | @Component 24 | public class FlowHandler extends AbstractFlowHandler { 25 | 26 | private Logger logger = LoggerFactory.getLogger(FlowHandler.class); 27 | 28 | @Autowired 29 | private FlowContext flowContext; 30 | 31 | @Override 32 | public FlowDefintion flowDefintion(String flowId) { 33 | return flowContext.getFlowDefinition(flowId); 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /service-flow-spring-boot-starter/src/main/java/com/service/flow/web/config/FlowConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.web.config; 2 | 3 | import com.service.flow.index.component.BaseComponentClassLoader; 4 | import com.service.flow.index.dto.DTOClassLoader; 5 | import com.service.flow.support.FlowDefintitionFactory; 6 | import com.service.flow.web.context.ComponentContext; 7 | import com.service.flow.web.context.DtoContext; 8 | import com.service.flow.web.context.FlowContext; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | 13 | /** 14 | * @author zhangcb 15 | * @ClassName FlowConfiguration.java 16 | * @Description TODO 17 | * @createTime 2020年06月21日 15:38:00 18 | */ 19 | @Configuration 20 | public class FlowConfiguration { 21 | 22 | private String scanName = "com.service.flow"; 23 | 24 | @Bean 25 | public FlowContext flowContext(){ 26 | FlowDefintitionFactory flowDefintitionFactory = new FlowDefintitionFactory(); 27 | flowDefintitionFactory.initDefintionFactory(); 28 | FlowContext flowContext = new FlowContext(); 29 | flowContext.setFlowDefintitionMap(flowDefintitionFactory.flowDefintitionMap); 30 | return flowContext; 31 | } 32 | 33 | @Bean 34 | public DtoContext dtoContext(){ 35 | DTOClassLoader dtoClassLoader = new DTOClassLoader(); 36 | dtoClassLoader.load(scanName); 37 | DtoContext dtoContext = new DtoContext(); 38 | dtoContext.setDtoDefinitionMap(dtoClassLoader.getDtoDefinitionMap()); 39 | return dtoContext; 40 | } 41 | 42 | @Bean 43 | public ComponentContext componentContext(){ 44 | BaseComponentClassLoader baseComponentClassLoader = new BaseComponentClassLoader(); 45 | baseComponentClassLoader.load(scanName); 46 | ComponentContext componentContext = new ComponentContext(); 47 | componentContext.setComponentDefinitionMap(baseComponentClassLoader.getComponentDefinitionMap()); 48 | return componentContext; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /service-flow-spring-boot-starter/src/main/java/com/service/flow/web/context/ComponentContext.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.web.context; 2 | 3 | import com.service.flow.index.component.ComponentDefinition; 4 | import com.service.flow.index.dto.DTODefinition; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * @author zhangcb 10 | * @ClassName FlowContext.java 11 | * @Description TODO 12 | * @createTime 2020年06月21日 15:38:00 13 | */ 14 | public class ComponentContext { 15 | 16 | private Map componentDefinitionMap; 17 | 18 | public Map getComponentDefinitionMap() { 19 | return componentDefinitionMap; 20 | } 21 | 22 | public void setComponentDefinitionMap(Map componentDefinitionMap) { 23 | this.componentDefinitionMap = componentDefinitionMap; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return "ComponentContext{" + 29 | "componentDefinitionMap=" + componentDefinitionMap + 30 | '}'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /service-flow-spring-boot-starter/src/main/java/com/service/flow/web/context/DtoContext.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.web.context; 2 | 3 | import com.service.flow.index.dto.DTODefinition; 4 | import com.service.flow.model.FlowDefintion; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * @author zhangcb 10 | * @ClassName FlowContext.java 11 | * @Description TODO 12 | * @createTime 2020年06月21日 15:38:00 13 | */ 14 | public class DtoContext { 15 | 16 | private Map dtoDefinitionMap; 17 | 18 | public Map getDtoDefinitionMap() { 19 | return dtoDefinitionMap; 20 | } 21 | 22 | public void setDtoDefinitionMap(Map dtoDefinitionMap) { 23 | this.dtoDefinitionMap = dtoDefinitionMap; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return "DtoContext{" + 29 | "dtoDefinitionMap=" + dtoDefinitionMap + 30 | '}'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /service-flow-spring-boot-starter/src/main/java/com/service/flow/web/context/FlowContext.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.web.context; 2 | 3 | import com.service.flow.model.FlowDefintion; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * @author zhangcb 9 | * @ClassName FlowContext.java 10 | * @Description TODO 11 | * @createTime 2020年06月21日 15:38:00 12 | */ 13 | public class FlowContext { 14 | 15 | private Map flowDefintitionMap; 16 | 17 | public Map getFlowDefintitionMap() { 18 | return flowDefintitionMap; 19 | } 20 | 21 | public void setFlowDefintitionMap(Map flowDefintitionMap) { 22 | this.flowDefintitionMap = flowDefintitionMap; 23 | } 24 | 25 | public FlowDefintion getFlowDefinition(String flowId){ 26 | return flowDefintitionMap.get(flowId); 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return "FlowContext{" + 32 | "flowDefintitionMap=" + flowDefintitionMap + 33 | '}'; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /service-flow-spring-boot-starter/src/main/java/com/service/flow/web/controller/FlowController.java: -------------------------------------------------------------------------------- 1 | package com.service.flow.web.controller; 2 | 3 | import com.service.flow.model.FlowDefintion; 4 | import com.service.flow.web.context.FlowContext; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import java.util.Map; 11 | 12 | /** 13 | * @author zhangcb 14 | * @ClassName FlowController.java 15 | * @Description TODO 16 | * @createTime 2020年06月22日 07:13:00 17 | */ 18 | @RestController 19 | @RequestMapping("/flows") 20 | public class FlowController { 21 | 22 | @Autowired 23 | private FlowContext flowContext; 24 | 25 | @GetMapping 26 | public Map getAllFlows(){ 27 | return flowContext.getFlowDefintitionMap(); 28 | } 29 | } 30 | --------------------------------------------------------------------------------