增加了内部策略调用特性

重写了节点步骤打印
This commit is contained in:
bryan.zhang
2017-12-08 17:05:31 +08:00
parent ba8ac461cb
commit 632e543928
17 changed files with 296 additions and 27 deletions

View File

@@ -5,7 +5,7 @@
<artifactId>liteflow</artifactId> <artifactId>liteflow</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<version>1.2.2</version> <version>1.2.3</version>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

View File

@@ -46,7 +46,7 @@ public class FlowExecutor {
try { try {
FlowParser.parseLocal(path); FlowParser.parseLocal(path);
} catch (Exception e) { } 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); throw new FlowExecutorNotInitException(errorMsg);
} }
} }
@@ -57,26 +57,47 @@ public class FlowExecutor {
} }
public <T> T execute(String chainId,Object param){ 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){ 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{ try{
if(FlowBus.needInit()) {
init();
}
Chain chain = FlowBus.getChain(chainId); Chain chain = FlowBus.getChain(chainId);
if(chain == null){ 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); throw new ChainNotFoundException(errorMsg);
} }
slotIndex = DataBus.offerSlot(slotClazz); if(!isInnerChain && slotIndex == null) {
LOG.info("slot[{}] offered",slotIndex); slotIndex = DataBus.offerSlot(slotClazz);
LOG.info("slot[{}] offered",slotIndex);
}
if(slotIndex == -1){ if(slotIndex == -1){
throw new NoAvailableSlotException("there is no available slot"); 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(); List<Condition> conditionList = chain.getConditionList();
@@ -97,7 +118,7 @@ public class FlowExecutor {
break; break;
} }
}else{ }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); throw new ComponentNotAccessException(errorMsg);
} }
}catch(Throwable t){ }catch(Throwable t){
@@ -116,12 +137,17 @@ public class FlowExecutor {
latch.await(15, TimeUnit.SECONDS); latch.await(15, TimeUnit.SECONDS);
} }
} }
DataBus.getSlot(slotIndex).printStep(); if(!isInnerChain) {
return DataBus.getSlot(slotIndex).getResponseData(); slot.printStep();
}
return slot.getResponseData();
}catch(Exception e){ }catch(Exception e){
LOG.error("executor cause error",e);
throw new FlowSystemException("executor cause error"); throw new FlowSystemException("executor cause error");
}finally{ }finally{
DataBus.releaseSlot(slotIndex); if(!isInnerChain) {
DataBus.releaseSlot(slotIndex);
}
} }
} }

View File

@@ -15,6 +15,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.thebeastshop.liteflow.entity.config.Node; 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.DataBus;
import com.thebeastshop.liteflow.entity.data.Slot; import com.thebeastshop.liteflow.entity.data.Slot;
import com.thebeastshop.liteflow.entity.monitor.CompStatistics; import com.thebeastshop.liteflow.entity.monitor.CompStatistics;
@@ -30,6 +32,7 @@ public abstract class NodeComponent {
private String nodeId; private String nodeId;
public void execute() throws Exception{ public void execute() throws Exception{
this.getSlot().addStep(new CmpStep(nodeId, CmpStepType.START));
StopWatch stopWatch = new StopWatch(); StopWatch stopWatch = new StopWatch();
stopWatch.start(); stopWatch.start();
long initm=Runtime.getRuntime().freeMemory(); long initm=Runtime.getRuntime().freeMemory();
@@ -39,7 +42,7 @@ public abstract class NodeComponent {
long timeSpent = stopWatch.getTime(); long timeSpent = stopWatch.getTime();
long endm=Runtime.getRuntime().freeMemory(); long endm=Runtime.getRuntime().freeMemory();
this.getSlot().addStep(nodeId); this.getSlot().addStep(new CmpStep(nodeId, CmpStepType.END));
//性能统计 //性能统计
CompStatistics statistics = new CompStatistics(); CompStatistics statistics = new CompStatistics();
@@ -93,6 +96,10 @@ public abstract class NodeComponent {
return this; return this;
} }
public Integer getSlotIndex() {
return this.slotIndexTL.get();
}
public <T extends Slot> T getSlot(){ public <T extends Slot> T getSlot(){
return DataBus.getSlot(this.slotIndexTL.get()); return DataBus.getSlot(this.slotIndexTL.get());
} }

View File

@@ -9,7 +9,10 @@
*/ */
package com.thebeastshop.liteflow.entity.data; package com.thebeastshop.liteflow.entity.data;
import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Deque;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@@ -31,7 +34,7 @@ public abstract class AbsSlot implements Slot{
private final String NODE_OUTPUT_PREFIX = "output_"; 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>(); 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); return (T)dataMap.get(COND_NODE_PREFIX + key);
} }
public void addStep(String nodeId){ public void addStep(CmpStep step){
this.executeSteps.add(nodeId); CmpStep lastStep = this.executeSteps.peekLast();
if(lastStep != null && lastStep.equals(step)) {
lastStep.setStepType(CmpStepType.SINGLE);
}else {
this.executeSteps.add(step);
}
} }
public void printStep(){ public void printStep(){
StringBuffer str = new StringBuffer(); StringBuffer str = new StringBuffer();
for(int i = 0; i < this.executeSteps.size(); i++){ CmpStep cmpStep = null;
str.append(executeSteps.get(i)); for (Iterator<CmpStep> it = executeSteps.iterator(); it.hasNext();) {
if(i < this.executeSteps.size()-1){ cmpStep = it.next();
str.append(cmpStep);
if(it.hasNext()){
str.append("==>"); str.append("==>");
} }
} }

View File

@@ -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;
}
}
}
}
}

