feat #I64L3Q 增加 @ScriptMethod 注解

This commit is contained in:
gaibu 2022-12-10 18:11:04 +08:00
parent 2adda1fdf2
commit b863908d78
35 changed files with 848 additions and 6 deletions

View File

@ -0,0 +1,25 @@
package com.yomahub.liteflow.script.annotation;
import com.yomahub.liteflow.annotation.AliasFor;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 用于标注在Script中可使用的java bean
* @author Bryan.Zhang
* @since 2.9.0
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface ScriptMethod {
@AliasFor("name")
String value() default "";
}

View File

@ -0,0 +1,98 @@
package com.yomahub.liteflow.script.proxy;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.exception.LiteFlowException;
import com.yomahub.liteflow.exception.ScriptBeanMethodInvokeException;
import com.yomahub.liteflow.util.LiteFlowProxyUtil;
import com.yomahub.liteflow.util.SerialsUtil;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.InvocationHandlerAdapter;
import net.bytebuddy.matcher.ElementMatchers;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
/**
* 脚本方法代理
*/
public class ScriptMethodProxy {
/**
* 被代理的 bean
*/
private final Object bean;
/**
* 原始的类
*/
private final Class<?> orignalClass;
private final List<Method> scriptMethods;
public ScriptMethodProxy(Object bean, Class<?> orignalClass, List<Method> scriptMethods) {
this.bean = bean;
this.orignalClass = orignalClass;
this.scriptMethods = scriptMethods;
}
public Object getProxyScriptMethod() {
try {
return new ByteBuddy().subclass(orignalClass)
.name(buildClassName()) // 设置生成的类名
.method(ElementMatchers.any())
.intercept(InvocationHandlerAdapter.of(new AopInvocationHandler(bean, scriptMethods)))
.annotateType(orignalClass.getAnnotations())
.make()
.load(ScriptBeanProxy.class.getClassLoader())
.getLoaded()
.newInstance();
} catch (Exception e) {
throw new LiteFlowException(e);
}
}
private String buildClassName() {
return StrUtil.format("{}.ByteBuddy${}",
ClassUtil.getPackage(orignalClass),
SerialsUtil.generateShortUUID());
}
public static class AopInvocationHandler implements InvocationHandler {
private final Object bean;
private final Class<?> clazz;
private final Set<Method> methodSet;
public AopInvocationHandler(Object bean, List<Method> methods) {
this.bean = bean;
this.clazz = LiteFlowProxyUtil.getUserClass(bean.getClass());
this.methodSet = new HashSet<>(methods);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Optional<Method> invokeMethodOp = Arrays.stream(clazz.getMethods())
.filter(method::equals)
.findFirst();
if (!invokeMethodOp.isPresent()) {
String errorMsg = StrUtil.format("cannot find method[{}]", clazz.getName(), method.getName());
throw new ScriptBeanMethodInvokeException(errorMsg);
}
if (!methodSet.contains(method)) {
String errorMsg = StrUtil.format("script method[{}.{}] cannot be executed", clazz.getName(), method.getName());
throw new ScriptBeanMethodInvokeException(errorMsg);
}
return invokeMethodOp.get().invoke(bean, args);
}
}
}

View File

