通用HTTP任务(httpJobHandler)强化,支持更丰富请求参数设置,完整参数示例如下:

pull/72/head
xuxueli 11 months ago
parent 201fe07373
commit 586a31fdb5

@ -1186,13 +1186,33 @@ public void demoJobHandler() throws Exception {
**执行器内置任务列表:** **执行器内置任务列表:**
- a、demoJobHandler简单示例任务任务内部模拟耗时任务逻辑用户可在线体验Rolling Log等功能 - a、demoJobHandler简单示例任务任务内部模拟耗时任务逻辑用户可在线体验Rolling Log等功能
- b、shardingJobHandler分片示例任务任务内部模拟处理分片参数可参考熟悉分片任务 - b、shardingJobHandler分片示例任务任务内部模拟处理分片参数可参考熟悉分片任务
- c、httpJobHandler通用HTTP任务Handler业务方只需要提供HTTP链接等信息即可不限制语言、平台。示例任务入参如下: - c、httpJobHandler通用HTTP任务Handler业务方只需要提供HTTP链接等信息即可不限制语言、平台。任务入参示例如下:
``` ```
// 1、简单示例
{ {
"url": "http://www.baidu.com", "url": "http://www.baidu.com",
"method": "get", "method": "GET",
"data": "hello world" "data": "hello world"
} }
// 2、完整参数示例
{
"url": "http://www.baidu.com", // 请求URL
"method": "POST", // 请求方法支持GET、POST、HEAD、OPTIONS、PUT、DELETE、TRACE
"contentType": "application/json", // 请求内容类型支持application/json、application/x-www-form-urlencoded、application/xml、text/html、text/xml、text/plain
"headers": { // 请求Headerkey-value结构
"header01": "value01"
},
"cookies": { // 请求Cookiekey-value结构
"cookie01": "value01"
},
"timeout": 3000, // 请求超时时间,单位:毫秒
"data": "request body data", // 请求Body数据仅针对 POST 请求有效
"form": { // 请求Form数据仅针对 GET 请求有效
"key01": "value01"
},
"auth": "auth data" // 请求认证信息, 通过Basic Auth方式认证
}
``` ```
- d、commandJobHandler通用命令行任务Handler业务方只需要提供命令行即可命令及参数之间通过空格隔开如任务参数 "ls la" 或 "pwd" 将会执行命令并输出数据; - d、commandJobHandler通用命令行任务Handler业务方只需要提供命令行即可命令及参数之间通过空格隔开如任务参数 "ls la" 或 "pwd" 将会执行命令并输出数据;
@ -2586,10 +2606,30 @@ public void execute() {
- 12、【升级】升级多项maven依赖至较新版本如 netty、groovy、spring、spring-ai、dify 等; - 12、【升级】升级多项maven依赖至较新版本如 netty、groovy、spring、spring-ai、dify 等;
- 14、【优化】任务回调失败日志读写磁盘逻辑优化解决极端情况下大文件读写内存问题 - 14、【优化】任务回调失败日志读写磁盘逻辑优化解决极端情况下大文件读写内存问题
- 15、【修复】脚本任务process销毁逻辑优化解决风险情况下脚本进程无法终止问题 - 15、【修复】脚本任务process销毁逻辑优化解决风险情况下脚本进程无法终止问题
- 16、【ING】UI框架重构升级提升交互体验 - 16、【强化】通用HTTP任务httpJobHandler强化支持更丰富请求参数设置完整参数示例如下
- 17、【ING】调整资源加载逻辑移除不必要的拦截器逻辑提升页面加载效率 ```
- 18、【ING】规范API交互协议通用响应结构体调整为Response {
- 19、【ING】Http通讯组件升级基于接口代理方式重构 "url": "http://www.baidu.com",
"method": "POST",
"contentType": "application/json",
"headers": {
"header01": "value01"
},
"cookies": {
"cookie01": "value01"
},
"timeout": 3000,
"data": "request body data",
"form": {
"key01": "value01"
},
"auth": "auth data"
}
```
- 17、【ING】UI框架重构升级提升交互体验
- 18、【ING】调整资源加载逻辑移除不必要的拦截器逻辑提升页面加载效率
- 19、【ING】规范API交互协议通用响应结构体调整为Response
- 20、【ING】Http通讯组件升级基于接口代理方式重构
### TODO LIST ### TODO LIST

@ -2,20 +2,20 @@ package com.xxl.job.executor.jobhandler;
import com.xxl.job.core.context.XxlJobHelper; import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob; import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.tool.core.StringTool;
import com.xxl.tool.gson.GsonTool; import com.xxl.tool.gson.GsonTool;
import com.xxl.tool.http.HttpTool;
import com.xxl.tool.http.http.HttpResponse;
import com.xxl.tool.http.http.enums.ContentType;
import com.xxl.tool.http.http.enums.Header;
import com.xxl.tool.http.http.enums.Method;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -148,9 +148,9 @@ public class SampleXxlJob {
@XxlJob("httpJobHandler") @XxlJob("httpJobHandler")
public void httpJobHandler() throws Exception { public void httpJobHandler() throws Exception {
// param // param data
String param = XxlJobHelper.getJobParam(); String param = XxlJobHelper.getJobParam();
if (param==null || param.trim().length()==0) { if (param==null || param.trim().isEmpty()) {
XxlJobHelper.log("param["+ param +"] invalid."); XxlJobHelper.log("param["+ param +"] invalid.");
XxlJobHelper.handleFail(); XxlJobHelper.handleFail();
@ -158,113 +158,89 @@ public class SampleXxlJob {
} }
// param parse // param parse
String url; HttpJobParam httpJobParam = null;
String method;
String data;
try { try {
Map<String, String> paramMap = GsonTool.fromJson(param, Map.class); httpJobParam = GsonTool.fromJson(param, HttpJobParam.class);
url = paramMap.get("url");
method = paramMap.get("method");
data = paramMap.get("data");
} catch (Exception e) { } catch (Exception e) {
XxlJobHelper.log(e); XxlJobHelper.log(new RuntimeException("HttpJobParam parse error", e));
XxlJobHelper.handleFail(); XxlJobHelper.handleFail();
return; return;
} }
// param valid // param valid
if (url==null || url.trim().isEmpty()) { if (httpJobParam == null) {
XxlJobHelper.log("url["+ url +"] invalid."); XxlJobHelper.log("param parse fail.");
XxlJobHelper.handleFail(); XxlJobHelper.handleFail();
return; return;
} }
if (!isValidDomain( url)) { if (StringTool.isBlank(httpJobParam.getUrl())) {
XxlJobHelper.log("url["+ url +"] not allowed."); XxlJobHelper.log("url["+ httpJobParam.getUrl() +"] invalid.");
XxlJobHelper.handleFail(); XxlJobHelper.handleFail();
return; return;
} }
if (method==null || !Arrays.asList("GET", "POST").contains(method.toUpperCase())) { if (!isValidDomain(httpJobParam.getUrl())) {
XxlJobHelper.log("method["+ method +"] invalid."); XxlJobHelper.log("url["+ httpJobParam.getUrl() +"] not allowed.");
XxlJobHelper.handleFail(); XxlJobHelper.handleFail();
return; return;
} }
method = method.toUpperCase(); Method method = Method.POST;
boolean isPostMethod = method.equals("POST"); if (StringTool.isNotBlank(httpJobParam.getMethod())) {
Method methodParam = Method.valueOf(httpJobParam.getMethod().toUpperCase());
// request if (methodParam == null) {
HttpURLConnection connection = null; XxlJobHelper.log("method["+ httpJobParam.getMethod() +"] invalid.");
BufferedReader bufferedReader = null; XxlJobHelper.handleFail();
try { return;
// connection
URL realUrl = new URL(url);
connection = (HttpURLConnection) realUrl.openConnection();
// connection setting
connection.setRequestMethod(method);
connection.setDoOutput(isPostMethod);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setReadTimeout(5 * 1000);
connection.setConnectTimeout(3 * 1000);
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
connection.setRequestProperty("Accept-Charset", "application/json;charset=UTF-8");
// do connection
connection.connect();
// data
if (isPostMethod && data!=null && !data.trim().isEmpty()) {
DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
dataOutputStream.write(data.getBytes(StandardCharsets.UTF_8));
dataOutputStream.flush();
dataOutputStream.close();
}
// valid StatusCode
int statusCode = connection.getResponseCode();
if (statusCode != 200) {
throw new RuntimeException("Http Request StatusCode(" + statusCode + ") Invalid.");
} }
method = methodParam;
// result }
bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)); ContentType contentType = ContentType.JSON;
StringBuilder result = new StringBuilder(); if (StringTool.isNotBlank(httpJobParam.getContentType())) {
String line; for (ContentType contentTypeParam : ContentType.values()) {
while ((line = bufferedReader.readLine()) != null) { if (contentTypeParam.getValue().equals(httpJobParam.getContentType())) {
result.append(line); contentType = contentTypeParam;
break;
}
} }
String responseMsg = result.toString(); }
if (httpJobParam.getTimeout() <= 0) {
XxlJobHelper.log(responseMsg); XxlJobHelper.log("timeout["+ httpJobParam.getTimeout() +"] invalid.");
XxlJobHelper.handleFail();
return; return;
}
// do request
try {
HttpResponse httpResponse = HttpTool.createRequest()
.url(httpJobParam.getUrl())
.method(method)
.contentType(contentType)
.header(httpJobParam.getHeaders())
.header(Header.USER_AGENT.getValue(), Header.DEFAULT_USER_AGENT_WIN)
.cookie(httpJobParam.getCookies())
.body(httpJobParam.getData())
.form(httpJobParam.getForm())
.auth(httpJobParam.getAuth())
.execute();
XxlJobHelper.log("StatusCode: " + httpResponse.statusCode());
XxlJobHelper.log("Response: <br>" + httpResponse.response());
} catch (Exception e) { } catch (Exception e) {
XxlJobHelper.log(e); XxlJobHelper.log(e);
XxlJobHelper.handleFail(); XxlJobHelper.handleFail();
return;
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
if (connection != null) {
connection.disconnect();
}
} catch (Exception e2) {
XxlJobHelper.log(e2);
}
} }
} }
// domain white-list, for httpJobHandler /**
private static Set<String> DOMAIN_WHITE_LIST = new HashSet<String>(Arrays.asList( * domain white-list, for httpJobHandler
*/
private static Set<String> DOMAIN_WHITE_LIST = Set.of(
"http://www.baidu.com", "http://www.baidu.com",
"http://cn.bing.com" "http://cn.bing.com"
)); );
// valid if domain is in white-list
/**
* valid if domain is in white-list
*/
private boolean isValidDomain(String url) { private boolean isValidDomain(String url) {
if (url == null || DOMAIN_WHITE_LIST.isEmpty()) { if (url == null || DOMAIN_WHITE_LIST.isEmpty()) {
return false; return false;
@ -277,6 +253,108 @@ public class SampleXxlJob {
return false; return false;
} }
/*public static void main(String[] args) {
HttpJobParam httpJobParam = new HttpJobParam();
httpJobParam.setUrl("http://www.baidu.com");
httpJobParam.setMethod(Method.POST.name());
httpJobParam.setContentType(ContentType.JSON.getValue());
httpJobParam.setHeaders(Map.of("header01", "value01"));
httpJobParam.setCookies(Map.of("cookie01", "value01"));
httpJobParam.setTimeout(3000);
httpJobParam.setData("request body data");
httpJobParam.setForm(Map.of("form01", "value01"));
httpJobParam.setAuth("auth data");
logger.info(GsonTool.toJson(httpJobParam));
}*/
/**
* http job param
*/
private static class HttpJobParam{
private String url; // 请求 Url
private String method; // Method
private String contentType; // Content-Type
private Map<String, String> headers; // 存储请求头
private Map<String, String> cookies; // Cookie需要格式转换
private int timeout; // 请求超时时间
private String data; // 存储请求体
private Map<String, String> form; // 存储表单数据
private String auth; // 鉴权信息
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public Map<String, String> getHeaders() {
return headers;
}
public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}
public Map<String, String> getCookies() {
return cookies;
}
public void setCookies(Map<String, String> cookies) {
this.cookies = cookies;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Map<String, String> getForm() {
return form;
}
public void setForm(Map<String, String> form) {
this.form = form;
}
public String getAuth() {
return auth;
}
public void setAuth(String auth) {
this.auth = auth;
}
}
/** /**
* 5 * 5
*/ */

Loading…
Cancel
Save