future #I9050W 为每一个上下文提供一个名字,使用时可以根据名字来获取

This commit is contained in:
everywhere.z 2024-01-31 13:57:37 +08:00
parent c373fd78cd
commit 69b7fdf991
11 changed files with 167 additions and 23 deletions

View File

@ -280,6 +280,10 @@ public abstract class NodeComponent {
return this.getSlot().getContextBean(contextBeanClazz);
}
public <T> T getContextBean(String contextName) {
return this.getSlot().getContextBean(contextName);
}
public String getNodeId() {
return nodeId;
}

View File

@ -101,6 +101,10 @@ public class LiteflowResponse {
return this.getSlot().getContextBean(contextBeanClazz);
}
public <T> T getContextBean(String contextName) {
return this.getSlot().getContextBean(contextName);
}
public Map<String, List<CmpStep>> getExecuteSteps() {
Map<String, List<CmpStep>> map = new LinkedHashMap<>();
this.getSlot().getExecuteSteps().forEach(cmpStep -> {

View File

@ -54,17 +54,7 @@ public abstract class ScriptExecutor {
// key的规则为自定义上下文的simpleName
// 比如你的自定义上下文为AbcContext那么key就为:abcContext
// 这里不统一放一个map的原因是考虑到有些用户会调用上下文里的方法而不是参数所以脚本语言的绑定表里也是放多个上下文
DataBus.getContextBeanList(wrap.getSlotIndex()).forEach(o -> {
ContextBean contextBean = AnnoUtil.getAnnotation(o.getClass(), ContextBean.class);
String key;
if (contextBean != null && contextBean.value().trim().length() > 0) {
key = contextBean.value();
}
else {
key = StrUtil.lowerFirst(o.getClass().getSimpleName());
}
putConsumer.accept(key, o);
});
DataBus.getContextBeanList(wrap.getSlotIndex()).forEach(tuple -> putConsumer.accept(tuple.get(0), tuple.get(1)));
// 把wrap对象转换成元数据map
Map<String, Object> metaMap = BeanUtil.beanToMap(wrap);

View File

@ -7,10 +7,14 @@
*/
package com.yomahub.liteflow.slot;
import cn.hutool.core.lang.Tuple;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.annotation.util.AnnoUtil;
import com.yomahub.liteflow.context.ContextBean;
import com.yomahub.liteflow.log.LFLog;
import com.yomahub.liteflow.log.LFLoggerManager;
import com.yomahub.liteflow.property.LiteflowConfig;
@ -74,13 +78,22 @@ public class DataBus {
.map((Function<Class<?>, Object>) ReflectUtil::newInstanceIfPossible)
.collect(Collectors.toList());
Slot slot = new Slot(contextBeanList);
return offerIndex(slot);
return offerSlotByBean(contextBeanList);
}
public static int offerSlotByBean(List<Object> contextList) {
Slot slot = new Slot(contextList);
List<Tuple> contextBeanList = contextList.stream().map(object -> {
ContextBean contextBean = AnnoUtil.getAnnotation(object.getClass(), ContextBean.class);
String contextKey;
if (contextBean != null && StrUtil.isNotBlank(contextBean.value())){
contextKey = contextBean.value();
}else{
contextKey = StrUtil.lowerFirst(object.getClass().getSimpleName());
}
return new Tuple(contextKey, object);
}).collect(Collectors.toList());
Slot slot = new Slot(contextBeanList);
return offerIndex(slot);
}
@ -128,7 +141,7 @@ public class DataBus {
return SLOTS.get(slotIndex);
}
public static List<Object> getContextBeanList(int slotIndex) {
public static List<Tuple> getContextBeanList(int slotIndex) {
Slot slot = getSlot(slotIndex);
return slot.getContextBeanList();
}

View File

@ -9,6 +9,7 @@ package com.yomahub.liteflow.slot;
import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Tuple;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.ttl.TransmittableThreadLocal;
@ -30,6 +31,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Predicate;
/**
* Slot的抽象类实现
@ -91,14 +93,14 @@ public class Slot {
protected ConcurrentHashMap<String, Object> metaDataMap = new ConcurrentHashMap<>();
private List<Object> contextBeanList;
private List<Tuple> contextBeanList;
private static final TransmittableThreadLocal<Deque<Condition>> conditionStack = TransmittableThreadLocal.withInitial(ConcurrentLinkedDeque::new);
public Slot() {
}
public Slot(List<Object> contextBeanList) {
public Slot(List<Tuple> contextBeanList) {
this.contextBeanList = contextBeanList;
}
@ -449,21 +451,30 @@ public class Slot {
metaDataMap.remove(SUB_EXCEPTION_PREFIX + chainId);
}
public List<Object> getContextBeanList() {
public List<Tuple> getContextBeanList() {
return this.contextBeanList;
}
public <T> T getContextBean(Class<T> contextBeanClazz) {
T t = (T) contextBeanList.stream().filter(o -> o.getClass().getName().equals(contextBeanClazz.getName())).findFirst().orElse(null);
if (t == null) {
Tuple contextTuple = contextBeanList.stream().filter(tuple -> tuple.get(1).getClass().getName().equals(contextBeanClazz.getName())).findFirst().orElse(null);
if (contextTuple == null) {
contextBeanList.forEach(o -> LOG.info("ChainId[{}], Context class:{},Request class:{}", this.getChainId(), o.getClass().getName(), contextBeanClazz.getName()));
throw new NoSuchContextBeanException("this type is not in the context type passed in");
}
return t;
return contextTuple.get(1);
}
public <T> T getContextBean(String contextBeanKey) {
Tuple contextTuple = contextBeanList.stream().filter(tuple -> tuple.get(0).equals(contextBeanKey)).findFirst().orElse(null);
if (contextTuple == null) {
contextBeanList.forEach(o -> LOG.info("ChainId[{}], Context class:{},Request contextBeanKey:{}", this.getChainId(), o.getClass().getName(), contextBeanKey));
throw new NoSuchContextBeanException("this context key is not defined");
}
return contextTuple.get(1);
}
public <T> T getFirstContextBean() {
Class<T> firstContextBeanClazz = (Class<T>) this.getContextBeanList().get(0).getClass();
Class<T> firstContextBeanClazz = (Class<T>) this.getContextBeanList().get(0).get(1).getClass();
return this.getContextBean(firstContextBeanClazz);
}

View File

@ -0,0 +1,38 @@
package com.yomahub.liteflow.test.contextBean;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.test.BaseTest;
import com.yomahub.liteflow.test.contextBean.context.TestContext;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.TestPropertySource;
import javax.annotation.Resource;
/**
* ContextBean测试
*
* @author Bryan.Zhang
*/
@TestPropertySource(value = "classpath:/contextBean/application.properties")
@SpringBootTest(classes = ContextBeanSpringbootTest.class)
@EnableAutoConfiguration
@ComponentScan({ "com.yomahub.liteflow.test.contextBean.cmp" })
public class ContextBeanSpringbootTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
// 最简单的情况
@Test
public void testContextBean1() throws Exception {
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg", TestContext.class);
Assertions.assertTrue(response.isSuccess());
TestContext context = response.getContextBean("skuContext");
Assertions.assertEquals("J001", context.getSkuCode());
}
}

View File

@ -0,0 +1,23 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.contextBean.cmp;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.test.contextBean.context.TestContext;
import org.springframework.stereotype.Component;
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
TestContext context = this.getContextBean("skuContext");
context.setSkuCode("J001");
System.out.println("ACmp executed!");
}
}

View File

@ -0,0 +1,21 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.contextBean.cmp;
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;
@Component("b")
public class BCmp extends NodeComponent {
@Override
public void process() {
System.out.println("BCmp executed!");
}
}

View File

@ -0,0 +1,32 @@
package com.yomahub.liteflow.test.contextBean.context;
import com.yomahub.liteflow.context.ContextBean;
@ContextBean("skuContext")
public class TestContext {
private String skuCode;
private String skuName;
public TestContext(String skuCode, String skuName) {
this.skuCode = skuCode;
this.skuName = skuName;
}
public String getSkuCode() {
return skuCode;
}
public void setSkuCode(String skuCode) {
this.skuCode = skuCode;
}
public String getSkuName() {
return skuName;
}
public void setSkuName(String skuName) {
this.skuName = skuName;
}
}

View File

@ -0,0 +1 @@
liteflow.rule-source=contextBean/flow.xml

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
<flow>
<chain name="chain1">
THEN(a,b);
</chain>
</flow>