QLExpress requests 设计
参考文档:https://github.com/alibaba/QLExpress
要达到的目标
使用QLExpress技术构建服务编排逻辑,用户可以通过简单的 QLExpress 脚本实现复杂的服务编排逻辑。
QL脚本使用示例如下:
- QLExpress 脚本标识用
code:前缀,也就是只认此段字符串前缀有code:开头就代表是QL脚本。如果不是QL脚本,那么则是标准的requestInfo json 内容,执行的逻辑将分支到标准的request执行。 request(requestInfo, vars)函数支持QL脚本嵌套,其中由 requestInfo参数来承接,标识用code:前缀,也就是当 requestInfo是字符串时,并且此字符串片段的前缀开头是code:那么我们将走内嵌 QLExpress 脚本执行逻辑。xmlcode:::开始到结束都标注为画代码的描述信息配置,这些配置在执行QL脚本时要进行截取剔除不要。- 自定义的
request(requestInfo, vars)函数可支持两个参数也可支持一个参数——》request(requestInfo)
code:
// 导入的包必须放到顶部
import org.apache.commons.lang.StringUtils;
import com.justep.util.net.ServiceUrlUtil;
//========== 标准类型的request使用示例
requestInfo =
'{
"request": [{
"body": {
"classSize": 2,
"teacher": "陈chensc",
"student": [{
"number": 1,
"name": "${schedulingJobId}",
"age": 40
}, {
"number": 8,
"name": "${schedulingJobId}",
"age": 30
}],
"describe": "附中..."
},
"formCommit": false,
"headers": {},
"method": "POST",
"responseHeader": false,
"url": "http://jobswork/main/resultHandleSchool"
}, {
"body": {
"jobId": "${schedulingJobId}",
"feedbackUrl": "${schedulingFeedbackUrl}",
"executeNumber": "${schedulingExecuteNumber}",
"requestCounts": "${schedulingRequestCounts}",
"content": "${$.student[0]}|json"
},
"formCommit": false,
"headers": {},
"method": "POST",
"responseHeader": false,
"url": "http://jobswork/main/workHandleStr",
"timeoutSeconds": 300
}],
"timeoutSeconds": 60,
""
}';
vars =
'{
"schedulingJobId": "jobid",
"schedulingFeedbackUrl": "http://dfdf.newdoa.com",
"schedulingExecuteNumber": 12,
"schedulingRequestCounts": 1
}';
// 这里执行request函数逻辑
result = request(requestInfo,vars);
logger("响应body: " + result.responseBody);
logger("响应headers: " + result.responseHeaders);
//========== 根据request结果result来执行自己的逻辑
list = new ArrayList<>();
for (int i = 0; i < 1; i++) {
item = result.responseBody.message;
list.add(item);
}
logger("最后list: " + list);
//========== OpenAPI类型的request使用示例
requests_OpenAPI =
{
"request": [{
"kind": "OpenAPI",
"docUrl": "https://petstore3.swagger.io/api/v3/openapi.json",
"docContent": "",
"path": "/pet/login",
"method": "GET",
"label": "Finds Pets by status.",
"parameters": {
"status": "${status}"
}
}, {
"kind": "OpenAPI",
"docUrl": "https://petstore3.swagger.io/api/v3/openapi.json",
"path": "/pet/saveBody",
"method": "POST",
"label": "Update an existing pet by Id.",
"body": "${body}"
}],
"timeoutSeconds": 60
};
vars_OpenAPI =
{
"body": "body内容",
"status": 1
};
// 这里执行request函数逻辑,根据上方的requestInfo_OpenAPI配置,此逻辑将执行OpenAPI类型request
result_OpenAPI = request(requests_OpenAPI, vars_OpenAPI);
//========== request(requests, var) 函数支持QL嵌套
requests_QLCode =
'code:
logger("=== QLExpress脚本开始执行 ===");
// 定义变量
requestInfo = {
"request": [{
"method": "POST",
"url": "https://jobclient/main/workHandleStr",
"body": {
"teacher": "陈八",
"student": [{"name": "张三"}, {"name": "李四"}]
}
}]
};
result = request(requestInfo);
';
result_QLCode = request(requests_QLCode);
// ========== import 导包测试,导入 StringUtils和ServiceUrlUtil
url = "service://{serviceName}/main/api";
logger(url);
if (StringUtils.isNotBlank(url)) {
logger("进入了=========");
newurl = ServiceUrlUtil.format(url);
}
//========== 画代码xml描述信息
xmlcode:::
<service filepath="service/main/message.service.m">
<label language="zh_CN">消息服务</label>
<uses/>
</service>
实现QL request
- 实现一个自定义的 request 函数
// 自定义 request 函数实现
public class RequestFunction implements CustomFunction {
@Override
public Object call(QContext qContext, Parameters parameters) throws Throwable {
// TODO
}
}
// request 函数在QL脚本中的使用
requestInfo = {};
vars = {};
request(requestInfo, vars)
- RequestUtil 中添加request QL对外的使用工具方法
// RequestUtil 工具类中添加如下方法为外界提供使用
public class RequestUtil {
/**
* 标准 request 和 ql_script 统一使用入口
*
* @param requestInfo requestInfo、requests、ql_script 等三种(必填),如果该文本前缀有 code: 开头的标识时,则是QL脚本,否则是requestInfo(JSON)、request(JSONArray)
* @param staticVar 静态变量(可选)
* @param extHeaders request请求透传头,只作用于requestInfo不作用于QL code(可选)
* @param options 扩展选项(可选):自定义函数在此处设置注入{"ql_custom_function":[{"functionName":"hello","functionClass":"com.justep.util.request.ql.HelloFunction"}]}
* @return
* @throws RequestException
*/
public static HttpInvokeResult<JSONObject> invokeRequest(String requestInfo, Map<String, Object> staticVar, Map<String, String> extHeaders, Map<String, Object> options) throws RequestException {
// TODO
}
}
// 该工具方法使用示例
// 传入的文档内容可以有三种组成,ql_script(QL脚本)、requestInfo(请求JSON信息)、requests(请求JSON数组)
String context = "";
String ql_script = "ql_script"; context = ql_script;
String requestInfo = "{}"; context = requestInfo;
String requests = "[]"; context = requests;
// 添加用户自定义函数 hello()
Map<String, Object> options = new HashMap<>();
List<QLCustomFunctionManager> qlCustomFunctionManagers = new ArrayList<>();
qlCustomFunctionManagers.add(new QLCustomFunctionManager("hello", "com.justep.cloud.HelloFunction"));
options.put("ql_custom_function", qlCustomFunctionManagers);
// 配置静态变量
Map<String, Object> staticVar = new HashMap<>();
staticVar.put("hello","world");
HttpInvokeResult<JSONObject> res = RequestUtil.invokeRequest(context, staticVar, null,options);
System.out.println("执行invokeQLRequest得到结果: " + JSON.toJSONString(res));
- 扩展自定义函数:如上方工具类代码所示,用options参数承载
// invokeRequest() 方法中options参数承载,传入内容示例如下:
{
"ql_custom_function": [{
"functionName": "hello",
"functionClass": "com.justep.util.request.ql.HelloFunction"
}]
}
- 为了方便调试,内置定义了一个logger 函数,实现方式与上方的 request 函数类似
// 可在 QL 脚本中这样使用
logger("=== QLExpress脚本开始执行 ===");
logger("=== QLExpress脚本开始执行 ===", 3, 2, 1);