mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-14 04:02:09 +08:00
增加了内部策略调用特性
重写了节点步骤打印
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
||||
<artifactId>liteflow</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<version>1.2.2</version>
|
||||
<version>1.2.3</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
@@ -46,7 +46,7 @@ public class FlowExecutor {
|
||||
try {
|
||||
FlowParser.parseLocal(path);
|
||||
} catch (Exception e) {
|
||||
String errorMsg = MessageFormat.format("init flow executor cause error,cannot parse rule file{}", path);
|
||||
String errorMsg = MessageFormat.format("init flow executor cause error,cannot parse rule file{0}", path);
|
||||
throw new FlowExecutorNotInitException(errorMsg);
|
||||
}
|
||||
}
|
||||
@@ -57,26 +57,47 @@ public class FlowExecutor {
|
||||
}
|
||||
|
||||
public <T> T execute(String chainId,Object param){
|
||||
return execute(chainId, param, DefaultSlot.class);
|
||||
return execute(chainId, param, DefaultSlot.class,null,false);
|
||||
}
|
||||
|
||||
public <T> T execute(String chainId,Object param,Class<? extends Slot> slotClazz){
|
||||
int slotIndex = -1;
|
||||
return execute(chainId, param, slotClazz,null,false);
|
||||
}
|
||||
|
||||
public <T> T invoke(String chainId,Class<? extends Slot> slotClazz,Integer slotIndex){
|
||||
return execute(chainId,null, slotClazz,slotIndex,true);
|
||||
}
|
||||
|
||||
public <T> T execute(String chainId,Object param,Class<? extends Slot> slotClazz,Integer slotIndex,boolean isInnerChain){
|
||||
try{
|
||||
if(FlowBus.needInit()) {
|
||||
init();
|
||||
}
|
||||
|
||||
Chain chain = FlowBus.getChain(chainId);
|
||||
|
||||
if(chain == null){
|
||||
String errorMsg = MessageFormat.format("couldn't find chain with the id[{}]", chainId);
|
||||
String errorMsg = MessageFormat.format("couldn't find chain with the id[{0}]", chainId);
|
||||
throw new ChainNotFoundException(errorMsg);
|
||||
}
|
||||
|
||||
slotIndex = DataBus.offerSlot(slotClazz);
|
||||
LOG.info("slot[{}] offered",slotIndex);
|
||||
if(!isInnerChain && slotIndex == null) {
|
||||
slotIndex = DataBus.offerSlot(slotClazz);
|
||||
LOG.info("slot[{}] offered",slotIndex);
|
||||
}
|
||||
|
||||
if(slotIndex == -1){
|
||||
throw new NoAvailableSlotException("there is no available slot");
|
||||
}
|
||||
|
||||
DataBus.getSlot(slotIndex).setRequestData(param);
|
||||
Slot slot = DataBus.getSlot(slotIndex);
|
||||
if(slot == null) {
|
||||
throw new NoAvailableSlotException("the slot is not exist");
|
||||
}
|
||||
|
||||
if(!isInnerChain && param != null) {
|
||||
slot.setRequestData(param);
|
||||
}
|
||||
|
||||
List<Condition> conditionList = chain.getConditionList();
|
||||
|
||||
@@ -97,7 +118,7 @@ public class FlowExecutor {
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
String errorMsg = MessageFormat.format("component[{}] do not gain access", component.getClass().getSimpleName());
|
||||
String errorMsg = MessageFormat.format("component[{0}] do not gain access", component.getClass().getSimpleName());
|
||||
throw new ComponentNotAccessException(errorMsg);
|
||||
}
|
||||
}catch(Throwable t){
|
||||
@@ -116,12 +137,17 @@ public class FlowExecutor {
|
||||
latch.await(15, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
DataBus.getSlot(slotIndex).printStep();
|
||||
return DataBus.getSlot(slotIndex).getResponseData();
|
||||
if(!isInnerChain) {
|
||||
slot.printStep();
|
||||
}
|
||||
return slot.getResponseData();
|
||||
}catch(Exception e){
|
||||
LOG.error("executor cause error",e);
|
||||
throw new FlowSystemException("executor cause error");
|
||||
}finally{
|
||||
DataBus.releaseSlot(slotIndex);
|
||||
if(!isInnerChain) {
|
||||
DataBus.releaseSlot(slotIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.thebeastshop.liteflow.entity.config.Node;
|
||||
import com.thebeastshop.liteflow.entity.data.CmpStep;
|
||||
import com.thebeastshop.liteflow.entity.data.CmpStepType;
|
||||
import com.thebeastshop.liteflow.entity.data.DataBus;
|
||||
import com.thebeastshop.liteflow.entity.data.Slot;
|
||||
import com.thebeastshop.liteflow.entity.monitor.CompStatistics;
|
||||
@@ -30,6 +32,7 @@ public abstract class NodeComponent {
|
||||
private String nodeId;
|
||||
|
||||
public void execute() throws Exception{
|
||||
this.getSlot().addStep(new CmpStep(nodeId, CmpStepType.START));
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
long initm=Runtime.getRuntime().freeMemory();
|
||||
@@ -39,7 +42,7 @@ public abstract class NodeComponent {
|
||||
long timeSpent = stopWatch.getTime();
|
||||
long endm=Runtime.getRuntime().freeMemory();
|
||||
|
||||
this.getSlot().addStep(nodeId);
|
||||
this.getSlot().addStep(new CmpStep(nodeId, CmpStepType.END));
|
||||
|
||||
//性能统计
|
||||
CompStatistics statistics = new CompStatistics();
|
||||
@@ -93,6 +96,10 @@ public abstract class NodeComponent {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Integer getSlotIndex() {
|
||||
return this.slotIndexTL.get();
|
||||
}
|
||||
|
||||
public <T extends Slot> T getSlot(){
|
||||
return DataBus.getSlot(this.slotIndexTL.get());
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
*/
|
||||
package com.thebeastshop.liteflow.entity.data;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -31,7 +34,7 @@ public abstract class AbsSlot implements Slot{
|
||||
|
||||
private final String NODE_OUTPUT_PREFIX = "output_";
|
||||
|
||||
private List<String> executeSteps = new ArrayList<String>();
|
||||
private Deque<CmpStep> executeSteps = new ArrayDeque<CmpStep>();
|
||||
|
||||
protected ConcurrentHashMap<String, Object> dataMap = new ConcurrentHashMap<String, Object>();
|
||||
|
||||
@@ -83,15 +86,22 @@ public abstract class AbsSlot implements Slot{
|
||||
return (T)dataMap.get(COND_NODE_PREFIX + key);
|
||||
}
|
||||
|
||||
public void addStep(String nodeId){
|
||||
this.executeSteps.add(nodeId);
|
||||
public void addStep(CmpStep step){
|
||||
CmpStep lastStep = this.executeSteps.peekLast();
|
||||
if(lastStep != null && lastStep.equals(step)) {
|
||||
lastStep.setStepType(CmpStepType.SINGLE);
|
||||
}else {
|
||||
this.executeSteps.add(step);
|
||||
}
|
||||
}
|
||||
|
||||
public void printStep(){
|
||||
StringBuffer str = new StringBuffer();
|
||||
for(int i = 0; i < this.executeSteps.size(); i++){
|
||||
str.append(executeSteps.get(i));
|
||||
if(i < this.executeSteps.size()-1){
|
||||
CmpStep cmpStep = null;
|
||||
for (Iterator<CmpStep> it = executeSteps.iterator(); it.hasNext();) {
|
||||
cmpStep = it.next();
|
||||
str.append(cmpStep);
|
||||
if(it.hasNext()){
|
||||
str.append("==>");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* <p>Title: liteFlow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* <p>Copyright: Copyright (c) 2017</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2017-12-8
|
||||
* @version 1.0
|
||||
*/
|
||||
package com.thebeastshop.liteflow.entity.data;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
public class CmpStep {
|
||||
private String nodeId;
|
||||
|
||||
private CmpStepType stepType;
|
||||
|
||||
public CmpStep(String nodeId, CmpStepType stepType) {
|
||||
this.nodeId = nodeId;
|
||||
this.stepType = stepType;
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
public void setNodeId(String nodeId) {
|
||||
this.nodeId = nodeId;
|
||||
}
|
||||
|
||||
public CmpStepType getStepType() {
|
||||
return stepType;
|
||||
}
|
||||
|
||||
public void setStepType(CmpStepType stepType) {
|
||||
this.stepType = stepType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if(stepType.equals(CmpStepType.SINGLE)) {
|
||||
return MessageFormat.format("{0}", nodeId);
|
||||
}else {
|
||||
return MessageFormat.format("{0}({1})", nodeId,stepType);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}else {
|
||||
if(getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}else {
|
||||
if(((CmpStep)obj).getNodeId().equals(this.getNodeId())) {
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* <p>Title: beast-price</p>
|
||||
* <p>Description: 价格计算服务</p>
|
||||
* <p>Copyright: Copyright (c) 2017</p>
|
||||
* @author Bryan.Zhang
|
||||
* @Date 2017年12月8日
|
||||
*/
|
||||
package com.thebeastshop.liteflow.entity.data;
|
||||
|
||||
public enum CmpStepType {
|
||||
START,
|
||||
END,
|
||||
SINGLE;
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public interface Slot {
|
||||
|
||||
public <T> T getCondResult(String key);
|
||||
|
||||
public void addStep(String nodeId);
|
||||
public void addStep(CmpStep step);
|
||||
|
||||
public void printStep();
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ package com.thebeastshop.liteflow.flow;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
|
||||
import com.thebeastshop.liteflow.entity.config.Chain;
|
||||
|
||||
public class FlowBus {
|
||||
@@ -31,4 +33,8 @@ public class FlowBus {
|
||||
}
|
||||
chainMap.put(name, chain);
|
||||
}
|
||||
|
||||
public static boolean needInit() {
|
||||
return MapUtils.isEmpty(chainMap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ public class ComponentScaner implements BeanPostProcessor, PriorityOrdered {
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
Class clazz = bean.getClass();
|
||||
|
||||
@@ -17,7 +17,7 @@ import com.thebeastshop.liteflow.parser.FlowParser;
|
||||
public class TestMain {
|
||||
public static void main(String[] args) throws Exception {
|
||||
final FlowExecutor executor = new FlowExecutor();
|
||||
executor.setRulePath(Arrays.asList(new String[]{"flow.xml"}));
|
||||
executor.setRulePath(Arrays.asList(new String[]{"config/flow.xml"}));
|
||||
executor.init();
|
||||
|
||||
for(int i=0;i<1;i++){
|
||||
|
||||
@@ -25,11 +25,11 @@ public class TestWithSpringMain {
|
||||
public void test1() throws Exception {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(10);
|
||||
|
||||
for(int i=0;i<1;i++){
|
||||
for(int i=0;i<10;i++){
|
||||
executorService.submit(new Thread(){
|
||||
@Override
|
||||
public void run() {
|
||||
String response = flowExecutor.execute("chain2", "it's a request");
|
||||
String response = flowExecutor.execute("chain1", "it's a request");
|
||||
System.out.println(response);
|
||||
}
|
||||
});
|
||||
@@ -37,4 +37,16 @@ public class TestWithSpringMain {
|
||||
System.out.println("done!");
|
||||
System.in.read();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() throws Exception {
|
||||
try {
|
||||
String response = flowExecutor.execute("chain3", "it's a request");
|
||||
System.out.println(response);
|
||||
System.in.read();
|
||||
}catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* <p>Title: liteFlow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* <p>Copyright: Copyright (c) 2017</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2017-8-1
|
||||
* @version 1.0
|
||||
*/
|
||||
package com.thebeastshop.liteflow.test.component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.thebeastshop.liteflow.core.FlowExecutor;
|
||||
import com.thebeastshop.liteflow.core.NodeComponent;
|
||||
import com.thebeastshop.liteflow.entity.data.DefaultSlot;
|
||||
|
||||
@Component("h")
|
||||
public class HComponent extends NodeComponent {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("Hcomponent executed!");
|
||||
flowExecutor.invoke("strategy", DefaultSlot.class, this.getSlotIndex());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* <p>Title: liteFlow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* <p>Copyright: Copyright (c) 2017</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2017-8-1
|
||||
* @version 1.0
|
||||
*/
|
||||
package com.thebeastshop.liteflow.test.component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.thebeastshop.liteflow.core.FlowExecutor;
|
||||
import com.thebeastshop.liteflow.core.NodeComponent;
|
||||
|
||||
@Component("m1")
|
||||
public class M1Component extends NodeComponent {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("m1 component executed!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* <p>Title: liteFlow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* <p>Copyright: Copyright (c) 2017</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2017-8-1
|
||||
* @version 1.0
|
||||
*/
|
||||
package com.thebeastshop.liteflow.test.component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.thebeastshop.liteflow.core.FlowExecutor;
|
||||
import com.thebeastshop.liteflow.core.NodeComponent;
|
||||
|
||||
@Component("m2")
|
||||
public class M2Component extends NodeComponent {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("m2 component executed!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* <p>Title: liteFlow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* <p>Copyright: Copyright (c) 2017</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2017-8-1
|
||||
* @version 1.0
|
||||
*/
|
||||
package com.thebeastshop.liteflow.test.component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.thebeastshop.liteflow.core.FlowExecutor;
|
||||
import com.thebeastshop.liteflow.core.NodeComponent;
|
||||
import com.thebeastshop.liteflow.core.NodeCondComponent;
|
||||
|
||||
@Component("m")
|
||||
public class MComponent extends NodeCondComponent {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Override
|
||||
protected String processCond() throws Exception {
|
||||
System.out.println("m conponent executed");
|
||||
return "m1";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,8 +24,10 @@
|
||||
</chain>
|
||||
|
||||
<chain name="chain3">
|
||||
<then value="a,c,g"/>
|
||||
<when value="b,e"/>
|
||||
<then value="d,f"/>
|
||||
<then value="a,c,h,g"/>
|
||||
</chain>
|
||||
|
||||
<chain name="strategy">
|
||||
<then value="m(m1|m2)"/>
|
||||
</chain>
|
||||
</flow>
|
||||
@@ -10,7 +10,7 @@
|
||||
<context:component-scan base-package="com.thebeastshop.liteflow.test.component" />
|
||||
<bean class="com.thebeastshop.liteflow.spring.ComponentScaner"/>
|
||||
|
||||
<bean id="flowExecutor" class="com.thebeastshop.liteflow.core.FlowExecutor" init-method="init">
|
||||
<bean id="flowExecutor" class="com.thebeastshop.liteflow.core.FlowExecutor">
|
||||
<property name="rulePath">
|
||||
<list>
|
||||
<value>config/flow.xml</value>
|
||||
|
||||
Reference in New Issue
Block a user