View File

@@ -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;
}

View File

@@ -34,7 +34,7 @@ public interface Slot {
public <T> T getCondResult(String key); public <T> T getCondResult(String key);
public void addStep(String nodeId); public void addStep(CmpStep step);
public void printStep(); public void printStep();
} }

View File

@@ -12,6 +12,8 @@ package com.thebeastshop.liteflow.flow;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.commons.collections4.MapUtils;
import com.thebeastshop.liteflow.entity.config.Chain; import com.thebeastshop.liteflow.entity.config.Chain;
public class FlowBus { public class FlowBus {
@@ -31,4 +33,8 @@ public class FlowBus {
} }
chainMap.put(name, chain); chainMap.put(name, chain);
} }
public static boolean needInit() {
return MapUtils.isEmpty(chainMap);
}
} }

View File

@@ -31,6 +31,7 @@ public class ComponentScaner implements BeanPostProcessor, PriorityOrdered {
return Ordered.LOWEST_PRECEDENCE; return Ordered.LOWEST_PRECEDENCE;
} }
@SuppressWarnings("rawtypes")
@Override @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Class clazz = bean.getClass(); Class clazz = bean.getClass();

View File

@@ -17,7 +17,7 @@ import com.thebeastshop.liteflow.parser.FlowParser;
public class TestMain { public class TestMain {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
final FlowExecutor executor = new FlowExecutor(); final FlowExecutor executor = new FlowExecutor();
executor.setRulePath(Arrays.asList(new String[]{"flow.xml"})); executor.setRulePath(Arrays.asList(new String[]{"config/flow.xml"}));
executor.init(); executor.init();
for(int i=0;i<1;i++){ for(int i=0;i<1;i++){

View File

@@ -25,11 +25,11 @@ public class TestWithSpringMain {
public void test1() throws Exception { public void test1() throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(10); ExecutorService executorService = Executors.newFixedThreadPool(10);
for(int i=0;i<1;i++){ for(int i=0;i<10;i++){
executorService.submit(new Thread(){ executorService.submit(new Thread(){
@Override @Override
public void run() { 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); System.out.println(response);
} }
}); });
@@ -37,4 +37,16 @@ public class TestWithSpringMain {
System.out.println("done!"); System.out.println("done!");
System.in.read(); 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();
}
}
} }

View File

@@ -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());
}
}

View File

@@ -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!");
}
}

View File

@@ -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!");
}
}

View File

@@ -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";
}
}

View File

@@ -24,8 +24,10 @@
</chain> </chain>
<chain name="chain3"> <chain name="chain3">
<then value="a,c,g"/> <then value="a,c,h,g"/>
<when value="b,e"/> </chain>
<then value="d,f"/>
<chain name="strategy">
<then value="m(m1|m2)"/>
</chain> </chain>
</flow> </flow>

View File

@@ -10,7 +10,7 @@
<context:component-scan base-package="com.thebeastshop.liteflow.test.component" /> <context:component-scan base-package="com.thebeastshop.liteflow.test.component" />
<bean class="com.thebeastshop.liteflow.spring.ComponentScaner"/> <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"> <property name="rulePath">
<list> <list>
<value>config/flow.xml</value> <value>config/flow.xml</value>