From 551f148d19f1da6b814c3868cb77d33b838e5195 Mon Sep 17 00:00:00 2001 From: xuxueli <931591021@qq.com> Date: Sun, 26 Oct 2025 05:50:26 +0800 Subject: [PATCH] =?UTF-8?q?feat(job):=E9=87=8D=E6=9E=84HTTP=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=A4=84=E7=90=86=E5=99=A8=E4=BB=A5=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=9B=B4=E4=B8=B0=E5=AF=8C=E7=9A=84=E8=AF=B7=E6=B1=82=E5=8F=82?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入HttpTool工具类简化HTTP请求处理- 新增HttpJobParam内部类封装请求参数 - 支持GET/POST方法及自定义请求头、Cookie、表单数据 - 增加Content-Type和超时时间配置选项 - 提供完整的请求参数示例说明-优化域名白名单校验逻辑 - 使用StringTool替代原生字符串判空方法- 升级DOMAIN_WHITE_LIST为Set.of初始化方式 --- .../frameless/jobhandler/SampleXxlJob.java | 268 ++++++++++++------ .../job/executor/jobhandler/SampleXxlJob.java | 20 ++ 2 files changed, 206 insertions(+), 82 deletions(-) diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xxl/job/executor/sample/frameless/jobhandler/SampleXxlJob.java b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xxl/job/executor/sample/frameless/jobhandler/SampleXxlJob.java index 0293b2cf..f4edb432 100644 --- a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xxl/job/executor/sample/frameless/jobhandler/SampleXxlJob.java +++ b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xxl/job/executor/sample/frameless/jobhandler/SampleXxlJob.java @@ -2,7 +2,13 @@ package com.xxl.job.executor.sample.frameless.jobhandler; import com.xxl.job.core.context.XxlJobHelper; import com.xxl.job.core.handler.annotation.XxlJob; +import com.xxl.tool.core.StringTool; 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.LoggerFactory; @@ -136,19 +142,39 @@ public class SampleXxlJob { * * 参数示例: *
+     *      // 1、简单示例:
      *      {
      *          "url": "http://www.baidu.com",
      *          "method": "get",
      *          "data": "hello world"
      *      }
+     *
+     *      // 2、完整参数示例:
+     *      {
+     *          "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"
+     *      }
      *  
*/ @XxlJob("httpJobHandler") public void httpJobHandler() throws Exception { - // param + // param data String param = XxlJobHelper.getJobParam(); - if (param==null || param.trim().length()==0) { + if (param==null || param.trim().isEmpty()) { XxlJobHelper.log("param["+ param +"] invalid."); XxlJobHelper.handleFail(); @@ -156,113 +182,89 @@ public class SampleXxlJob { } // param parse - String url; - String method; - String data; + HttpJobParam httpJobParam = null; try { - Map paramMap = GsonTool.fromJson(param, Map.class); - url = paramMap.get("url"); - method = paramMap.get("method"); - data = paramMap.get("data"); + httpJobParam = GsonTool.fromJson(param, HttpJobParam.class); } catch (Exception e) { - XxlJobHelper.log(e); + XxlJobHelper.log(new RuntimeException("HttpJobParam parse error", e)); XxlJobHelper.handleFail(); return; } // param valid - if (url==null || url.trim().isEmpty()) { - XxlJobHelper.log("url["+ url +"] invalid."); + if (httpJobParam == null) { + XxlJobHelper.log("param parse fail."); XxlJobHelper.handleFail(); return; } - if (!isValidDomain( url)) { - XxlJobHelper.log("url["+ url +"] not allowed."); + if (StringTool.isBlank(httpJobParam.getUrl())) { + XxlJobHelper.log("url["+ httpJobParam.getUrl() +"] invalid."); XxlJobHelper.handleFail(); return; } - if (method==null || !Arrays.asList("GET", "POST").contains(method.toUpperCase())) { - XxlJobHelper.log("method["+ method +"] invalid."); + if (!isValidDomain(httpJobParam.getUrl())) { + XxlJobHelper.log("url["+ httpJobParam.getUrl() +"] not allowed."); XxlJobHelper.handleFail(); return; } - method = method.toUpperCase(); - boolean isPostMethod = method.equals("POST"); - - // request - HttpURLConnection connection = null; - BufferedReader bufferedReader = null; - try { - // 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 method = Method.POST; + if (StringTool.isNotBlank(httpJobParam.getMethod())) { + Method methodParam = Method.valueOf(httpJobParam.getMethod().toUpperCase()); + if (methodParam == null) { + XxlJobHelper.log("method["+ httpJobParam.getMethod() +"] invalid."); + XxlJobHelper.handleFail(); + return; } - - // result - bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)); - StringBuilder result = new StringBuilder(); - String line; - while ((line = bufferedReader.readLine()) != null) { - result.append(line); + method = methodParam; + } + ContentType contentType = ContentType.JSON; + if (StringTool.isNotBlank(httpJobParam.getContentType())) { + for (ContentType contentTypeParam : ContentType.values()) { + if (contentTypeParam.getValue().equals(httpJobParam.getContentType())) { + contentType = contentTypeParam; + break; + } } - String responseMsg = result.toString(); - - XxlJobHelper.log(responseMsg); - + } + if (httpJobParam.getTimeout() <= 0) { + XxlJobHelper.log("timeout["+ httpJobParam.getTimeout() +"] invalid."); + XxlJobHelper.handleFail(); 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:
" + httpResponse.response()); } catch (Exception e) { XxlJobHelper.log(e); - 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 DOMAIN_WHITE_LIST = new HashSet(Arrays.asList( + /** + * domain white-list, for httpJobHandler + */ + private static Set DOMAIN_WHITE_LIST = Set.of( "http://www.baidu.com", "http://cn.bing.com" - )); - // valid if domain is in white-list + ); + + /** + * valid if domain is in white-list + */ private boolean isValidDomain(String url) { if (url == null || DOMAIN_WHITE_LIST.isEmpty()) { return false; @@ -275,6 +277,108 @@ public class SampleXxlJob { 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 headers; // 存储请求头 + private Map cookies; // Cookie(需要格式转换) + private int timeout; // 请求超时时间 + private String data; // 存储请求体 + private Map 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 getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public Map getCookies() { + return cookies; + } + + public void setCookies(Map 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 getForm() { + return form; + } + + public void setForm(Map form) { + this.form = form; + } + + public String getAuth() { + return auth; + } + + public void setAuth(String auth) { + this.auth = auth; + } + } + /** * 5、生命周期任务示例:任务初始化与销毁时,支持自定义相关逻辑; diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/jobhandler/SampleXxlJob.java b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/jobhandler/SampleXxlJob.java index 383a2668..9bc59c08 100644 --- a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/jobhandler/SampleXxlJob.java +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/jobhandler/SampleXxlJob.java @@ -138,11 +138,31 @@ public class SampleXxlJob { * * 参数示例: *
+     *      // 1、简单示例:
      *      {
      *          "url": "http://www.baidu.com",
      *          "method": "get",
      *          "data": "hello world"
      *      }
+     *
+     *      // 2、完整参数示例:
+     *      {
+     *          "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"
+     *      }
      *  
*/ @XxlJob("httpJobHandler")