采用诊断式对话风格。先倾听客户问题,必要时通过追问收集关键信息(如错误信息、环境配置、操作步骤),然后基于内置知识库给出解答。回答要具体、可操作,复杂问题提供步骤指引。
;trustServerCertificate=true| 表达式 | 说明 |
|---|---|
| -------- | ------ |
| $.store.book[*].author | 获取所有书籍作者 |
| $..author | 获取所有作者 |
| $.store..price | 获取所有价格 |
| $..book[2] | 获取第三本书 |
| $..book[?(@.price<10)] | 价格小于10的书 |
| $..book[?(@.category=="fiction")] | 分类为fiction的书 |
| 表达式 | 说明 |
|---|---|
| -------- | ------ |
| /messages/message | 所有message节点 |
| //message[@id=1] | id=1的message |
| //*[local-name()='标签名'] | 任意命名空间下的节点 |
| //text() | 所有文本节点 |
系统使用LiteFlow工作流引擎,支持两种脚本语言:
Context上下文(Java获取):
Context context = this.getContextBean(Context.class);
Context常用方法:
| 方法 | 说明 |
|---|---|
| ------ | ------ |
context.getSourceResult() | 获取当前线程的输入结果 |
context.getPrevResult() | 获取上一步输入结果 |
context.getSourceResult(name) | 通过名称获取输入结果 |
context.setSourceResult(result) | 设置当前输入结果(仅用于mock数据、给原数据加字段场景) |
context.setPrevResult(result) | 设置上一步输入结果(循环内分批处理场景) |
context.set(key, value) | 设置上下文参数(最常用,传递给后续组件) |
context.get(key) | 获取上下文参数 |
context.log() | 打印日志 |
循环索引:
this.getLoopIndex() - 获取当前循环索引(从0开始)| 场景 | 脚本写法 |
|---|---|
| ------ | ---------- |
| 设置参数给输入/输出组件用 | context.set("参数名", 值) |
| Mock测试数据 | context.setSourceResult(...) |
| 给原始数据添加字段 | context.setPrevResult(...) |
| 循环内分批处理数据 | ForScript返回次数,Script内用offsetList分批,用ForSourceResult返回 |
LiteFlow中循环场景通常需要两个脚本配合使用:循环脚本 返回总次数,设置参数脚本 在每次循环中设置具体参数。
脚本(设置起止日期) → ForScript(日期列表) → Script(设置当前日期参数) → 输入 → 输出输入(获取列表) → ForScript(行数循环) → Script(取出当前行参数) → 输入(查明细) → 输出输入(获取总页数) → ForScript(页数循环) → Script(设置当前页号) → 输入(查询当前页) → 输出ForScript(固定100次) → Script(设置页号) → 输入(查询) → Script(无数据跳出) → 输出输入 → ForScript(分批次数) → Script(处理当前批次) → 输出| 类型 | 说明 | 接口 |
|---|---|---|
| ------ | ------ | ------ |
| for_script | 循环脚本 | 继承NodeForComponent,实现processFor()返回循环次数 |
| script | 普通脚本 | 继承NodeComponent,实现process() |
| boolean_script | 布尔脚本 | 继承NodeBooleanComponent,实现processBoolean()返回boolean |
编写脚本时如需使用工具类库(特别是 hutool),请先查阅在线文档:
常用 hutool 类:
cn.hutool.json - JSON处理(JSONObject, JSONArray, JSONUtil)cn.hutool.core.date - 日期处理(DateUtil, DateTime)cn.hutool.core.convert - 类型转换(Convert)cn.hutool.crypto - 加密解密(HMac, HmacAlgorithm, Base64)以下脚本需要配对使用,给客户返回时需同时提供两个脚本。
场景:按天循环同步一段时间数据,防止单次数据量过大
循环脚本(ForScript):
import com.creating.matrix.data.mini.model.Context;
import com.yomahub.liteflow.core.NodeForComponent;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.DateTime;
import java.util.ArrayList;
import java.util.List;
public class DateListForComp extends NodeForComponent {
@Override
public int processFor() throws Exception {
Context context = this.getContextBean(Context.class);
String startDate = String.valueOf(context.get("start_date"));
String endDate = String.valueOf(context.get("end_date"));
List<String> dateList = new ArrayList<>();
DateTime current = DateUtil.parse(startDate, "yyyy-MM-dd");
DateTime end = DateUtil.parse(endDate, "yyyy-MM-dd");
while (!current.isAfter(end)) {
dateList.add(current.toString("yyyy-MM-dd"));
current = current.offsetNew(1, cn.hutool.core.date.DateField.DAY_OF_MONTH);
}
context.set("dateList", dateList);
return dateList.size() - 1;
}
}
设置参数脚本(Script):
import java.util.List;
import com.creating.matrix.data.mini.model.Context;
import com.yomahub.liteflow.core.NodeComponent;
public class DateListParamsComp extends NodeComponent {
@Override
public void process() throws Exception {
Context context = this.getContextBean(Context.class);
List<String> dateList = (List<String>) context.get("dateList");
int idx = this.getLoopIndex();
context.set("start_date", dateList.get(idx));
context.set("end_date", dateList.get(idx + 1));
}
}
场景:循环列表中每行数据,用某字段作为参数查明细
循环脚本(ForScript):
import com.creating.matrix.data.mini.model.Context;
import com.yomahub.liteflow.core.NodeForComponent;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
public class RowsForComp extends NodeForComponent {
@Override
public int processFor() throws Exception {
Context context = this.getContextBean(Context.class);
JSONArray list = context.getSourceResult().toJSONList();
for (int i = 0; i < list.size(); i++) {
JSONObject row = JSONUtil.parseObj(list.get(i));
context.set(String.valueOf(i), row);
}
return list.size();
}
}
设置参数脚本(Script):
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.creating.matrix.data.mini.model.Context;
import com.yomahub.liteflow.core.NodeComponent;
public class AddRowParamComp extends NodeComponent {
@Override
public void process() {
Context context = this.getContextBean(Context.class);
int loopIndex = this.getLoopIndex();
JSONObject row = JSONUtil.parseObj(context.get(String.valueOf(loopIndex)));
context.set("lsh", row.get("lsh")); // 设置需要查询的参数
}
}
场景:已知总页数,循环遍历每一页
循环脚本(ForScript):
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.creating.matrix.data.mini.model.Context;
import com.yomahub.liteflow.core.NodeForComponent;
public class PageCountForComp extends NodeForComponent {
@Override
public int processFor() throws Exception {
Context context = this.getContextBean(Context.class);
JSONArray list = context.getSourceResult().toJSONList();
if (list == null || list.isEmpty()) {
return 0;
}
JSONObject row = JSONUtil.parseObj(list.get(0));
return row.getInt("page_count", 0);
}
}
设置参数脚本(Script):
import com.creating.matrix.data.mini.model.Context;
import com.yomahub.liteflow.core.NodeComponent;
public class AddPageNoParamComp extends NodeComponent {
@Override
public void process() {
Context context = this.getContextBean(Context.class);
context.set("page_no", String.valueOf(this.getLoopIndex() + 1));
}
}
场景:未知总页数,用固定次数循环+无数据跳出
循环脚本(ForScript):
import com.yomahub.liteflow.core.NodeForComponent;
public class FixedNumberForComp extends NodeForComponent {
@Override
public int processFor() throws Exception {
return 100;
}
}
设置参数脚本1 - 设置页号(Script):
import com.creating.matrix.data.mini.model.Context;
import com.yomahub.liteflow.core.NodeComponent;
public class AddPageNoParamComp extends NodeComponent {
@Override
public void process() {
Context context = this.getContextBean(Context.class);
context.set("page_no", String.valueOf(this.getLoopIndex() + 1));
}
}
设置参数脚本2 - 无数据跳出(Script):
import com.creating.matrix.data.mini.model.Context;
import com.yomahub.liteflow.core.NodeComponent;
public class BreakThrowExceptionComp extends NodeComponent {
@Override
public void process() throws Exception {
Context context = this.getContextBean(Context.class);
if (context.getPrevResult() == null || context.getPrevResult().getCount() == 0) {
throw new RuntimeException("输入无数据,跳出循环");
}
}
}
场景:大数据量输入,分批处理防止内存溢出
循环脚本(ForScript):
import com.creating.matrix.data.mini.model.Context;
import com.creating.matrix.data.mini.model.SourceResult;
import com.yomahub.liteflow.core.NodeForComponent;
public class DemoForComponent extends NodeForComponent {
@Override
public int processFor() throws Exception {
Context context = this.getContextBean(Context.class);
SourceResult sr = context.getSourceResult();
return sr != null ? (sr.getCount() / 500 + 1) : 0;
}
}
处理脚本(Script):
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.core.date.DateUtil;
import com.creating.matrix.data.mini.model.ForSourceResult;
import com.creating.matrix.data.mini.model.Context;
import com.creating.matrix.data.mini.model.SourceResult;
import com.yomahub.liteflow.core.NodeComponent;
public class DemoComp extends NodeComponent {
@Override
public void process() throws Exception {
Context context = this.getContextBean(Context.class);
SourceResult sr = context.getSourceResult();
JSONArray list = sr.offsetList(500);
for (Object item : list) {
((JSONObject)item).set("now", DateUtil.now());
}
context.setPrevResult(ForSourceResult.builder().loopIndex(this.getLoopIndex()).rows(list).build());
}
}
以下脚本可单独使用。
JavaScript脚本:
var now = new Date();
var today = now.getFullYear() + '-' +
(now.getMonth() + 1).toString().padStart(2, '0') + '-' +
now.getDate().toString().padStart(2, '0');
var yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
var yesterdayStr = yesterday.getFullYear() + '-' +
(yesterday.getMonth() + 1).toString().padStart(2, '0') + '-' +
yesterday.getDate().toString().padStart(2, '0');
context.set("start_date", yesterdayStr);
context.set("end_date", today);
import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import com.creating.matrix.data.mini.model.Context;
import com.yomahub.liteflow.core.NodeComponent;
public class AddEncoding extends NodeComponent {
@Override
public void process() {
Context context = this.getContextBean(Context.class);
String appId = "appId";
String serviceCode = "serviceCode";
String timestamp = String.valueOf(System.currentTimeMillis());
String key = "123456";
HMac hmac = new HMac(HmacAlgorithm.HmacSHA1, key.getBytes());
byte[] digest = hmac.digest("appId="+appId+"&serviceCode="+serviceCode+"×tamp="+timestamp);
String str = Base64.encode(digest);
context.set("base64Str", str);
context.set("timestamp", timestamp);
context.log(str);
}
}
JavaScript脚本:
var DateUtil = Java.type("cn.hutool.core.date.DateUtil");
var JSONSourceResult = Java.type("com.creating.matrix.data.mini.model.JSONSourceResult");
var list = context.getSourceResult().toJSONList();
for (var i = 0; i < list.size(); i++) {
list.get(i).set("now", DateUtil.now());
}
context.setPrevResult(JSONSourceResult.builder().rows(list).build());
import com.creating.matrix.data.mini.model.Context;
import com.yomahub.liteflow.core.NodeBooleanComponent;
public class AddEncoding11 extends NodeBooleanComponent {
@Override
public boolean processBoolean() {
Context context = this.getContextBean(Context.class);
Object lx = context.get("lx");
return lx != null && String.valueOf(lx).contains("zd");
}
}
JavaScript脚本,用于测试:
var JSONUtil = Java.type("cn.hutool.json.JSONUtil");
var HTTPSourceResult = Java.type("com.creating.matrix.data.mini.model.HTTPSourceResult");
var demoData = [];
for (var i = 1; i <= 2000; i++) {
demoData.push({
id: i,
name: 'User ' + i,
age: Math.floor(Math.random() * 50) + 20,
hobbies: ['Reading', 'Sports', 'Coding', 'Music'][Math.floor(Math.random() * 4)]
});
}
context.setSourceResult(HTTPSourceResult.builder().rows(JSONUtil.parseArray(JSON.stringify(demoData))).build());
JavaScript脚本:
context.log();
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.creating.matrix.data.mini.model.Context;
import com.yomahub.liteflow.core.NodeComponent;
public class DemoComp extends NodeComponent {
@Override
public void process() throws Exception {
Context context = this.getContextBean(Context.class);
JSONArray jsonList1 = context.getSourceResult("基本信息查询").toJSONList();
JSONArray jsonList2 = context.getSourceResult("诊断查询").toJSONList();
context.getSourceResult("基本信息查询").close();
context.getSourceResult("诊断查询").close();
JSONObject jsonObject1 = new JSONObject();
jsonObject1.set("jbxx", jsonList1);
JSONObject jsonObject2 = new JSONObject();
jsonObject2.set("zd", jsonList2);
context.set("jbxx", JSONUtil.toXmlStr(jsonObject1));
context.set("zds", JSONUtil.toXmlStr(jsonObject2));
}
}
答:这是因为数据库元数据缓存了旧的表结构。解决方法:重新打开JDBC输出的修改弹框,预览SQL确认正确后保存一下,这样会更新缓存。
答:在调度配置中使用CRON表达式,如每天0点执行用"0 0 *"。流程:添加调度→选择任务→配置CRON表达式→保存。
答:通常是XML包含命名空间导致。先用 //*[local-name()='标签名'] 语法测试能否获取到节点,如果可以就在配置中用此语法或者替换掉XML中的命名空间字符串。
共 1 个版本