ソースを参照

添加job模块

pangqijun 1 年間 前
コミット
5474784142

+ 8 - 0
pom.xml

@@ -71,6 +71,7 @@
             <artifactId>blade-core-develop</artifactId>
             <version>${blade.tool.version}</version>
         </dependency>
+        <!-- 存储 -->
         <dependency>
             <groupId>org.springblade</groupId>
             <artifactId>blade-core-oss</artifactId>
@@ -82,11 +83,18 @@
                 </exclusion>
             </exclusions>
         </dependency>
+        <!-- 短信 -->
         <dependency>
             <groupId>org.springblade</groupId>
             <artifactId>blade-core-sms</artifactId>
             <version>${blade.tool.version}</version>
         </dependency>
+        <!-- xxljob 定时任务 -->
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-job</artifactId>
+            <version>${blade.tool.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.springblade</groupId>
             <artifactId>blade-core-report</artifactId>

+ 253 - 0
src/main/java/org/springblade/modules/job/SampleXxlJob.java

@@ -0,0 +1,253 @@
+package org.springblade.modules.job;
+
+import com.xxl.job.core.context.XxlJobHelper;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * XxlJob开发示例(Bean模式)
+ *
+ * 开发步骤:
+ *      1、任务开发:在Spring Bean实例中,开发Job方法;
+ *      2、注解配置:为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")",注解value值对应的是调度中心新建任务的JobHandler属性的值。
+ *      3、执行日志:需要通过 "XxlJobHelper.log" 打印执行日志;
+ *      4、任务结果:默认任务结果为 "成功" 状态,不需要主动设置;如有诉求,比如设置任务结果为失败,可以通过 "XxlJobHelper.handleFail/handleSuccess" 自主设置任务结果;
+ *
+ * @author xuxueli 2019-12-11 21:52:51
+ */
+@Component
+public class SampleXxlJob {
+    private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class);
+
+
+    /**
+     * 1、简单任务示例(Bean模式)
+     */
+    @XxlJob("demoJobHandler")
+    public void demoJobHandler() throws Exception {
+        XxlJobHelper.log("XXL-JOB, Hello World.");
+
+        for (int i = 0; i < 5; i++) {
+            XxlJobHelper.log("beat at:" + i);
+            TimeUnit.SECONDS.sleep(2);
+        }
+        // default success
+    }
+
+
+    /**
+     * 2、分片广播任务
+     */
+    @XxlJob("shardingJobHandler")
+    public void shardingJobHandler() throws Exception {
+
+        // 分片参数
+        int shardIndex = XxlJobHelper.getShardIndex();
+        int shardTotal = XxlJobHelper.getShardTotal();
+
+        XxlJobHelper.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardIndex, shardTotal);
+
+        // 业务逻辑
+        for (int i = 0; i < shardTotal; i++) {
+            if (i == shardIndex) {
+                XxlJobHelper.log("第 {} 片, 命中分片开始处理", i);
+            } else {
+                XxlJobHelper.log("第 {} 片, 忽略", i);
+            }
+        }
+
+    }
+
+
+    /**
+     * 3、命令行任务
+     */
+    @XxlJob("commandJobHandler")
+    public void commandJobHandler() throws Exception {
+        String command = XxlJobHelper.getJobParam();
+        int exitValue = -1;
+
+        BufferedReader bufferedReader = null;
+        try {
+            // command process
+            ProcessBuilder processBuilder = new ProcessBuilder();
+            processBuilder.command(command);
+            processBuilder.redirectErrorStream(true);
+
+            Process process = processBuilder.start();
+            //Process process = Runtime.getRuntime().exec(command);
+
+            BufferedInputStream bufferedInputStream = new BufferedInputStream(process.getInputStream());
+            bufferedReader = new BufferedReader(new InputStreamReader(bufferedInputStream));
+
+            // command log
+            String line;
+            while ((line = bufferedReader.readLine()) != null) {
+                XxlJobHelper.log(line);
+            }
+
+            // command exit
+            process.waitFor();
+            exitValue = process.exitValue();
+        } catch (Exception e) {
+            XxlJobHelper.log(e);
+        } finally {
+            if (bufferedReader != null) {
+                bufferedReader.close();
+            }
+        }
+
+        if (exitValue == 0) {
+            // default success
+        } else {
+            XxlJobHelper.handleFail("command exit value("+exitValue+") is failed");
+        }
+
+    }
+
+
+    /**
+     * 4、跨平台Http任务
+     *  参数示例:
+     *      "url: http://www.baidu.com\n" +
+     *      "method: get\n" +
+     *      "data: content\n";
+     */
+    @XxlJob("httpJobHandler")
+    public void httpJobHandler() throws Exception {
+
+        // param parse
+        String param = XxlJobHelper.getJobParam();
+        if (param==null || param.trim().length()==0) {
+            XxlJobHelper.log("param["+ param +"] invalid.");
+
+            XxlJobHelper.handleFail();
+            return;
+        }
+
+        String[] httpParams = param.split("\n");
+        String url = null;
+        String method = null;
+        String data = null;
+        for (String httpParam: httpParams) {
+            if (httpParam.startsWith("url:")) {
+                url = httpParam.substring(httpParam.indexOf("url:") + 4).trim();
+            }
+            if (httpParam.startsWith("method:")) {
+                method = httpParam.substring(httpParam.indexOf("method:") + 7).trim().toUpperCase();
+            }
+            if (httpParam.startsWith("data:")) {
+                data = httpParam.substring(httpParam.indexOf("data:") + 5).trim();
+            }
+        }
+
+        // param valid
+        if (url==null || url.trim().length()==0) {
+            XxlJobHelper.log("url["+ url +"] invalid.");
+
+            XxlJobHelper.handleFail();
+            return;
+        }
+        if (method==null || !Arrays.asList("GET", "POST").contains(method)) {
+            XxlJobHelper.log("method["+ method +"] invalid.");
+
+            XxlJobHelper.handleFail();
+            return;
+        }
+        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().length()>0) {
+                DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
+                dataOutputStream.write(data.getBytes("UTF-8"));
+                dataOutputStream.flush();
+                dataOutputStream.close();
+            }
+
+            // valid StatusCode
+            int statusCode = connection.getResponseCode();
+            if (statusCode != 200) {
+                throw new RuntimeException("Http Request StatusCode(" + statusCode + ") Invalid.");
+            }
+
+            // result
+            bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
+            StringBuilder result = new StringBuilder();
+            String line;
+            while ((line = bufferedReader.readLine()) != null) {
+                result.append(line);
+            }
+            String responseMsg = result.toString();
+
+            XxlJobHelper.log(responseMsg);
+
+            return;
+        } 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);
+            }
+        }
+
+    }
+
+    /**
+     * 5、生命周期任务示例:任务初始化与销毁时,支持自定义相关逻辑;
+     */
+    @XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy")
+    public void demoJobHandler2() throws Exception {
+        XxlJobHelper.log("XXL-JOB, Hello World.");
+    }
+    public void init(){
+        logger.info("init");
+    }
+    public void destroy(){
+        logger.info("destroy");
+    }
+
+
+}

+ 23 - 1
src/main/resources/application.yml

@@ -187,4 +187,26 @@ sms:
   access-key-id: LTAI5tJkrXAxPJnQdaQX6ZZX
   access-key-secret: cI9X9pjjcKavsEXfbf5QFeElAoklHd
   # 检测到数据异常时接收通知短信的号码
-  message-phone: 18786650887
+  message-phone: 18786650887
+
+# xxl-job配置
+xxl:
+  job:
+    admin:
+      ### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
+      addresses: http://127.0.0.1:8080/xxl-job-admin
+      ### 执行器通讯TOKEN [选填]:非空时启用;
+    accessToken: default_token
+    executor:
+      ### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
+      appname: xxl-job-executor
+      ### 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
+      address:
+      ### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
+      ip:
+      ### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
+      port: 9999
+      ### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
+      logpath: logs/xxl-job/jobhandler
+      ### 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
+      logretentiondays: 30