mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-14 12:12:08 +08:00
feature #IBW9PC 上下文表达式搜索&设置,摆脱对上下文的依赖
This commit is contained in:
@@ -476,14 +476,23 @@ public abstract class NodeComponent{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> List<T> getBindDataList(Class<T> clazz) {
|
public <T> List<T> getBindDataList(String key, Class<T> clazz) {
|
||||||
String bindData = getRefNode().getCmpData();
|
String bindData = getRefNode().getBindData(key);
|
||||||
if (StrUtil.isBlank(bindData)) {
|
if (StrUtil.isBlank(bindData)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return JsonUtil.parseList(bindData, clazz);
|
return JsonUtil.parseList(bindData, clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T getContextValue(String expression){
|
||||||
|
return (T)LiteflowContextRegexMatcher.searchContext(this.getSlot().getContextBeanList(), expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContextValue(String methodExpress, Object... values){
|
||||||
|
LiteflowContextRegexMatcher.searchAndSetContext(this.getSlot().getContextBeanList(), methodExpress, values);
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getLoopIndex() {
|
public Integer getLoopIndex() {
|
||||||
return this.getRefNode().getLoopIndex();
|
return this.getRefNode().getLoopIndex();
|
||||||
}
|
}
|
||||||
@@ -539,9 +548,4 @@ public abstract class NodeComponent{
|
|||||||
return originalClass.getName();
|
return originalClass.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
|
|
||||||
boolean flag = ReUtil.isMatch(ChainConstant.CONTEXT_SEARCH_REGEX, "${user.name}");
|
|
||||||
System.out.println(ReUtil.getGroup1(ChainConstant.CONTEXT_SEARCH_REGEX, "${user.name}"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,22 @@
|
|||||||
package com.yomahub.liteflow.util;
|
package com.yomahub.liteflow.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.lang.Tuple;
|
import cn.hutool.core.lang.Tuple;
|
||||||
|
import cn.hutool.core.util.BooleanUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.ql.util.express.DefaultContext;
|
import com.ql.util.express.DefaultContext;
|
||||||
import com.ql.util.express.ExpressRunner;
|
import com.ql.util.express.ExpressRunner;
|
||||||
import com.ql.util.express.InstructionSet;
|
import com.ql.util.express.InstructionSet;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LiteFlow上下文正则表达式匹配器
|
* LiteFlow上下文正则表达式匹配器
|
||||||
@@ -54,4 +62,47 @@ public class LiteflowContextRegexMatcher {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void searchAndSetContext(List<Tuple> contextList, String methodExpress, Object... args){
|
||||||
|
// 把上下文数据转换成map形式的,key为别名,value为上下文
|
||||||
|
Map<String, Object> contextMap = contextList.stream().collect(
|
||||||
|
Collectors.toMap(tuple -> tuple.get(0), tuple -> tuple.get(1))
|
||||||
|
);
|
||||||
|
|
||||||
|
List<String> errorList = new ArrayList<>();
|
||||||
|
|
||||||
|
boolean flag = false;
|
||||||
|
|
||||||
|
String argStr = IntStream.range(0, args.length).mapToObj(
|
||||||
|
idx -> StrUtil.format("arg{}", idx)
|
||||||
|
).collect(Collectors.joining(","));
|
||||||
|
|
||||||
|
List<TupleOf2<String, Integer>> tupleList = IntStream.range(0, args.length).mapToObj(
|
||||||
|
idx -> new TupleOf2<>(StrUtil.format("arg{}", idx), idx)
|
||||||
|
).collect(Collectors.toList());
|
||||||
|
|
||||||
|
for(Map.Entry<String, Object> entry : contextMap.entrySet()){
|
||||||
|
try{
|
||||||
|
InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache(StrUtil.format("{}.{}({})", entry.getKey(), methodExpress, argStr));
|
||||||
|
DefaultContext<String, Object> context = new DefaultContext<>();
|
||||||
|
context.put(entry.getKey(), entry.getValue());
|
||||||
|
tupleList.forEach(tuple -> context.put(tuple.getA(), args[tuple.getB()]));
|
||||||
|
expressRunner.execute(instructionSet, context, errorList, false, false);
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
}catch (Exception ignore){}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据表达式去上下文里搜索相匹配的数据
|
||||||
|
if (BooleanUtil.isFalse(flag)){
|
||||||
|
try{
|
||||||
|
// 如果没有搜到,那么尝试推断表达式是指定的上下文,按照指定上下文的方式去再获取
|
||||||
|
InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache(StrUtil.format("contextMap.{}({})", methodExpress, argStr));
|
||||||
|
DefaultContext<String, Object> context = new DefaultContext<>();
|
||||||
|
context.put("contextMap", contextMap);
|
||||||
|
tupleList.forEach(tuple -> context.put(tuple.getA(), args[tuple.getB()]));
|
||||||
|
expressRunner.execute(instructionSet, context, errorList, false, false);
|
||||||
|
}catch (Exception ignore){}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package com.yomahub.liteflow.test.searchContext;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.FlowExecutor;
|
||||||
|
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||||
|
import com.yomahub.liteflow.slot.DefaultContext;
|
||||||
|
import com.yomahub.liteflow.test.BaseTest;
|
||||||
|
import com.yomahub.liteflow.test.searchContext.context.Member;
|
||||||
|
import com.yomahub.liteflow.test.searchContext.context.MemberContext;
|
||||||
|
import com.yomahub.liteflow.test.searchContext.context.OrderContext;
|
||||||
|
import com.yomahub.liteflow.test.searchContext.context.UserInfoContext;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* springboot环境EL常规的例子测试
|
||||||
|
*
|
||||||
|
* @author Bryan.Zhang
|
||||||
|
*/
|
||||||
|
@TestPropertySource(value = "classpath:/searchContext/application.properties")
|
||||||
|
@SpringBootTest(classes = SearchContextSpringbootTest.class)
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
@ComponentScan({"com.yomahub.liteflow.test.searchContext.cmp"})
|
||||||
|
public class SearchContextSpringbootTest extends BaseTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FlowExecutor flowExecutor;
|
||||||
|
|
||||||
|
// 测试动态取,动态设置的基础情况
|
||||||
|
@Test
|
||||||
|
public void testSearchContext1() throws Exception {
|
||||||
|
MemberContext memberContext = new MemberContext();
|
||||||
|
memberContext.setId(31);
|
||||||
|
memberContext.setName("jack");
|
||||||
|
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg", memberContext, new DefaultContext());
|
||||||
|
Assertions.assertTrue(response.isSuccess());
|
||||||
|
MemberContext context = response.getContextBean(MemberContext.class);
|
||||||
|
Assertions.assertEquals("hello,jack", context.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试动态取,2个上下文智能设置,1个参数
|
||||||
|
@Test
|
||||||
|
public void testSearchContext2() throws Exception {
|
||||||
|
MemberContext memberContext = new MemberContext();
|
||||||
|
memberContext.setId(31);
|
||||||
|
memberContext.setName("jack");
|
||||||
|
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg", memberContext, new DefaultContext());
|
||||||
|
Assertions.assertTrue(response.isSuccess());
|
||||||
|
MemberContext context = response.getContextBean(MemberContext.class);
|
||||||
|
Assertions.assertEquals("hello,jack", context.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 多级动态取,2个上下文智能设置,多个参数
|
||||||
|
@Test
|
||||||
|
public void testSearchContext3() throws Exception {
|
||||||
|
OrderContext orderContext = new OrderContext();
|
||||||
|
orderContext.setOrderCode("SO1234");
|
||||||
|
orderContext.setMember(new Member("M0001","jack"));
|
||||||
|
LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg", orderContext, new DefaultContext());
|
||||||
|
Assertions.assertTrue(response.isSuccess());
|
||||||
|
DefaultContext context = response.getContextBean(DefaultContext.class);
|
||||||
|
Assertions.assertEquals("M0001", context.getData("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3个上下文指定上下文取和设置
|
||||||
|
@Test
|
||||||
|
public void testSearchContext4() throws Exception {
|
||||||
|
MemberContext memberContext = new MemberContext();
|
||||||
|
memberContext.setId(2000);
|
||||||
|
memberContext.setName("jack");
|
||||||
|
|
||||||
|
OrderContext orderContext = new OrderContext();
|
||||||
|
orderContext.setId(3000);
|
||||||
|
orderContext.setOrderCode("SO1234");
|
||||||
|
orderContext.setMember(new Member("M0001","jack"));
|
||||||
|
|
||||||
|
LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg", memberContext, orderContext, new DefaultContext());
|
||||||
|
Assertions.assertTrue(response.isSuccess());
|
||||||
|
DefaultContext context = response.getContextBean(DefaultContext.class);
|
||||||
|
Assertions.assertEquals(3000, (Integer) context.getData("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 多个上下文,结合@ContextBean测试
|
||||||
|
@Test
|
||||||
|
public void testSearchContext5() throws Exception {
|
||||||
|
UserInfoContext userInfoContext = new UserInfoContext();
|
||||||
|
userInfoContext.setInfo("test info");
|
||||||
|
|
||||||
|
LiteflowResponse response = flowExecutor.execute2Resp("chain5", "arg", userInfoContext, new DefaultContext());
|
||||||
|
Assertions.assertTrue(response.isSuccess());
|
||||||
|
DefaultContext context = response.getContextBean(DefaultContext.class);
|
||||||
|
Assertions.assertEquals("test info", context.getData("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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.searchContext.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeComponent;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component("a1")
|
||||||
|
public class A1Cmp extends NodeComponent {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process() {
|
||||||
|
String name = this.getContextValue("name");
|
||||||
|
|
||||||
|
this.setContextValue("setName", "hello," + name);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.searchContext.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeComponent;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component("a2")
|
||||||
|
public class A2Cmp extends NodeComponent {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process() {
|
||||||
|
String name = this.getContextValue("name");
|
||||||
|
|
||||||
|
this.setContextValue("memberContext.setName", "hello," + name);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* <p>Title: liteflow</p>
|
||||||
|
* <p>Description: 轻量级的组件式流程框架</p>
|
||||||
|
* @author Bryan.Zhang
|
||||||
|
* @email weenyc31@163.com
|
||||||
|
* @Date 2020/4/1
|
||||||
|
*/
|
||||||
|
package com.yomahub.liteflow.test.searchContext.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeComponent;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component("a3")
|
||||||
|
public class A3Cmp extends NodeComponent {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process() {
|
||||||
|
String name = this.getContextValue("member.memberCode");
|
||||||
|
this.setContextValue("setData", "test", name);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* <p>Title: liteflow</p>
|
||||||
|
* <p>Description: 轻量级的组件式流程框架</p>
|
||||||
|
* @author Bryan.Zhang
|
||||||
|
* @email weenyc31@163.com
|
||||||
|
* @Date 2020/4/1
|
||||||
|
*/
|
||||||
|
package com.yomahub.liteflow.test.searchContext.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeComponent;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component("a4")
|
||||||
|
public class A4Cmp extends NodeComponent {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process() {
|
||||||
|
Integer id = this.getContextValue("orderContext.id");
|
||||||
|
this.setContextValue("setData", "test", id);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* <p>Title: liteflow</p>
|
||||||
|
* <p>Description: 轻量级的组件式流程框架</p>
|
||||||
|
* @author Bryan.Zhang
|
||||||
|
* @email weenyc31@163.com
|
||||||
|
* @Date 2020/4/1
|
||||||
|
*/
|
||||||
|
package com.yomahub.liteflow.test.searchContext.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeComponent;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component("a5")
|
||||||
|
public class A5Cmp extends NodeComponent {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process() {
|
||||||
|
String str = this.getContextValue("userCx.info");
|
||||||
|
this.setContextValue("setData", "test", str);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.yomahub.liteflow.test.searchContext.context;
|
||||||
|
|
||||||
|
public class Member {
|
||||||
|
private String memberCode;
|
||||||
|
|
||||||
|
private String memberName;
|
||||||
|
|
||||||
|
public Member(String memberCode, String memberName) {
|
||||||
|
this.memberCode = memberCode;
|
||||||
|
this.memberName = memberName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMemberCode() {
|
||||||
|
return memberCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberCode(String memberCode) {
|
||||||
|
this.memberCode = memberCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMemberName() {
|
||||||
|
return memberName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberName(String memberName) {
|
||||||
|
this.memberName = memberName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.yomahub.liteflow.test.searchContext.context;
|
||||||
|
|
||||||
|
public class MemberContext {
|
||||||
|
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.yomahub.liteflow.test.searchContext.context;
|
||||||
|
|
||||||
|
public class OrderContext {
|
||||||
|
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private String orderCode;
|
||||||
|
|
||||||
|
private Member member;
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOrderCode() {
|
||||||
|
return orderCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderCode(String orderCode) {
|
||||||
|
this.orderCode = orderCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Member getMember() {
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMember(Member member) {
|
||||||
|
this.member = member;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.yomahub.liteflow.test.searchContext.context;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.context.ContextBean;
|
||||||
|
|
||||||
|
@ContextBean("userCx")
|
||||||
|
public class UserInfoContext {
|
||||||
|
|
||||||
|
private String info;
|
||||||
|
|
||||||
|
public String getInfo() {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInfo(String info) {
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
liteflow.rule-source=searchContext/flow.xml
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
|
||||||
|
<flow>
|
||||||
|
<chain name="chain1">
|
||||||
|
THEN(a1);
|
||||||
|
</chain>
|
||||||
|
|
||||||
|
<chain name="chain2">
|
||||||
|
THEN(a2);
|
||||||
|
</chain>
|
||||||
|
|
||||||
|
<chain name="chain3">
|
||||||
|
THEN(a3);
|
||||||
|
</chain>
|
||||||
|
|
||||||
|
<chain name="chain4">
|
||||||
|
THEN(a4);
|
||||||
|
</chain>
|
||||||
|
|
||||||
|
<chain name="chain5">
|
||||||
|
THEN(a5);
|
||||||
|
</chain>
|
||||||
|
</flow>
|
||||||
Reference in New Issue
Block a user