增加了内部策略调用特性

重写了节点步骤打印
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>
<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>

View File

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

View File

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

View File

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

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 void addStep(String nodeId);
public void addStep(CmpStep step);
public void printStep();
}

View File

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

View File

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

View File

@@ -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++){

View File

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

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 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>

View File

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