@ -8,15 +8,19 @@
*/
package com.yomahub.liteflow.spring;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.annotation.util.AnnoUtil;
import com.yomahub.liteflow.aop.ICmpAroundAspect;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.script.annotation.ScriptBean;
import com.yomahub.liteflow.script.ScriptBeanManager;
import com.yomahub.liteflow.script.annotation.ScriptBean;
import com.yomahub.liteflow.script.annotation.ScriptMethod;
import com.yomahub.liteflow.script.proxy.ScriptBeanProxy;
import com.yomahub.liteflow.script.proxy.ScriptMethodProxy;
import com.yomahub.liteflow.util.LOGOPrinter;
import com.yomahub.liteflow.util.LiteFlowProxyUtil;
import org.slf4j.Logger;
@ -24,12 +28,16 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 组件扫描类只要是NodeComponent的实现类都可以被这个扫描器扫到
*
* @author Bryan.Zhang
*/
public class ComponentScanner implements BeanPostProcessor {
@ -48,7 +56,7 @@ public class ComponentScanner implements BeanPostProcessor {
public ComponentScanner(LiteflowConfig liteflowConfig) {
this.liteflowConfig = liteflowConfig;
if(liteflowConfig.getPrintBanner()){
if (liteflowConfig.getPrintBanner()) {
// 打印liteflow的LOGO
LOGOPrinter.print();
}
@ -66,7 +74,7 @@ public class ComponentScanner implements BeanPostProcessor {
//判断是不是声明式组件
//如果是就缓存到类属性的map中
if (LiteFlowProxyUtil.isDeclareCmp(bean.getClass())){
if (LiteFlowProxyUtil.isDeclareCmp(bean.getClass())) {
LOG.info("proxy component[{}] has been found", beanName);
List<NodeComponent> nodeComponents = LiteFlowProxyUtil.proxy2NodeComponent(bean, beanName);
nodeComponents.forEach(
@ -77,7 +85,7 @@ public class ComponentScanner implements BeanPostProcessor {
}
);
// 只有注解支持单bean多Node,所以一个直接返回
if (nodeComponents.size() == 1){
if (nodeComponents.size() == 1) {
return nodeComponents.get(0);
}
return bean;
@ -98,11 +106,38 @@ public class ComponentScanner implements BeanPostProcessor {
return cmpAroundAspect;
}
//扫描@ScriptBean修饰的类
// 扫描@ScriptBean修饰的类
ScriptBean scriptBean = AnnoUtil.getAnnotation(clazz, ScriptBean.class);
if (ObjectUtil.isNotNull(scriptBean)){
if (ObjectUtil.isNotNull(scriptBean)) {
ScriptBeanProxy proxy = new ScriptBeanProxy(bean, clazz, scriptBean);
ScriptBeanManager.addScriptBean(scriptBean.value(), proxy.getProxyScriptBean());
return bean;
}
// 扫描@ScriptMethod修饰的类
List<Method> scriptMethods = Arrays.stream(clazz.getMethods())
.filter(method -> {
ScriptMethod scriptMethod = AnnoUtil.getAnnotation(method, ScriptMethod.class);
return ObjectUtil.isNotNull(scriptMethod) && StrUtil.isNotEmpty(scriptMethod.value());
})
.collect(Collectors.toList());
if (CollUtil.isNotEmpty(scriptMethods)) {
Map<String, List<Method>> scriptMethodsGroupByValue = CollStreamUtil.groupBy(scriptMethods, method -> {
ScriptMethod scriptMethod = AnnoUtil.getAnnotation(method, ScriptMethod.class);
return scriptMethod.value();
}, Collectors.toList());
for (Map.Entry<String, List<Method>> entry : scriptMethodsGroupByValue.entrySet()) {
String key = entry.getKey();
List<Method> methods = entry.getValue();
ScriptMethodProxy proxy = new ScriptMethodProxy(bean, clazz, methods);
ScriptBeanManager.addScriptBean(key, proxy.getProxyScriptMethod());
}
return bean;
}
return bean;

View File

@ -0,0 +1,44 @@
package com.yomahub.liteflow.test.script.graaljs.scriptmethod;
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 org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
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 org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@TestPropertySource(value = "classpath:/scriptmethod/application.properties")
@SpringBootTest(classes = LiteFlowScriptScripMethodJsELTest.class)
@EnableAutoConfiguration
@ComponentScan({"com.yomahub.liteflow.test.script.graaljs.scriptmethod.cmp", "com.yomahub.liteflow.test.script.graaljs.scriptmethod.bean"})
public class LiteFlowScriptScripMethodJsELTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
@Test
public void testScriptBean1() throws Exception{
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
Assert.assertEquals("hello", context.getData("demo"));
}
@Test
public void testScriptBean2() throws Exception{
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
Assert.assertEquals("hello,kobekobe", context.getData("demo"));
}
}

View File

@ -0,0 +1,29 @@
package com.yomahub.liteflow.test.script.graaljs.scriptmethod.bean;
import com.yomahub.liteflow.script.annotation.ScriptMethod;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class DemoBean1 {
@Resource
private DemoBean2 demoBean2;
@ScriptMethod("demo1")
public String getDemoStr1() {
return "hello";
}
@ScriptMethod("demo")
public String getDemoStr2(String name) {
return demoBean2.getDemoStr2(name);
}
@ScriptMethod("demo")
public String getDemoStr2(String name1, String name2) {
return demoBean2.getDemoStr2(name1 + name2);
}
}

View File

@ -0,0 +1,11 @@
package com.yomahub.liteflow.test.script.graaljs.scriptmethod.bean;
import org.springframework.stereotype.Component;
@Component
public class DemoBean2 {
public String getDemoStr2(String name){
return "hello,"+name;
}
}

View File

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

View File

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

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<nodes>
<node id="d" type="script" language="js">
<![CDATA[
var str = demo1.getDemoStr1();
defaultContext.setData("demo", str);
]]>
</node>
<node id="e" type="script" language="js">
<![CDATA[
var str = demo.getDemoStr2("kobe","kobe");
defaultContext.setData("demo", str);
]]>
</node>
</nodes>
<chain name="chain1">
THEN(a,b,c,d);
</chain>
<chain name="chain2">
THEN(a,b,c,e);
</chain>
</flow>

View File

@ -0,0 +1,43 @@
package com.yomahub.liteflow.test.script.groovy.scriptmethod;
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 org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
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 org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@TestPropertySource(value = "classpath:/scriptmethod/application.properties")
@SpringBootTest(classes = LiteFlowScriptScriptMethodGroovyELTest.class)
@EnableAutoConfiguration
@ComponentScan({"com.yomahub.liteflow.test.script.groovy.scriptmethod.cmp","com.yomahub.liteflow.test.script.groovy.scriptmethod.bean"})
public class LiteFlowScriptScriptMethodGroovyELTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
@Test
public void testScriptBean1() throws Exception{
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
Assert.assertEquals("hello", context.getData("demo"));
}
@Test
public void testScriptBean2() throws Exception{
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
Assert.assertEquals("hello,kobe", context.getData("demo"));
}
}

View File

@ -0,0 +1,25 @@
package com.yomahub.liteflow.test.script.groovy.scriptmethod.bean;
import com.yomahub.liteflow.script.annotation.ScriptMethod;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class DemoBean1 {
@Resource
private DemoBean2 demoBean2;
@ScriptMethod("demo")
public String getDemoStr1() {
return "hello";
}
@ScriptMethod("demo2")
public String getDemoStr2(String name) {
return demoBean2.getDemoStr2(name);
}
}

View File

@ -0,0 +1,11 @@
package com.yomahub.liteflow.test.script.groovy.scriptmethod.bean;
import org.springframework.stereotype.Component;
@Component
public class DemoBean2 {
public String getDemoStr2(String name){
return "hello,"+name;
}
}

View File

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

View File

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

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<nodes>
<node id="d" type="script" language="groovy">
<![CDATA[
def str = demo.getDemoStr1()
defaultContext.setData("demo", str)
]]>
</node>
<node id="e" type="script" language="groovy">
<![CDATA[
def str = demo2.getDemoStr2("kobe")
defaultContext.setData("demo", str)
]]>
</node>
</nodes>
<chain name="chain1">
THEN(a,b,c,d);
</chain>
<chain name="chain2">
THEN(a,b,c,e);
</chain>
</flow>

View File

@ -0,0 +1,44 @@
package com.yomahub.liteflow.test.script.javascript.scriptmethod;
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 org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
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 org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@TestPropertySource(value = "classpath:/scriptmethod/application.properties")
@SpringBootTest(classes = LiteFlowScriptScriptMethodJsELTest.class)
@EnableAutoConfiguration
@ComponentScan({"com.yomahub.liteflow.test.script.javascript.scriptmethod.cmp","com.yomahub.liteflow.test.script.javascript.scriptmethod.bean"})
public class LiteFlowScriptScriptMethodJsELTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
@Test
public void testScriptBean1() throws Exception{
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
Assert.assertEquals("hello", context.getData("demo"));
}
@Test
public void testScriptBean2() throws Exception{
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
Assert.assertEquals("hello,kobe", context.getData("demo"));
}
}

View File

@ -0,0 +1,28 @@
package com.yomahub.liteflow.test.script.javascript.scriptmethod.bean;
import com.yomahub.liteflow.script.annotation.ScriptMethod;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class DemoBean1 {
@Resource
private DemoBean2 demoBean2;
@ScriptMethod("demo")
public String getDemoStr1() {
return "hello";
}
@ScriptMethod("demo2")
public String getDemoStr2(String name) {
return demoBean2.getDemoStr2(name);
}
@ScriptMethod("demo3")
public String getDemoStr3(String name, String name2) {
return demoBean2.getDemoStr2(name) + name2;
}
}

View File

@ -0,0 +1,11 @@
package com.yomahub.liteflow.test.script.javascript.scriptmethod.bean;
import org.springframework.stereotype.Component;
@Component
public class DemoBean2 {
public String getDemoStr2(String name){
return "hello,"+name;
}
}

View File

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

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<nodes>
<node id="d" type="script" language="js">
<![CDATA[
var str = demo.getDemoStr1();
defaultContext.setData("demo", str);
]]>
</node>
<node id="e" type="script" language="js">
<![CDATA[
var str = demo2.getDemoStr2("kobe");
defaultContext.setData("demo", str);
]]>
</node>
</nodes>
<chain name="chain1">
THEN(a,b,c,d);
</chain>
<chain name="chain2">
THEN(a,b,c,e);
</chain>
</flow>

View File

@ -0,0 +1,44 @@
package com.yomahub.liteflow.test.script.qlexpress.scriptmethod;
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 org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
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 org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@TestPropertySource(value = "classpath:/scriptmethod/application.properties")
@SpringBootTest(classes = LiteFlowScriptScriptMethodQLExpressELTest.class)
@EnableAutoConfiguration
@ComponentScan({"com.yomahub.liteflow.test.script.qlexpress.scriptmethod.cmp","com.yomahub.liteflow.test.script.qlexpress.scriptmethod.bean"})
public class LiteFlowScriptScriptMethodQLExpressELTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
@Test
public void testScriptBean1() throws Exception{
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
Assert.assertEquals("hello", context.getData("demo"));
}
@Test
public void testScriptBean2() throws Exception{
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
Assert.assertEquals("hello,kobe", context.getData("demo"));
}
}

View File

@ -0,0 +1,23 @@
package com.yomahub.liteflow.test.script.qlexpress.scriptmethod.bean;
import com.yomahub.liteflow.script.annotation.ScriptMethod;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class DemoBean1 {
@Resource
private DemoBean2 demoBean2;
@ScriptMethod("demo")
public String getDemoStr1(){
return "hello";
}
@ScriptMethod("demo2")
public String getDemoStr2(String name){
return demoBean2.getDemoStr2(name);
}
}

View File

@ -0,0 +1,11 @@
package com.yomahub.liteflow.test.script.qlexpress.scriptmethod.bean;
import org.springframework.stereotype.Component;
@Component
public class DemoBean2 {
public String getDemoStr2(String name){
return "hello,"+name;
}
}

View File

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

View File

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

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<nodes>
<node id="d" type="script">
<![CDATA[
str = demo.getDemoStr1();
defaultContext.setData("demo", str);
]]>
</node>
<node id="e" type="script">
<![CDATA[
str = demo2.getDemoStr2("kobe");
defaultContext.setData("demo", str);
]]>
</node>
</nodes>
<chain name="chain1">
THEN(a,b,c,d)
</chain>
<chain name="chain2">
THEN(a,b,c,e)
</chain>
</flow>