增强循环

This commit is contained in:
mxd 2020-04-09 17:03:02 +08:00
parent 375f74dbfc
commit 374f60b07a
4 changed files with 99 additions and 36 deletions

View File

@ -3,6 +3,7 @@ package org.spiderflow.model;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import com.alibaba.fastjson.JSONArray;
@ -85,6 +86,11 @@ public class SpiderNode {
return value;
}
public String getStringJsonValue(String key,String defaultValue){
String value = getStringJsonValue(key);
return StringUtils.isNotBlank(value) ? value : defaultValue;
}
public List<Map<String,String>> getListJsonValue(String ... keys){
List<JSONArray> arrays = new ArrayList<>();
int size = -1;

View File

@ -9,6 +9,7 @@ import org.spiderflow.concurrent.*;
import org.spiderflow.concurrent.SpiderFlowThreadPoolExecutor.SubThreadPoolExecutor;
import org.spiderflow.context.SpiderContext;
import org.spiderflow.context.SpiderContextHolder;
import org.spiderflow.core.executor.shape.LoopExecutor;
import org.spiderflow.core.model.SpiderFlow;
import org.spiderflow.core.service.FlowNoticeService;
import org.spiderflow.core.utils.ExecutorsUtils;
@ -24,6 +25,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@ -162,7 +164,9 @@ public class Spider {
}
//睡眠1ms,让出cpu
Thread.sleep(1);
} catch (InterruptedException | ExecutionException ignored) {
} catch (InterruptedException ignored) {
} catch (Throwable t){
logger.error("程序发生异常",t);
}
}
//等待线程池结束
@ -211,15 +215,37 @@ public class Spider {
logger.error("执行失败,找不到对应的执行器:{}", shape);
context.setRunning(false);
}
//循环次数默认为1,如果节点有循环属性且填了循环次数,则取出循环次数
int loopCount = 1;
int loopCount = 1; //循环次数默认为1,如果节点有循环属性且填了循环次数/集合,则取出循环次数
int loopStart = 0; //循环起始位置
int loopEnd = 1; //循环结束位置
String loopCountStr = node.getStringJsonValue(ShapeExecutor.LOOP_COUNT);
if (StringUtils.isNotBlank(loopCountStr)) {
Object loopArray = null;
boolean isLoop = false;
if (isLoop = StringUtils.isNotBlank(loopCountStr)) {
try {
Object result = ExpressionUtils.execute(loopCountStr, variables);
result = result == null ? 0 : result;
logger.info("获取循环次数{}={}", loopCountStr, result);
loopCount = Integer.parseInt(result.toString());
loopArray = ExpressionUtils.execute(loopCountStr, variables);
if(loopArray == null){
loopCount = 0;
}else if(loopArray instanceof Collection){
loopCount = ((Collection)loopArray).size();
loopArray = ((Collection)loopArray).toArray();
}else if(loopArray.getClass().isArray()){
loopCount = Array.getLength(loopArray);
}else{
loopCount = NumberUtils.toInt(loopArray.toString(),0);
loopArray = null;
}
loopEnd = loopCount;
if(loopCount > 0){
loopStart = Math.max(NumberUtils.toInt(node.getStringJsonValue(LoopExecutor.LOOP_START), 0),0);
int end = NumberUtils.toInt(node.getStringJsonValue(LoopExecutor.LOOP_END), -1);
if(end >=0){
loopEnd = Math.min(end,loopEnd);
}else{
loopEnd = Math.max(loopEnd + end + 1,0);
}
}
logger.info("获取循环次数{}={}", loopCountStr, loopCount);
} catch (Throwable t) {
loopCount = 0;
logger.error("获取循环次数失败,异常信息:{}", t);
@ -228,8 +254,9 @@ public class Spider {
if (loopCount > 0) {
//获取循环下标的变量名称
String loopVariableName = node.getStringJsonValue(ShapeExecutor.LOOP_VARIABLE_NAME);
String loopItem = node.getStringJsonValue(LoopExecutor.LOOP_ITEM,"item");
List<SpiderTask> tasks = new ArrayList<>();
for (int i = 0; i < loopCount; i++) {
for (int i = loopStart; i < loopEnd; i++) {
node.increment(); //节点执行次数+1(后续Join节点使用)
if (context.isRunning()) {
Map<String, Object> nVariables = new HashMap<>();
@ -237,10 +264,14 @@ public class Spider {
if(fromNode == null || node.isTransmitVariable(fromNode.getNodeId())){
nVariables.putAll(variables);
}
if(isLoop){
// 存入下标变量
if (!StringUtils.isBlank(loopVariableName)) {
nVariables.put(loopVariableName, i);
}
// 存入item
nVariables.put(loopItem,loopArray == null ? i : Array.get(loopArray, i));
}
tasks.add(new SpiderTask(TtlRunnable.get(() -> {
if (context.isRunning()) {
try {

View File

@ -15,9 +15,11 @@ import org.springframework.stereotype.Component;
@Component
public class LoopExecutor implements ShapeExecutor{
public static final String LOOP_NODE_KEY = "__loop_node_";
public static final String LOOP_ITEM = "loopItem";
public static final String BEFORE_LOOP_VARIABLE = "__loop_before_variable_";
public static final String LOOP_START = "loopStart";
public static final String LOOP_END = "loopEnd";
@Override
public void execute(SpiderNode node, SpiderContext context, Map<String,Object> variables) {

View File

@ -5,27 +5,51 @@
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<form class="layui-form editor-form-node">
<div class="layui-row">
<div class="layui-col-md4">
<div class="layui-form-item">
<label class="layui-form-label">节点名称</label>
<div class="layui-input-block">
<input type="text" name="value" placeholder="请输入节点名称" value="{{=d.value}}" autocomplete="off" class="layui-input">
</div>
</div>
</div>
<div class="layui-col-md4">
<div class="layui-form-item">
<label class="layui-form-label">次数或集合</label>
<div class="layui-input-block" codemirror="loopCount" placeholder="请输入循环次数或集合" data-value="{{=d.data.object.loopCount}}"></div>
</div>
</div>
<div class="layui-col-md4">
<div class="layui-form-item">
<label class="layui-form-label">循环变量</label>
<div class="layui-input-block">
<input type="text" name="loopItem" placeholder="请输入循环变量(默认item)" autocomplete="off" class="layui-input input-default" value="{{=d.data.object.loopItem}}">
</div>
</div>
</div>
</div>
<div class="layui-row">
<div class="layui-col-md4">
<div class="layui-form-item">
<label class="layui-form-label">下标变量</label>
<div class="layui-input-block">
<input type="text" name="loopVariableName" placeholder="请输入下标变量" autocomplete="off" class="layui-input input-default" value="{{=d.data.object.loopVariableName}}">
</div>
</div>
<!-- <div class="layui-form-item">
<label class="layui-form-label">循环变量</label>
<div class="layui-input-block">
<input type="text" name="loopVariableItem" placeholder="请输入循环变量" autocomplete="off" class="layui-input input-default" value="{{=d.data.object.loopVariableItem}}">
</div>
</div> -->
<div class="layui-col-md4">
<div class="layui-form-item">
<label class="layui-form-label">循环次数</label>
<div class="layui-input-block" codemirror="loopCount" placeholder="请输入循环次数" data-value="{{=d.data.object.loopCount}}"></div>
<label class="layui-form-label">开始位置</label>
<div class="layui-input-block" codemirror="loopStart" placeholder="请输入循环次数" data-value="{{=d.data.object.loopStart || '0'}}"></div>
</div>
</div>
<div class="layui-col-md4">
<div class="layui-form-item">
<label class="layui-form-label">结束位置</label>
<div class="layui-input-block" codemirror="loopEnd" placeholder="请输入循环次数" data-value="{{=d.data.object.loopEnd || -1}}"></div>
</div>
</div>
</div>
</form>
</div>