diff --git a/pom.xml b/pom.xml index 3c1ed2b7f..a38f32236 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ liteflow jar 4.0.0 - 1.2.2 + 1.2.3 UTF-8 diff --git a/src/main/java/com/thebeastshop/liteflow/core/FlowExecutor.java b/src/main/java/com/thebeastshop/liteflow/core/FlowExecutor.java index 136b78bbf..f748eb789 100644 --- a/src/main/java/com/thebeastshop/liteflow/core/FlowExecutor.java +++ b/src/main/java/com/thebeastshop/liteflow/core/FlowExecutor.java @@ -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 execute(String chainId,Object param){ - return execute(chainId, param, DefaultSlot.class); + return execute(chainId, param, DefaultSlot.class,null,false); } public T execute(String chainId,Object param,Class slotClazz){ - int slotIndex = -1; + return execute(chainId, param, slotClazz,null,false); + } + + public T invoke(String chainId,Class slotClazz,Integer slotIndex){ + return execute(chainId,null, slotClazz,slotIndex,true); + } + + public T execute(String chainId,Object param,Class 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 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); + } } } diff --git a/src/main/java/com/thebeastshop/liteflow/core/NodeComponent.java b/src/main/java/com/thebeastshop/liteflow/core/NodeComponent.java index ca07d8897..a4552a299 100644 --- a/src/main/java/com/thebeastshop/liteflow/core/NodeComponent.java +++ b/src/main/java/com/thebeastshop/liteflow/core/NodeComponent.java @@ -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 getSlot(){ return DataBus.getSlot(this.slotIndexTL.get()); } diff --git a/src/main/java/com/thebeastshop/liteflow/entity/data/AbsSlot.java b/src/main/java/com/thebeastshop/liteflow/entity/data/AbsSlot.java index 4ed0ff3ea..417d81af5 100644 --- a/src/main/java/com/thebeastshop/liteflow/entity/data/AbsSlot.java +++ b/src/main/java/com/thebeastshop/liteflow/entity/data/AbsSlot.java @@ -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 executeSteps = new ArrayList(); + private Deque executeSteps = new ArrayDeque(); protected ConcurrentHashMap dataMap = new ConcurrentHashMap(); @@ -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 it = executeSteps.iterator(); it.hasNext();) { + cmpStep = it.next(); + str.append(cmpStep); + if(it.hasNext()){ str.append("==>"); } } diff --git a/src/main/java/com/thebeastshop/liteflow/entity/data/CmpStep.java b/src/main/java/com/thebeastshop/liteflow/entity/data/CmpStep.java new file mode 100644 index 000000000..3076df018 --- /dev/null +++ b/src/main/java/com/thebeastshop/liteflow/entity/data/CmpStep.java @@ -0,0 +1,67 @@ +/** + *

Title: liteFlow

+ *

Description: 轻量级的组件式流程框架

+ *

Copyright: Copyright (c) 2017

+ * @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; + } + } + } + } +} diff --git a/src/main/java/com/thebeastshop/liteflow/entity/data/CmpStepType.java b/src/main/java/com/thebeastshop/liteflow/entity/data/CmpStepType.java new file mode 100644 index 000000000..ba40c63ea --- /dev/null +++ b/src/main/java/com/thebeastshop/liteflow/entity/data/CmpStepType.java @@ -0,0 +1,14 @@ +/** + *

Title: beast-price

+ *

Description: 价格计算服务

+ *

Copyright: Copyright (c) 2017

+ * @author Bryan.Zhang + * @Date 2017年12月8日 + */ +package com.thebeastshop.liteflow.entity.data; + +public enum CmpStepType { + START, + END, + SINGLE; +} diff --git a/src/main/java/com/thebeastshop/liteflow/entity/data/Slot.java b/src/main/java/com/thebeastshop/liteflow/entity/data/Slot.java index c6e5ca159..c7556439f 100644 --- a/src/main/java/com/thebeastshop/liteflow/entity/data/Slot.java +++ b/src/main/java/com/thebeastshop/liteflow/entity/data/Slot.java @@ -34,7 +34,7 @@ public interface Slot { public T getCondResult(String key); - public void addStep(String nodeId); + public void addStep(CmpStep step); public void printStep(); } diff --git a/src/main/java/com/thebeastshop/liteflow/flow/FlowBus.java b/src/main/java/com/thebeastshop/liteflow/flow/FlowBus.java index 72e142429..d8130c33f 100644 --- a/src/main/java/com/thebeastshop/liteflow/flow/FlowBus.java +++ b/src/main/java/com/thebeastshop/liteflow/flow/FlowBus.java @@ -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); + } } diff --git a/src/main/java/com/thebeastshop/liteflow/spring/ComponentScaner.java b/src/main/java/com/thebeastshop/liteflow/spring/ComponentScaner.java index 1249e21cf..81c74891a 100644 --- a/src/main/java/com/thebeastshop/liteflow/spring/ComponentScaner.java +++ b/src/main/java/com/thebeastshop/liteflow/spring/ComponentScaner.java @@ -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(); diff --git a/src/test/java/com/thebeastshop/liteflow/test/TestMain.java b/src/test/java/com/thebeastshop/liteflow/test/TestMain.java index 0406f66ae..eb1096cfe 100644 --- a/src/test/java/com/thebeastshop/liteflow/test/TestMain.java +++ b/src/test/java/com/thebeastshop/liteflow/test/TestMain.java @@ -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++){ diff --git a/src/test/java/com/thebeastshop/liteflow/test/TestWithSpringMain.java b/src/test/java/com/thebeastshop/liteflow/test/TestWithSpringMain.java index 2a0c459ea..5b9e3560f 100644 --- a/src/test/java/com/thebeastshop/liteflow/test/TestWithSpringMain.java +++ b/src/test/java/com/thebeastshop/liteflow/test/TestWithSpringMain.java @@ -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(); + } + + } } diff --git a/src/test/java/com/thebeastshop/liteflow/test/component/HComponent.java b/src/test/java/com/thebeastshop/liteflow/test/component/HComponent.java new file mode 100644 index 000000000..f1ab7a653 --- /dev/null +++ b/src/test/java/com/thebeastshop/liteflow/test/component/HComponent.java @@ -0,0 +1,32 @@ +/** + *

Title: liteFlow

+ *

Description: 轻量级的组件式流程框架

+ *

Copyright: Copyright (c) 2017

+ * @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()); + } + +} diff --git a/src/test/java/com/thebeastshop/liteflow/test/component/M1Component.java b/src/test/java/com/thebeastshop/liteflow/test/component/M1Component.java new file mode 100644 index 000000000..9efbb153f --- /dev/null +++ b/src/test/java/com/thebeastshop/liteflow/test/component/M1Component.java @@ -0,0 +1,30 @@ +/** + *

Title: liteFlow

+ *

Description: 轻量级的组件式流程框架

+ *

Copyright: Copyright (c) 2017

+ * @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!"); + } + +} diff --git a/src/test/java/com/thebeastshop/liteflow/test/component/M2Component.java b/src/test/java/com/thebeastshop/liteflow/test/component/M2Component.java new file mode 100644 index 000000000..96a6bf906 --- /dev/null +++ b/src/test/java/com/thebeastshop/liteflow/test/component/M2Component.java @@ -0,0 +1,30 @@ +/** + *

Title: liteFlow

+ *

Description: 轻量级的组件式流程框架

+ *

Copyright: Copyright (c) 2017

+ * @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!"); + } + +} diff --git a/src/test/java/com/thebeastshop/liteflow/test/component/MComponent.java b/src/test/java/com/thebeastshop/liteflow/test/component/MComponent.java new file mode 100644 index 000000000..d9267b908 --- /dev/null +++ b/src/test/java/com/thebeastshop/liteflow/test/component/MComponent.java @@ -0,0 +1,32 @@ +/** + *

Title: liteFlow

+ *

Description: 轻量级的组件式流程框架

+ *

Copyright: Copyright (c) 2017

+ * @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"; + } + +} diff --git a/src/test/resources/config/flow.xml b/src/test/resources/config/flow.xml index 87fe28548..d29fc2d61 100644 --- a/src/test/resources/config/flow.xml +++ b/src/test/resources/config/flow.xml @@ -24,8 +24,10 @@ - - - + + + + + \ No newline at end of file diff --git a/src/test/resources/spring-test.xml b/src/test/resources/spring-test.xml index 8cc2046d7..685098480 100644 --- a/src/test/resources/spring-test.xml +++ b/src/test/resources/spring-test.xml @@ -10,7 +10,7 @@ - + config/flow.xml