diff options
| author | doufenghu <[email protected]> | 2020-02-21 17:30:08 +0800 |
|---|---|---|
| committer | doufenghu <[email protected]> | 2020-02-21 17:30:08 +0800 |
| commit | 5350840a9f4c76fbb6c5ec4b3bdf8c75dcc9ccf3 (patch) | |
| tree | bb4cfd98a85e10c6a43340bf8885463a6e5802c0 /xxl-job-executor-samples | |
| parent | c71da1bd2069ae9f608bc214aae7d8ea3b2f97c0 (diff) | |
Diffstat (limited to 'xxl-job-executor-samples')
72 files changed, 2893 insertions, 0 deletions
diff --git a/xxl-job-executor-samples/pom.xml b/xxl-job-executor-samples/pom.xml new file mode 100644 index 0000000..2d28467 --- /dev/null +++ b/xxl-job-executor-samples/pom.xml @@ -0,0 +1,22 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job</artifactId> + <version>2.2.0-SNAPSHOT</version> + </parent> + <artifactId>xxl-job-executor-samples</artifactId> + <packaging>pom</packaging> + + <modules> + <module>xxl-job-executor-sample-frameless</module> + <module>xxl-job-executor-sample-springboot</module> + <module>xxl-job-executor-sample-spring</module> + <module>xxl-job-executor-sample-jfinal</module> + <module>xxl-job-executor-sample-nutz</module> + <module>xxl-job-executor-sample-jboot</module> + </modules> + +</project>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/pom.xml b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/pom.xml new file mode 100644 index 0000000..36bb61f --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/pom.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-executor-samples</artifactId> + <version>2.2.0-SNAPSHOT</version> + </parent> + <artifactId>xxl-job-executor-sample-frameless</artifactId> + <packaging>jar</packaging> + + <name>${project.artifactId}</name> + <description>Example executor project for spring boot.</description> + <url>https://www.xuxueli.com/</url> + + + <dependencies> + + <!-- slf4j --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>${slf4j-api.version}</version> + </dependency> + + <!-- xxl-job-core --> + <dependency> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-core</artifactId> + <version>${project.parent.version}</version> + </dependency> + </dependencies> + + +</project>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/FramelessApplication.java b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/FramelessApplication.java new file mode 100644 index 0000000..092aa4b --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/FramelessApplication.java @@ -0,0 +1,38 @@ +package com.xuxueli.executor.sample.frameless; + +import com.xuxueli.executor.sample.frameless.config.FrameLessXxlJobConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.TimeUnit; + +/** + * @author xuxueli 2018-10-31 19:05:43 + */ +public class FramelessApplication { + private static Logger logger = LoggerFactory.getLogger(FramelessApplication.class); + + public static void main(String[] args) { + + try { + // start + FrameLessXxlJobConfig.getInstance().initXxlJobExecutor(); + + // Blocks until interrupted + while (true) { + try { + TimeUnit.HOURS.sleep(1); + } catch (InterruptedException e) { + break; + } + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + } finally { + // destory + FrameLessXxlJobConfig.getInstance().destoryXxlJobExecutor(); + } + + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/config/FrameLessXxlJobConfig.java b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/config/FrameLessXxlJobConfig.java new file mode 100644 index 0000000..28aa06a --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/config/FrameLessXxlJobConfig.java @@ -0,0 +1,98 @@ +package com.xuxueli.executor.sample.frameless.config; + +import com.xuxueli.executor.sample.frameless.jobhandler.CommandJobHandler; +import com.xuxueli.executor.sample.frameless.jobhandler.DemoJobHandler; +import com.xuxueli.executor.sample.frameless.jobhandler.HttpJobHandler; +import com.xuxueli.executor.sample.frameless.jobhandler.ShardingJobHandler; +import com.xxl.job.core.executor.XxlJobExecutor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Properties; + +/** + * @author xuxueli 2018-10-31 19:05:43 + */ +public class FrameLessXxlJobConfig { + private static Logger logger = LoggerFactory.getLogger(FrameLessXxlJobConfig.class); + + + private static FrameLessXxlJobConfig instance = new FrameLessXxlJobConfig(); + public static FrameLessXxlJobConfig getInstance() { + return instance; + } + + + private XxlJobExecutor xxlJobExecutor = null; + + /** + * init + */ + public void initXxlJobExecutor() { + + // registry jobhandler + XxlJobExecutor.registJobHandler("demoJobHandler", new DemoJobHandler()); + XxlJobExecutor.registJobHandler("shardingJobHandler", new ShardingJobHandler()); + XxlJobExecutor.registJobHandler("httpJobHandler", new HttpJobHandler()); + XxlJobExecutor.registJobHandler("commandJobHandler", new CommandJobHandler()); + + // load executor prop + Properties xxlJobProp = loadProperties("xxl-job-executor.properties"); + + + // init executor + xxlJobExecutor = new XxlJobExecutor(); + xxlJobExecutor.setAdminAddresses(xxlJobProp.getProperty("xxl.job.admin.addresses")); + xxlJobExecutor.setAppName(xxlJobProp.getProperty("xxl.job.executor.appname")); + xxlJobExecutor.setIp(xxlJobProp.getProperty("xxl.job.executor.ip")); + xxlJobExecutor.setPort(Integer.valueOf(xxlJobProp.getProperty("xxl.job.executor.port"))); + xxlJobExecutor.setAccessToken(xxlJobProp.getProperty("xxl.job.accessToken")); + xxlJobExecutor.setLogPath(xxlJobProp.getProperty("xxl.job.executor.logpath")); + xxlJobExecutor.setLogRetentionDays(Integer.valueOf(xxlJobProp.getProperty("xxl.job.executor.logretentiondays"))); + + // start executor + try { + xxlJobExecutor.start(); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + + /** + * destory + */ + public void destoryXxlJobExecutor() { + if (xxlJobExecutor != null) { + xxlJobExecutor.destroy(); + } + } + + + public static Properties loadProperties(String propertyFileName) { + InputStreamReader in = null; + try { + ClassLoader loder = Thread.currentThread().getContextClassLoader(); + + in = new InputStreamReader(loder.getResourceAsStream(propertyFileName), "UTF-8");; + if (in != null) { + Properties prop = new Properties(); + prop.load(in); + return prop; + } + } catch (IOException e) { + logger.error("load {} error!", propertyFileName); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + logger.error("close {} error!", propertyFileName); + } + } + } + return null; + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/CommandJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/CommandJobHandler.java new file mode 100644 index 0000000..fb8281a --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/CommandJobHandler.java @@ -0,0 +1,54 @@ +package com.xuxueli.executor.sample.frameless.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.InputStreamReader; + +/** + * 命令行任务 + * + * @author xuxueli 2018-09-16 03:48:34 + */ +public class CommandJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + String command = param; + int exitValue = -1; + + BufferedReader bufferedReader = null; + try { + // command process + 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) { + XxlJobLogger.log(line); + } + + // command exit + process.waitFor(); + exitValue = process.exitValue(); + } catch (Exception e) { + XxlJobLogger.log(e); + } finally { + if (bufferedReader != null) { + bufferedReader.close(); + } + } + + if (exitValue == 0) { + return IJobHandler.SUCCESS; + } else { + return new ReturnT<String>(IJobHandler.FAIL.getCode(), "command exit value("+exitValue+") is failed"); + } + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/DemoJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/DemoJobHandler.java new file mode 100644 index 0000000..1807156 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/DemoJobHandler.java @@ -0,0 +1,32 @@ +package com.xuxueli.executor.sample.frameless.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.util.concurrent.TimeUnit; + +/** + * 任务Handler示例(Bean模式) + * + * 开发步骤: + * 1、继承"IJobHandler":“com.xxl.job.core.handler.IJobHandler”; + * 2、注册到执行器工厂:在 "JFinalCoreConfig.initXxlJobExecutor" 中手动注册,注解key值对应的是调度中心新建任务的JobHandler属性的值。 + * 3、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志; + * + * @author xuxueli 2015-12-19 19:43:36 + */ +public class DemoJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + XxlJobLogger.log("XXL-JOB, Hello World."); + + for (int i = 0; i < 5; i++) { + XxlJobLogger.log("beat at:" + i); + TimeUnit.SECONDS.sleep(2); + } + return SUCCESS; + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/HttpJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/HttpJobHandler.java new file mode 100644 index 0000000..a8748a8 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/HttpJobHandler.java @@ -0,0 +1,87 @@ +package com.xuxueli.executor.sample.frameless.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * 跨平台Http任务 + * + * @author xuxueli 2018-09-16 03:48:34 + */ +public class HttpJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + + // valid + if (param==null || param.trim().length()==0) { + XxlJobLogger.log("URL Empty"); + return FAIL; + } + + // request + HttpURLConnection connection = null; + BufferedReader bufferedReader = null; + try { + // connection + URL realUrl = new URL(param); + connection = (HttpURLConnection) realUrl.openConnection(); + + // connection setting + connection.setRequestMethod("GET"); + connection.setDoOutput(true); + 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(); + + //Map<String, List<String>> map = connection.getHeaderFields(); + + // 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(); + + XxlJobLogger.log(responseMsg); + return SUCCESS; + } catch (Exception e) { + XxlJobLogger.log(e); + return FAIL; + } finally { + try { + if (bufferedReader != null) { + bufferedReader.close(); + } + if (connection != null) { + connection.disconnect(); + } + } catch (Exception e2) { + XxlJobLogger.log(e2); + } + } + + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/ShardingJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/ShardingJobHandler.java new file mode 100644 index 0000000..b45a24e --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/ShardingJobHandler.java @@ -0,0 +1,34 @@ +package com.xuxueli.executor.sample.frameless.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; +import com.xxl.job.core.util.ShardingUtil; + +/** + * 分片广播任务 + * + * @author xuxueli 2017-07-25 20:56:50 + */ +public class ShardingJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + + // 分片参数 + ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo(); + XxlJobLogger.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardingVO.getIndex(), shardingVO.getTotal()); + + // 业务逻辑 + for (int i = 0; i < shardingVO.getTotal(); i++) { + if (i == shardingVO.getIndex()) { + XxlJobLogger.log("第 {} 片, 命中分片开始处理", i); + } else { + XxlJobLogger.log("第 {} 片, 忽略", i); + } + } + + return SUCCESS; + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/resources/log4j.xml b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/resources/log4j.xml new file mode 100644 index 0000000..896517e --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/resources/log4j.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd"> +<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" threshold="null" debug="null"> + + <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> + <param name="Target" value="System.out" /> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-executor-sample-frameless [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/> + </layout> + </appender> + + <appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender"> + <param name="file" value="/data/applogs/xxl-job/xxl-job-executor-sample-frameless.log"/> + <param name="append" value="true"/> + <param name="encoding" value="UTF-8"/> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-executor-sample-frameless [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/> + </layout> + </appender> + + <root> + <level value="INFO" /> + <appender-ref ref="CONSOLE" /> + <appender-ref ref="FILE" /> + </root> + +</log4j:configuration>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/resources/xxl-job-executor.properties b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/resources/xxl-job-executor.properties new file mode 100644 index 0000000..72274ee --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/resources/xxl-job-executor.properties @@ -0,0 +1,15 @@ +### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" +xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin + +### xxl-job executor address +xxl.job.executor.appname=xxl-job-executor-sample +xxl.job.executor.ip= +xxl.job.executor.port=9994 + +### xxl-job, access token +xxl.job.accessToken= + +### xxl-job log path +xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler +### xxl-job log retention days +xxl.job.executor.logretentiondays=30 diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-frameless/xxl-job-executor-sample-frameless.iml b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/xxl-job-executor-sample-frameless.iml new file mode 100644 index 0000000..df91b9a --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-frameless/xxl-job-executor-sample-frameless.iml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7"> + <output url="file://$MODULE_DIR$/target/classes" /> + <output-test url="file://$MODULE_DIR$/target/test-classes" /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> + <excludeFolder url="file://$MODULE_DIR$/target" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="library" name="Maven: org.slf4j:slf4j-log4j12:1.7.29" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.29" level="project" /> + <orderEntry type="library" name="Maven: log4j:log4j:1.2.17" level="project" /> + <orderEntry type="module" module-name="xxl-job-core" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-rpc-core:1.5.0" level="project" /> + <orderEntry type="library" name="Maven: io.netty:netty-all:4.1.43.Final" level="project" /> + <orderEntry type="library" name="Maven: com.caucho:hessian:4.0.63" level="project" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-registry-client:1.1.0" level="project" /> + <orderEntry type="library" name="Maven: org.codehaus.groovy:groovy:2.5.8" level="project" /> + </component> +</module>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/pom.xml b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/pom.xml new file mode 100644 index 0000000..8c2a5db --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/pom.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-executor-samples</artifactId> + <version>2.2.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>xxl-job-executor-sample-jboot</artifactId> + <packaging>jar</packaging> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + </properties> + + <dependencies> + <!-- jboot --> + <dependency> + <groupId>io.jboot</groupId> + <artifactId>jboot</artifactId> + <version>2.0.9</version> + </dependency> + + <!-- xxl-job-core --> + <dependency> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-core</artifactId> + <version>${project.parent.version}</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-core</artifactId> + <version>1.1.11</version> + </dependency> + + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <version>1.1.11</version> + </dependency> + + </dependencies> + +</project> diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/JbootApp.java b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/JbootApp.java new file mode 100644 index 0000000..79e2b7a --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/JbootApp.java @@ -0,0 +1,12 @@ +package com.xuxueli.executor.sample.jboot; + +import io.jboot.app.JbootApplication; + +/** + * Jboot app + */ +public class JbootApp { + public static void main(String[] args) { + JbootApplication.run(args); + } +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/config/JbootConfig.java b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/config/JbootConfig.java new file mode 100644 index 0000000..0f58c34 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/config/JbootConfig.java @@ -0,0 +1,64 @@ +package com.xuxueli.executor.sample.jboot.config; + +import com.xuxueli.executor.sample.jboot.jobhandler.CommandJobHandler; +import com.xuxueli.executor.sample.jboot.jobhandler.DemoJobHandler; +import com.xuxueli.executor.sample.jboot.jobhandler.HttpJobHandler; +import com.xuxueli.executor.sample.jboot.jobhandler.ShardingJobHandler; +import com.xxl.job.core.executor.XxlJobExecutor; +import io.jboot.Jboot; +import io.jboot.core.listener.JbootAppListenerBase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class JbootConfig extends JbootAppListenerBase { + private Logger logger = LoggerFactory.getLogger(JbootConfig.class); + + // ---------------------- xxl-job executor ---------------------- + private XxlJobExecutor xxlJobExecutor = null; + + private void initXxlJobExecutor() { + + // registry jobhandler + XxlJobExecutor.registJobHandler("demoJobHandler", new DemoJobHandler()); + XxlJobExecutor.registJobHandler("shardingJobHandler", new ShardingJobHandler()); + XxlJobExecutor.registJobHandler("httpJobHandler", new HttpJobHandler()); + XxlJobExecutor.registJobHandler("commandJobHandler", new CommandJobHandler()); + + // init executor + xxlJobExecutor = new XxlJobExecutor(); + xxlJobExecutor.setAdminAddresses(Jboot.configValue("xxl.job.admin.addresses")); + xxlJobExecutor.setAppName(Jboot.configValue("xxl.job.executor.appname")); + xxlJobExecutor.setIp(Jboot.configValue("xxl.job.executor.ip")); + xxlJobExecutor.setPort(Integer.valueOf(Jboot.configValue("xxl.job.executor.port"))); + xxlJobExecutor.setAccessToken(Jboot.configValue("xxl.job.accessToken")); + xxlJobExecutor.setLogPath(Jboot.configValue("xxl.job.executor.logpath")); + xxlJobExecutor.setLogRetentionDays(Integer.valueOf(Jboot.configValue("xxl.job.executor.logretentiondays"))); + + // start executor + try { + xxlJobExecutor.start(); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + + // ---------------------- jboot ---------------------- + + private void destoryXxlJobExecutor() { + if (xxlJobExecutor != null) { + xxlJobExecutor.destroy(); + } + } + + @Override + public void onStart() { + initXxlJobExecutor(); + super.onStart(); + } + + @Override + public void onStop() { + destoryXxlJobExecutor(); + super.onStop(); + } +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/controller/IndexController.java b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/controller/IndexController.java new file mode 100644 index 0000000..f7a8597 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/controller/IndexController.java @@ -0,0 +1,14 @@ +package com.xuxueli.executor.sample.jboot.controller; + +import io.jboot.web.controller.JbootController; +import io.jboot.web.controller.annotation.RequestMapping; + + +@RequestMapping("/") +public class IndexController extends JbootController { + + public void index() { + renderText("xxl job executor running."); + } + +}
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/CommandJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/CommandJobHandler.java new file mode 100644 index 0000000..a73e19a --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/CommandJobHandler.java @@ -0,0 +1,54 @@ +package com.xuxueli.executor.sample.jboot.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.InputStreamReader; + +/** + * 命令行任务 + * + * @author xuxueli 2018-09-16 03:48:34 + */ +public class CommandJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + String command = param; + int exitValue = -1; + + BufferedReader bufferedReader = null; + try { + // command process + 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) { + XxlJobLogger.log(line); + } + + // command exit + process.waitFor(); + exitValue = process.exitValue(); + } catch (Exception e) { + XxlJobLogger.log(e); + } finally { + if (bufferedReader != null) { + bufferedReader.close(); + } + } + + if (exitValue == 0) { + return IJobHandler.SUCCESS; + } else { + return new ReturnT<String>(IJobHandler.FAIL.getCode(), "command exit value("+exitValue+") is failed"); + } + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/DemoJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/DemoJobHandler.java new file mode 100644 index 0000000..baf7e88 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/DemoJobHandler.java @@ -0,0 +1,32 @@ +package com.xuxueli.executor.sample.jboot.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.util.concurrent.TimeUnit; + +/** + * 任务Handler示例(Bean模式) + * + * 开发步骤: + * 1、继承"IJobHandler":“com.xxl.job.core.handler.IJobHandler”; + * 2、注册到执行器工厂:在 "JFinalCoreConfig.initXxlJobExecutor" 中手动注册,注解key值对应的是调度中心新建任务的JobHandler属性的值。 + * 3、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志; + * + * @author xuxueli 2015-12-19 19:43:36 + */ +public class DemoJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + XxlJobLogger.log("XXL-JOB, Hello World."); + + for (int i = 0; i < 5; i++) { + XxlJobLogger.log("beat at:" + i); + TimeUnit.SECONDS.sleep(2); + } + return SUCCESS; + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/HttpJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/HttpJobHandler.java new file mode 100644 index 0000000..2796ecd --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/HttpJobHandler.java @@ -0,0 +1,81 @@ +package com.xuxueli.executor.sample.jboot.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * 跨平台Http任务 + * + * @author xuxueli 2018-09-16 03:48:34 + */ +public class HttpJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + + // request + HttpURLConnection connection = null; + BufferedReader bufferedReader = null; + try { + // connection + URL realUrl = new URL(param); + connection = (HttpURLConnection) realUrl.openConnection(); + + // connection setting + connection.setRequestMethod("GET"); + connection.setDoOutput(true); + 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(); + + //Map<String, List<String>> map = connection.getHeaderFields(); + + // 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(); + + XxlJobLogger.log(responseMsg); + return SUCCESS; + } catch (Exception e) { + XxlJobLogger.log(e); + return FAIL; + } finally { + try { + if (bufferedReader != null) { + bufferedReader.close(); + } + if (connection != null) { + connection.disconnect(); + } + } catch (Exception e2) { + XxlJobLogger.log(e2); + } + } + + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/ShardingJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/ShardingJobHandler.java new file mode 100644 index 0000000..8eb70aa --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/java/com/xuxueli/executor/sample/jboot/jobhandler/ShardingJobHandler.java @@ -0,0 +1,34 @@ +package com.xuxueli.executor.sample.jboot.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; +import com.xxl.job.core.util.ShardingUtil; + +/** + * 分片广播任务 + * + * @author xuxueli 2017-07-25 20:56:50 + */ +public class ShardingJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + + // 分片参数 + ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo(); + XxlJobLogger.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardingVO.getIndex(), shardingVO.getTotal()); + + // 业务逻辑 + for (int i = 0; i < shardingVO.getTotal(); i++) { + if (i == shardingVO.getIndex()) { + XxlJobLogger.log("第 {} 片, 命中分片开始处理", i); + } else { + XxlJobLogger.log("第 {} 片, 忽略", i); + } + } + + return SUCCESS; + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/resources/jboot.properties b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/resources/jboot.properties new file mode 100644 index 0000000..2fa683c --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/resources/jboot.properties @@ -0,0 +1,19 @@ +#jboot port +undertow.port=8082 + + +### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" +xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin + +### xxl-job executor address +xxl.job.executor.appname=xxl-job-executor-sample +xxl.job.executor.ip= +xxl.job.executor.port=9995 + +### xxl-job, access token +xxl.job.accessToken= + +### xxl-job log path +xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler +### xxl-job log retention days +xxl.job.executor.logretentiondays=30
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/resources/logback.xml b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/resources/logback.xml new file mode 100644 index 0000000..e560605 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/main/resources/logback.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration debug="false" scan="true" scanPeriod="1 seconds"> + + <contextName>logback</contextName> + <property name="log.path" value="/data/applogs/xxl-job/xxl-job-executor-sample-jboot.log"/> + + <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${log.path}</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern> + </rollingPolicy> + <encoder> + <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n + </pattern> + </encoder> + </appender> + + <root level="info"> + <appender-ref ref="console"/> + <appender-ref ref="file"/> + </root> + +</configuration>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/test/java/com/xuxueli/AppTest.java b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/test/java/com/xuxueli/AppTest.java new file mode 100644 index 0000000..470feac --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/src/test/java/com/xuxueli/AppTest.java @@ -0,0 +1,18 @@ +package com.xuxueli; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Unit test for simple App. + */ +public class AppTest { + /** + * Rigorous Test :-) + */ + @Test + public void shouldAnswerWithTrue() { + assertTrue(true); + } +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jboot/xxl-job-executor-sample-jboot.iml b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/xxl-job-executor-sample-jboot.iml new file mode 100644 index 0000000..b09bcc9 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jboot/xxl-job-executor-sample-jboot.iml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8"> + <output url="file://$MODULE_DIR$/target/classes" /> + <output-test url="file://$MODULE_DIR$/target/test-classes" /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> + <excludeFolder url="file://$MODULE_DIR$/target" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="library" name="Maven: io.jboot:jboot:2.0.9" level="project" /> + <orderEntry type="library" name="Maven: com.jfinal:jfinal:3.8" level="project" /> + <orderEntry type="library" name="Maven: cglib:cglib-nodep:3.2.5" level="project" /> + <orderEntry type="library" name="Maven: com.jfinal:cos:2017.5" level="project" /> + <orderEntry type="library" name="Maven: com.jfinal:jfinal-weixin:2.3" level="project" /> + <orderEntry type="library" name="Maven: com.jfinal:jfinal-undertow:1.6" level="project" /> + <orderEntry type="library" name="Maven: io.undertow:undertow-core:2.0.19.Final" level="project" /> + <orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.2.Final" level="project" /> + <orderEntry type="library" name="Maven: org.jboss.xnio:xnio-api:3.3.8.Final" level="project" /> + <orderEntry type="library" scope="RUNTIME" name="Maven: org.jboss.xnio:xnio-nio:3.3.8.Final" level="project" /> + <orderEntry type="library" name="Maven: io.undertow:undertow-servlet:2.0.19.Final" level="project" /> + <orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:4.0.1" level="project" /> + <orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.3.1" level="project" /> + <orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.47" level="project" /> + <orderEntry type="library" name="Maven: io.undertow:undertow-websockets-jsr:2.0.19.Final" level="project" /> + <orderEntry type="library" name="Maven: org.jboss.spec.javax.websocket:jboss-websocket-api_1.1_spec:1.1.3.Final" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" /> + <orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.57" level="project" /> + <orderEntry type="library" name="Maven: net.sf.trove4j:core:3.1.0" level="project" /> + <orderEntry type="library" name="Maven: com.google.guava:guava:27.1-jre" level="project" /> + <orderEntry type="library" name="Maven: com.google.guava:failureaccess:1.0.1" level="project" /> + <orderEntry type="library" name="Maven: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" level="project" /> + <orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" /> + <orderEntry type="library" name="Maven: org.checkerframework:checker-qual:2.5.2" level="project" /> + <orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.2.0" level="project" /> + <orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.1" level="project" /> + <orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.17" level="project" /> + <orderEntry type="library" name="Maven: it.sauronsoftware.cron4j:cron4j:2.2.5" level="project" /> + <orderEntry type="library" name="Maven: redis.clients:jedis:2.10.1" level="project" /> + <orderEntry type="library" name="Maven: org.apache.commons:commons-pool2:2.4.3" level="project" /> + <orderEntry type="library" name="Maven: de.ruedigermoeller:fst:2.57" level="project" /> + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.8.8" level="project" /> + <orderEntry type="library" name="Maven: org.javassist:javassist:3.21.0-GA" level="project" /> + <orderEntry type="library" name="Maven: org.objenesis:objenesis:2.5.1" level="project" /> + <orderEntry type="library" name="Maven: org.jsoup:jsoup:1.11.3" level="project" /> + <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache:2.10.6" level="project" /> + <orderEntry type="library" name="Maven: io.dropwizard.metrics:metrics-core:4.0.5" level="project" /> + <orderEntry type="library" name="Maven: io.shardingsphere:sharding-jdbc-core:3.1.0" level="project" /> + <orderEntry type="library" name="Maven: io.shardingsphere:sharding-core:3.1.0" level="project" /> + <orderEntry type="library" name="Maven: org.codehaus.groovy:groovy:indy:2.4.5" level="project" /> + <orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.16" level="project" /> + <orderEntry type="library" name="Maven: org.antlr:antlr4:4.7.1" level="project" /> + <orderEntry type="library" name="Maven: org.antlr:antlr4-runtime:4.7.1" level="project" /> + <orderEntry type="library" name="Maven: org.antlr:antlr-runtime:3.5.2" level="project" /> + <orderEntry type="library" name="Maven: org.antlr:ST4:4.0.8" level="project" /> + <orderEntry type="library" name="Maven: org.abego.treelayout:org.abego.treelayout.core:1.0.3" level="project" /> + <orderEntry type="library" name="Maven: org.glassfish:javax.json:1.0.4" level="project" /> + <orderEntry type="library" name="Maven: com.ibm.icu:icu4j:58.2" level="project" /> + <orderEntry type="library" name="Maven: io.shardingsphere:sharding-transaction-core:3.1.0" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.7" level="project" /> + <orderEntry type="library" name="Maven: io.dropwizard.metrics:metrics-servlets:4.0.5" level="project" /> + <orderEntry type="library" name="Maven: io.dropwizard.metrics:metrics-healthchecks:4.0.5" level="project" /> + <orderEntry type="library" name="Maven: io.dropwizard.metrics:metrics-json:4.0.5" level="project" /> + <orderEntry type="library" name="Maven: io.dropwizard.metrics:metrics-jvm:4.0.5" level="project" /> + <orderEntry type="library" name="Maven: com.papertrail:profiler:1.0.2" level="project" /> + <orderEntry type="library" name="Maven: joda-time:joda-time:2.9.1" level="project" /> + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.5" level="project" /> + <orderEntry type="library" name="Maven: com.alibaba:dubbo:2.6.6" level="project" /> + <orderEntry type="library" name="Maven: org.jboss.netty:netty:3.2.5.Final" level="project" /> + <orderEntry type="library" name="Maven: org.apache.curator:curator-framework:4.1.0" level="project" /> + <orderEntry type="library" name="Maven: org.apache.curator:curator-client:4.1.0" level="project" /> + <orderEntry type="library" name="Maven: org.apache.zookeeper:zookeeper:3.5.4-beta" level="project" /> + <orderEntry type="library" name="Maven: commons-cli:commons-cli:1.2" level="project" /> + <orderEntry type="library" name="Maven: log4j:log4j:1.2.17" level="project" /> + <orderEntry type="library" name="Maven: org.apache.yetus:audience-annotations:0.5.0" level="project" /> + <orderEntry type="library" name="Maven: io.netty:netty:3.10.6.Final" level="project" /> + <orderEntry type="library" name="Maven: io.jsonwebtoken:jjwt:0.9.1" level="project" /> + <orderEntry type="library" name="Maven: io.swagger:swagger-core:1.5.21" level="project" /> + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.5" level="project" /> + <orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.9.5" level="project" /> + <orderEntry type="library" name="Maven: io.swagger:swagger-models:1.5.21" level="project" /> + <orderEntry type="library" name="Maven: io.swagger:swagger-annotations:1.5.21" level="project" /> + <orderEntry type="library" name="Maven: javax.validation:validation-api:1.1.0.Final" level="project" /> + <orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.8.1" level="project" /> + <orderEntry type="library" name="Maven: commons-io:commons-io:2.6" level="project" /> + <orderEntry type="library" name="Maven: io.seata:seata-config-core:0.5.1" level="project" /> + <orderEntry type="library" name="Maven: io.seata:seata-common:0.5.1" level="project" /> + <orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" /> + <orderEntry type="library" name="Maven: com.typesafe:config:1.2.1" level="project" /> + <orderEntry type="module" module-name="xxl-job-core" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-rpc-core:1.5.0" level="project" /> + <orderEntry type="library" name="Maven: io.netty:netty-all:4.1.43.Final" level="project" /> + <orderEntry type="library" name="Maven: com.caucho:hessian:4.0.63" level="project" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-registry-client:1.1.0" level="project" /> + <orderEntry type="library" name="Maven: org.codehaus.groovy:groovy:2.5.8" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.11" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" /> + <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.1.11" level="project" /> + <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.1.11" level="project" /> + </component> +</module>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/pom.xml b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/pom.xml new file mode 100644 index 0000000..aa82229 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/pom.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-executor-samples</artifactId> + <version>2.2.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>xxl-job-executor-sample-jfinal</artifactId> + <packaging>war</packaging> + + <dependencies> + <!-- jfinal --> + <dependency> + <groupId>com.jfinal</groupId> + <artifactId>jfinal</artifactId> + <version>2.2</version> + </dependency> + + <!-- slf4j --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>${slf4j-api.version}</version> + </dependency> + + <!-- xxl-job --> + <dependency> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-core</artifactId> + <version>${project.parent.version}</version> + </dependency> + + </dependencies> + +</project>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/config/JFinalCoreConfig.java b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/config/JFinalCoreConfig.java new file mode 100644 index 0000000..4dff38f --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/config/JFinalCoreConfig.java @@ -0,0 +1,90 @@ +package com.xuxueli.executor.sample.jfinal.config; + +import com.jfinal.config.*; +import com.jfinal.kit.Prop; +import com.jfinal.kit.PropKit; +import com.xuxueli.executor.sample.jfinal.controller.IndexController; +import com.xuxueli.executor.sample.jfinal.jobhandler.CommandJobHandler; +import com.xuxueli.executor.sample.jfinal.jobhandler.DemoJobHandler; +import com.xuxueli.executor.sample.jfinal.jobhandler.HttpJobHandler; +import com.xuxueli.executor.sample.jfinal.jobhandler.ShardingJobHandler; +import com.xxl.job.core.executor.XxlJobExecutor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author xuxueli 2017-08-11 14:17:41 + */ +public class JFinalCoreConfig extends JFinalConfig { + private Logger logger = LoggerFactory.getLogger(JFinalCoreConfig.class); + + // ---------------------- xxl-job executor ---------------------- + private XxlJobExecutor xxlJobExecutor = null; + private void initXxlJobExecutor() { + + // registry jobhandler + XxlJobExecutor.registJobHandler("demoJobHandler", new DemoJobHandler()); + XxlJobExecutor.registJobHandler("shardingJobHandler", new ShardingJobHandler()); + XxlJobExecutor.registJobHandler("httpJobHandler", new HttpJobHandler()); + XxlJobExecutor.registJobHandler("commandJobHandler", new CommandJobHandler()); + + // load executor prop + Prop xxlJobProp = PropKit.use("xxl-job-executor.properties"); + + // init executor + xxlJobExecutor = new XxlJobExecutor(); + xxlJobExecutor.setAdminAddresses(xxlJobProp.get("xxl.job.admin.addresses")); + xxlJobExecutor.setAppName(xxlJobProp.get("xxl.job.executor.appname")); + xxlJobExecutor.setIp(xxlJobProp.get("xxl.job.executor.ip")); + xxlJobExecutor.setPort(xxlJobProp.getInt("xxl.job.executor.port")); + xxlJobExecutor.setAccessToken(xxlJobProp.get("xxl.job.accessToken")); + xxlJobExecutor.setLogPath(xxlJobProp.get("xxl.job.executor.logpath")); + xxlJobExecutor.setLogRetentionDays(xxlJobProp.getInt("xxl.job.executor.logretentiondays")); + + // start executor + try { + xxlJobExecutor.start(); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + private void destoryXxlJobExecutor() { + if (xxlJobExecutor != null) { + xxlJobExecutor.destroy(); + } + } + + // ---------------------- jfinal ---------------------- + + public void configRoute(Routes route) { + route.add("/", IndexController.class); + } + + @Override + public void afterJFinalStart() { + initXxlJobExecutor(); + } + + @Override + public void beforeJFinalStop() { + destoryXxlJobExecutor(); + } + + public void configConstant(Constants constants) { + + } + + public void configPlugin(Plugins plugins) { + + } + + public void configInterceptor(Interceptors interceptors) { + + } + + public void configHandler(Handlers handlers) { + + } + + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/controller/IndexController.java b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/controller/IndexController.java new file mode 100644 index 0000000..2c47b73 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/controller/IndexController.java @@ -0,0 +1,11 @@ +package com.xuxueli.executor.sample.jfinal.controller; + +import com.jfinal.core.Controller; + +public class IndexController extends Controller { + + public void index(){ + renderText("xxl job executor running."); + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/CommandJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/CommandJobHandler.java new file mode 100644 index 0000000..b6646d2 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/CommandJobHandler.java @@ -0,0 +1,54 @@ +package com.xuxueli.executor.sample.jfinal.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.InputStreamReader; + +/** + * 命令行任务 + * + * @author xuxueli 2018-09-16 03:48:34 + */ +public class CommandJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + String command = param; + int exitValue = -1; + + BufferedReader bufferedReader = null; + try { + // command process + 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) { + XxlJobLogger.log(line); + } + + // command exit + process.waitFor(); + exitValue = process.exitValue(); + } catch (Exception e) { + XxlJobLogger.log(e); + } finally { + if (bufferedReader != null) { + bufferedReader.close(); + } + } + + if (exitValue == 0) { + return IJobHandler.SUCCESS; + } else { + return new ReturnT<String>(IJobHandler.FAIL.getCode(), "command exit value("+exitValue+") is failed"); + } + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/DemoJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/DemoJobHandler.java new file mode 100644 index 0000000..bf4e888 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/DemoJobHandler.java @@ -0,0 +1,32 @@ +package com.xuxueli.executor.sample.jfinal.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.util.concurrent.TimeUnit; + +/** + * 任务Handler示例(Bean模式) + * + * 开发步骤: + * 1、继承"IJobHandler":“com.xxl.job.core.handler.IJobHandler”; + * 2、注册到执行器工厂:在 "JFinalCoreConfig.initXxlJobExecutor" 中手动注册,注解key值对应的是调度中心新建任务的JobHandler属性的值。 + * 3、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志; + * + * @author xuxueli 2015-12-19 19:43:36 + */ +public class DemoJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + XxlJobLogger.log("XXL-JOB, Hello World."); + + for (int i = 0; i < 5; i++) { + XxlJobLogger.log("beat at:" + i); + TimeUnit.SECONDS.sleep(2); + } + return SUCCESS; + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/HttpJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/HttpJobHandler.java new file mode 100644 index 0000000..b8b61f9 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/HttpJobHandler.java @@ -0,0 +1,81 @@ +package com.xuxueli.executor.sample.jfinal.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * 跨平台Http任务 + * + * @author xuxueli 2018-09-16 03:48:34 + */ +public class HttpJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + + // request + HttpURLConnection connection = null; + BufferedReader bufferedReader = null; + try { + // connection + URL realUrl = new URL(param); + connection = (HttpURLConnection) realUrl.openConnection(); + + // connection setting + connection.setRequestMethod("GET"); + connection.setDoOutput(true); + 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(); + + //Map<String, List<String>> map = connection.getHeaderFields(); + + // 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(); + + XxlJobLogger.log(responseMsg); + return SUCCESS; + } catch (Exception e) { + XxlJobLogger.log(e); + return FAIL; + } finally { + try { + if (bufferedReader != null) { + bufferedReader.close(); + } + if (connection != null) { + connection.disconnect(); + } + } catch (Exception e2) { + XxlJobLogger.log(e2); + } + } + + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/ShardingJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/ShardingJobHandler.java new file mode 100644 index 0000000..bb3fa2c --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/ShardingJobHandler.java @@ -0,0 +1,34 @@ +package com.xuxueli.executor.sample.jfinal.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; +import com.xxl.job.core.util.ShardingUtil; + +/** + * 分片广播任务 + * + * @author xuxueli 2017-07-25 20:56:50 + */ +public class ShardingJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + + // 分片参数 + ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo(); + XxlJobLogger.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardingVO.getIndex(), shardingVO.getTotal()); + + // 业务逻辑 + for (int i = 0; i < shardingVO.getTotal(); i++) { + if (i == shardingVO.getIndex()) { + XxlJobLogger.log("第 {} 片, 命中分片开始处理", i); + } else { + XxlJobLogger.log("第 {} 片, 忽略", i); + } + } + + return SUCCESS; + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/resources/log4j.xml b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/resources/log4j.xml new file mode 100644 index 0000000..5a0c547 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/resources/log4j.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd"> +<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" threshold="null" debug="null"> + + <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> + <param name="Target" value="System.out" /> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-executor-sample-jfinal [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/> + </layout> + </appender> + + <appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender"> + <param name="file" value="/data/applogs/xxl-job/xxl-job-executor-sample-jfinal.log"/> + <param name="append" value="true"/> + <param name="encoding" value="UTF-8"/> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-executor-sample-jfinal [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/> + </layout> + </appender> + + <root> + <level value="INFO" /> + <appender-ref ref="CONSOLE" /> + <appender-ref ref="FILE" /> + </root> + +</log4j:configuration>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/resources/xxl-job-executor.properties b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/resources/xxl-job-executor.properties new file mode 100644 index 0000000..ff8614b --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/resources/xxl-job-executor.properties @@ -0,0 +1,15 @@ +### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" +xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin + +### xxl-job executor address +xxl.job.executor.appname=xxl-job-executor-sample +xxl.job.executor.ip= +xxl.job.executor.port=9996 + +### xxl-job, access token +xxl.job.accessToken= + +### xxl-job log path +xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler +### xxl-job log retention days +xxl.job.executor.logretentiondays=30 diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/webapp/WEB-INF/web.xml b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..208179c --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" + id="WebApp_ID" version="2.5"> + + <display-name>xxl-job-executor-sample-jfinal</display-name> + <context-param> + <param-name>webAppRootKey</param-name> + <param-value>xxl-job-executor-sample-jfinal</param-value> + </context-param> + + <!-- jfinal --> + <filter> + <filter-name>jfinal</filter-name> + <filter-class>com.jfinal.core.JFinalFilter</filter-class> + <init-param> + <param-name>configClass</param-name> + <param-value>com.xuxueli.executor.sample.jfinal.config.JFinalCoreConfig</param-value> + </init-param> + </filter> + <filter-mapping> + <filter-name>jfinal</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + + + <welcome-file-list> + <welcome-file>index.html</welcome-file> + </welcome-file-list> + +</web-app>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/webapp/index.html b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/webapp/index.html new file mode 100644 index 0000000..7085239 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/webapp/index.html @@ -0,0 +1 @@ +i am alive.
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/xxl-job-executor-sample-jfinal.iml b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/xxl-job-executor-sample-jfinal.iml new file mode 100644 index 0000000..adc96b7 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-jfinal/xxl-job-executor-sample-jfinal.iml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> + <component name="FacetManager"> + <facet type="web" name="Web"> + <configuration> + <descriptors> + <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/main/webapp/WEB-INF/web.xml" /> + </descriptors> + <webroots> + <root url="file://$MODULE_DIR$/src/main/webapp" relative="/" /> + </webroots> + </configuration> + </facet> + </component> + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7"> + <output url="file://$MODULE_DIR$/target/classes" /> + <output-test url="file://$MODULE_DIR$/target/test-classes" /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> + <excludeFolder url="file://$MODULE_DIR$/target" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="library" name="Maven: com.jfinal:jfinal:2.2" level="project" /> + <orderEntry type="library" name="Maven: cglib:cglib-nodep:3.1" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:slf4j-log4j12:1.7.29" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.29" level="project" /> + <orderEntry type="library" name="Maven: log4j:log4j:1.2.17" level="project" /> + <orderEntry type="module" module-name="xxl-job-core" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-rpc-core:1.5.0" level="project" /> + <orderEntry type="library" name="Maven: io.netty:netty-all:4.1.43.Final" level="project" /> + <orderEntry type="library" name="Maven: com.caucho:hessian:4.0.63" level="project" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-registry-client:1.1.0" level="project" /> + <orderEntry type="library" name="Maven: org.codehaus.groovy:groovy:2.5.8" level="project" /> + </component> +</module>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/pom.xml b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/pom.xml new file mode 100644 index 0000000..fcd72d9 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/pom.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-executor-samples</artifactId> + <version>2.2.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>xxl-job-executor-sample-nutz</artifactId> + <packaging>war</packaging> + + <dependencies> + <!-- nutz --> + <dependency> + <groupId>org.nutz</groupId> + <artifactId>nutz</artifactId> + <version>1.r.62</version> + </dependency> + + <!-- slf4j --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>${slf4j-api.version}</version> + </dependency> + + <!-- xxl-job --> + <dependency> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-core</artifactId> + <version>${project.parent.version}</version> + </dependency> + + </dependencies> + +</project>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/MainModule.java b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/MainModule.java new file mode 100644 index 0000000..a8163ff --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/MainModule.java @@ -0,0 +1,23 @@ +package com.xuxueli.executor.sample.nutz; + +import com.xuxueli.executor.sample.nutz.config.NutzSetup; +import org.nutz.mvc.annotation.*; +import org.nutz.mvc.ioc.provider.ComboIocProvider; + +/** + * nutz module + * + * @author xuxueli 2017-12-25 17:58:43 + */ +@IocBy(type = ComboIocProvider.class, + args = {"*org.nutz.ioc.loader.annotation.AnnotationIocLoader", + "com.xuxueli.executor.sample.nutz"}) +@Encoding(input = "utf-8", output = "utf-8") +@Modules(scanPackage = true) +@Localization("msg") +@Ok("json") +@Fail("json") +@SetupBy(NutzSetup.class) +public class MainModule { + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/config/NutzSetup.java b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/config/NutzSetup.java new file mode 100644 index 0000000..0077065 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/config/NutzSetup.java @@ -0,0 +1,61 @@ +package com.xuxueli.executor.sample.nutz.config; + +import com.xuxueli.executor.sample.nutz.jobhandler.CommandJobHandler; +import com.xuxueli.executor.sample.nutz.jobhandler.DemoJobHandler; +import com.xuxueli.executor.sample.nutz.jobhandler.HttpJobHandler; +import com.xuxueli.executor.sample.nutz.jobhandler.ShardingJobHandler; +import com.xxl.job.core.executor.XxlJobExecutor; +import org.nutz.ioc.impl.PropertiesProxy; +import org.nutz.mvc.NutConfig; +import org.nutz.mvc.Setup; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * nutz setup + * + * @author xuxueli 2017-12-25 17:58:43 + */ +public class NutzSetup implements Setup { + private Logger logger = LoggerFactory.getLogger(NutzSetup.class); + + private XxlJobExecutor xxlJobExecutor = null; + + @Override + public void init(NutConfig cfg) { + + // registry jobhandler + XxlJobExecutor.registJobHandler("demoJobHandler", new DemoJobHandler()); + XxlJobExecutor.registJobHandler("shardingJobHandler", new ShardingJobHandler()); + XxlJobExecutor.registJobHandler("httpJobHandler", new HttpJobHandler()); + XxlJobExecutor.registJobHandler("commandJobHandler", new CommandJobHandler()); + + // load executor prop + PropertiesProxy xxlJobProp = new PropertiesProxy("xxl-job-executor.properties"); + + // init executor + xxlJobExecutor = new XxlJobExecutor(); + xxlJobExecutor.setAdminAddresses(xxlJobProp.get("xxl.job.admin.addresses")); + xxlJobExecutor.setAppName(xxlJobProp.get("xxl.job.executor.appname")); + xxlJobExecutor.setIp(xxlJobProp.get("xxl.job.executor.ip")); + xxlJobExecutor.setPort(xxlJobProp.getInt("xxl.job.executor.port")); + xxlJobExecutor.setAccessToken(xxlJobProp.get("xxl.job.accessToken")); + xxlJobExecutor.setLogPath(xxlJobProp.get("xxl.job.executor.logpath")); + xxlJobExecutor.setLogRetentionDays(xxlJobProp.getInt("xxl.job.executor.logretentiondays")); + + // start executor + try { + xxlJobExecutor.start(); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + + @Override + public void destroy(NutConfig cfg) { + if (xxlJobExecutor != null) { + xxlJobExecutor.destroy(); + } + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/CommandJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/CommandJobHandler.java new file mode 100644 index 0000000..120180a --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/CommandJobHandler.java @@ -0,0 +1,54 @@ +package com.xuxueli.executor.sample.nutz.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.InputStreamReader; + +/** + * 命令行任务 + * + * @author xuxueli 2018-09-16 03:48:34 + */ +public class CommandJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + String command = param; + int exitValue = -1; + + BufferedReader bufferedReader = null; + try { + // command process + 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) { + XxlJobLogger.log(line); + } + + // command exit + process.waitFor(); + exitValue = process.exitValue(); + } catch (Exception e) { + XxlJobLogger.log(e); + } finally { + if (bufferedReader != null) { + bufferedReader.close(); + } + } + + if (exitValue == 0) { + return IJobHandler.SUCCESS; + } else { + return new ReturnT<String>(IJobHandler.FAIL.getCode(), "command exit value("+exitValue+") is failed"); + } + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/DemoJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/DemoJobHandler.java new file mode 100644 index 0000000..420c003 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/DemoJobHandler.java @@ -0,0 +1,34 @@ +package com.xuxueli.executor.sample.nutz.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.util.concurrent.TimeUnit; + +/** + * 任务Handler示例(Bean模式) + * + * 开发步骤: + * 1、继承"IJobHandler":“com.xxl.job.core.handler.IJobHandler”; + * 2、注册到Nutz容器:添加“@IocBean”注解,被Nutz容器扫描为Bean实例; + * 3、注册到执行器工厂:添加“@JobHandler(value="自定义jobhandler名称")”注解,注解value值对应的是调度中心新建任务的JobHandler属性的值。 + * 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志; + * + * @author xuxueli 2015-12-19 19:43:36 + */ +public class DemoJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + XxlJobLogger.log("XXL-JOB, Hello World."); + + for (int i = 0; i < 5; i++) { + XxlJobLogger.log("beat at:" + i); + TimeUnit.SECONDS.sleep(2); + } + return SUCCESS; + } + +} + diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/HttpJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/HttpJobHandler.java new file mode 100644 index 0000000..895afcc --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/HttpJobHandler.java @@ -0,0 +1,81 @@ +package com.xuxueli.executor.sample.nutz.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * 跨平台Http任务 + * + * @author xuxueli 2018-09-16 03:48:34 + */ +public class HttpJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + + // request + HttpURLConnection connection = null; + BufferedReader bufferedReader = null; + try { + // connection + URL realUrl = new URL(param); + connection = (HttpURLConnection) realUrl.openConnection(); + + // connection setting + connection.setRequestMethod("GET"); + connection.setDoOutput(true); + 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(); + + //Map<String, List<String>> map = connection.getHeaderFields(); + + // 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(); + + XxlJobLogger.log(responseMsg); + return SUCCESS; + } catch (Exception e) { + XxlJobLogger.log(e); + return FAIL; + } finally { + try { + if (bufferedReader != null) { + bufferedReader.close(); + } + if (connection != null) { + connection.disconnect(); + } + } catch (Exception e2) { + XxlJobLogger.log(e2); + } + } + + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/ShardingJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/ShardingJobHandler.java new file mode 100644 index 0000000..d01ab91 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/ShardingJobHandler.java @@ -0,0 +1,34 @@ +package com.xuxueli.executor.sample.nutz.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.log.XxlJobLogger; +import com.xxl.job.core.util.ShardingUtil; + +/** + * 分片广播任务 + * + * @author xuxueli 2017-07-25 20:56:50 + */ +public class ShardingJobHandler extends IJobHandler { + + @Override + public ReturnT<String> execute(String param) throws Exception { + + // 分片参数 + ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo(); + XxlJobLogger.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardingVO.getIndex(), shardingVO.getTotal()); + + // 业务逻辑 + for (int i = 0; i < shardingVO.getTotal(); i++) { + if (i == shardingVO.getIndex()) { + XxlJobLogger.log("第 {} 片, 命中分片开始处理", i); + } else { + XxlJobLogger.log("第 {} 片, 忽略", i); + } + } + + return SUCCESS; + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/module/IndexModule.java b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/module/IndexModule.java new file mode 100644 index 0000000..0cd0233 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/module/IndexModule.java @@ -0,0 +1,16 @@ +package com.xuxueli.executor.sample.nutz.module; + +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +@IocBean +public class IndexModule { + + @At("/") + @Ok("json") + public String index() { + return "xxl job executor running."; + } + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/resources/log4j.xml b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/resources/log4j.xml new file mode 100644 index 0000000..b9ba6ce --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/resources/log4j.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd"> +<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" threshold="null" debug="null"> + + <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> + <param name="Target" value="System.out" /> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-executor-sample-nutz [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/> + </layout> + </appender> + + <appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender"> + <param name="file" value="/data/applogs/xxl-job/xxl-job-executor-sample-nutz.log"/> + <param name="append" value="true"/> + <param name="encoding" value="UTF-8"/> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-executor-sample-nutz [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/> + </layout> + </appender> + + <root> + <level value="INFO" /> + <appender-ref ref="CONSOLE" /> + <appender-ref ref="FILE" /> + </root> + +</log4j:configuration>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/resources/xxl-job-executor.properties b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/resources/xxl-job-executor.properties new file mode 100644 index 0000000..973b4b3 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/resources/xxl-job-executor.properties @@ -0,0 +1,15 @@ +### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" +xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin + +### xxl-job executor address +xxl.job.executor.appname=xxl-job-executor-sample +xxl.job.executor.ip= +xxl.job.executor.port=9997 + +### xxl-job, access token +xxl.job.accessToken= + +### xxl-job log path +xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler +### xxl-job log retention days +xxl.job.executor.logretentiondays=30 diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/webapp/WEB-INF/web.xml b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..19f2817 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" + id="WebApp_ID" version="2.5"> + + <display-name>xxl-job-executor-sample-nutz</display-name> + <context-param> + <param-name>webAppRootKey</param-name> + <param-value>xxl-job-executor-sample-nutz</param-value> + </context-param> + + <!-- nutz --> + <filter> + <filter-name>nutz</filter-name> + <filter-class>org.nutz.mvc.NutFilter</filter-class> + <init-param> + <param-name>modules</param-name> + <param-value>com.xuxueli.executor.sample.nutz.MainModule</param-value> + </init-param> + </filter> + <filter-mapping> + <filter-name>nutz</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + + + <welcome-file-list> + <welcome-file>index.html</welcome-file> + </welcome-file-list> + +</web-app> diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/webapp/index.html b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/webapp/index.html new file mode 100644 index 0000000..7085239 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/webapp/index.html @@ -0,0 +1 @@ +i am alive.
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-nutz/xxl-job-executor-sample-nutz.iml b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/xxl-job-executor-sample-nutz.iml new file mode 100644 index 0000000..b24a256 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-nutz/xxl-job-executor-sample-nutz.iml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> + <component name="FacetManager"> + <facet type="web" name="Web"> + <configuration> + <descriptors> + <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/main/webapp/WEB-INF/web.xml" /> + </descriptors> + <webroots> + <root url="file://$MODULE_DIR$/src/main/webapp" relative="/" /> + </webroots> + </configuration> + </facet> + </component> + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7"> + <output url="file://$MODULE_DIR$/target/classes" /> + <output-test url="file://$MODULE_DIR$/target/test-classes" /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> + <excludeFolder url="file://$MODULE_DIR$/target" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="library" name="Maven: org.nutz:nutz:1.r.62" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:slf4j-log4j12:1.7.29" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.29" level="project" /> + <orderEntry type="library" name="Maven: log4j:log4j:1.2.17" level="project" /> + <orderEntry type="module" module-name="xxl-job-core" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-rpc-core:1.5.0" level="project" /> + <orderEntry type="library" name="Maven: io.netty:netty-all:4.1.43.Final" level="project" /> + <orderEntry type="library" name="Maven: com.caucho:hessian:4.0.63" level="project" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-registry-client:1.1.0" level="project" /> + <orderEntry type="library" name="Maven: org.codehaus.groovy:groovy:2.5.8" level="project" /> + </component> +</module>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-spring/pom.xml b/xxl-job-executor-samples/xxl-job-executor-sample-spring/pom.xml new file mode 100644 index 0000000..1e13ed7 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-spring/pom.xml @@ -0,0 +1,52 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-executor-samples</artifactId> + <version>2.2.0-SNAPSHOT</version> + </parent> + <artifactId>xxl-job-executor-sample-spring</artifactId> + <packaging>war</packaging> + + <name>${project.artifactId}</name> + <description>Executor project for spring boot.</description> + <url>https://www.xuxueli.com/</url> + + <dependencies> + <!-- spring-webmvc --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-webmvc</artifactId> + <version>${spring.version}</version> + </dependency> + + <!-- slf4j --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>${slf4j-api.version}</version> + </dependency> + + <!-- xxl-job-core --> + <dependency> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-core</artifactId> + <version>${project.parent.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <version>${maven-war-plugin.version}</version> + <configuration> + <archiveClasses>false</archiveClasses> + </configuration> + </plugin> + </plugins> + </build> + +</project>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java new file mode 100644 index 0000000..f87b777 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java @@ -0,0 +1,193 @@ +package com.xxl.job.executor.service.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.handler.annotation.XxlJob; +import com.xxl.job.core.log.XxlJobLogger; +import com.xxl.job.core.util.ShardingUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.TimeUnit; + +/** + * XxlJob开发示例(Bean模式) + * + * 开发步骤: + * 1、在Spring Bean实例中,开发Job方法,方式格式要求为 "public ReturnT<String> execute(String param)" + * 2、为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")",注解value值对应的是调度中心新建任务的JobHandler属性的值。 + * 3、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志; + * + * @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 ReturnT<String> demoJobHandler(String param) throws Exception { + XxlJobLogger.log("XXL-JOB, Hello World."); + + for (int i = 0; i < 5; i++) { + XxlJobLogger.log("beat at:" + i); + TimeUnit.SECONDS.sleep(2); + } + return ReturnT.SUCCESS; + } + + + /** + * 2、分片广播任务 + */ + @XxlJob("shardingJobHandler") + public ReturnT<String> shardingJobHandler(String param) throws Exception { + + // 分片参数 + ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo(); + XxlJobLogger.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardingVO.getIndex(), shardingVO.getTotal()); + + // 业务逻辑 + for (int i = 0; i < shardingVO.getTotal(); i++) { + if (i == shardingVO.getIndex()) { + XxlJobLogger.log("第 {} 片, 命中分片开始处理", i); + } else { + XxlJobLogger.log("第 {} 片, 忽略", i); + } + } + + return ReturnT.SUCCESS; + } + + + /** + * 3、命令行任务 + */ + @XxlJob("commandJobHandler") + public ReturnT<String> commandJobHandler(String param) throws Exception { + String command = param; + int exitValue = -1; + + BufferedReader bufferedReader = null; + try { + // command process + 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) { + XxlJobLogger.log(line); + } + + // command exit + process.waitFor(); + exitValue = process.exitValue(); + } catch (Exception e) { + XxlJobLogger.log(e); + } finally { + if (bufferedReader != null) { + bufferedReader.close(); + } + } + + if (exitValue == 0) { + return IJobHandler.SUCCESS; + } else { + return new ReturnT<String>(IJobHandler.FAIL.getCode(), "command exit value("+exitValue+") is failed"); + } + } + + + /** + * 4、跨平台Http任务 + */ + @XxlJob("httpJobHandler") + public ReturnT<String> httpJobHandler(String param) throws Exception { + + // request + HttpURLConnection connection = null; + BufferedReader bufferedReader = null; + try { + // connection + URL realUrl = new URL(param); + connection = (HttpURLConnection) realUrl.openConnection(); + + // connection setting + connection.setRequestMethod("GET"); + connection.setDoOutput(true); + 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(); + + //Map<String, List<String>> map = connection.getHeaderFields(); + + // 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(); + + XxlJobLogger.log(responseMsg); + return ReturnT.SUCCESS; + } catch (Exception e) { + XxlJobLogger.log(e); + return ReturnT.FAIL; + } finally { + try { + if (bufferedReader != null) { + bufferedReader.close(); + } + if (connection != null) { + connection.disconnect(); + } + } catch (Exception e2) { + XxlJobLogger.log(e2); + } + } + + } + + /** + * 5、生命周期任务示例:任务初始化与销毁时,支持自定义相关逻辑; + */ + @XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy") + public ReturnT<String> demoJobHandler2(String param) throws Exception { + XxlJobLogger.log("XXL-JOB, Hello World."); + return ReturnT.SUCCESS; + } + public void init(){ + logger.info("init"); + } + public void destroy(){ + logger.info("destory"); + } + + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/applicationcontext-xxl-job.xml b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/applicationcontext-xxl-job.xml new file mode 100644 index 0000000..0cfdfb8 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/applicationcontext-xxl-job.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context.xsd"> + + <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> + <property name="fileEncoding" value="utf-8" /> + <property name="locations"> + <list> + <value>classpath*:xxl-job-executor.properties</value> + </list> + </property> + </bean> + + <!-- ********************************* 基础配置 ********************************* --> + + <!-- 配置01、JobHandler 扫描路径 --> + <context:component-scan base-package="com.xxl.job.executor.service.jobhandler" /> + + <!-- 配置02、执行器 --> + <bean id="xxlJobSpringExecutor" class="com.xxl.job.core.executor.impl.XxlJobSpringExecutor" > + <!-- 执行器注册中心地址[选填],为空则关闭自动注册 --> + <property name="adminAddresses" value="${xxl.job.admin.addresses}" /> + <!-- 执行器AppName[选填],为空则关闭自动注册 --> + <property name="appName" value="${xxl.job.executor.appname}" /> + <!-- 执行器IP[选填],为空则自动获取 --> + <property name="ip" value="${xxl.job.executor.ip}" /> + <!-- 执行器端口号[选填],小于等于0则自动获取 --> + <property name="port" value="${xxl.job.executor.port}" /> + <!-- 访问令牌[选填],非空则进行匹配校验 --> + <property name="accessToken" value="${xxl.job.accessToken}" /> + <!-- 执行器日志路径[选填],为空则使用默认路径 --> + <property name="logPath" value="${xxl.job.executor.logpath}" /> + <!-- 日志保存天数[选填],值大于3时生效 --> + <property name="logRetentionDays" value="${xxl.job.executor.logretentiondays}" /> + </bean> + + +</beans>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/log4j.xml b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/log4j.xml new file mode 100644 index 0000000..f0a7fc6 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/log4j.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd"> +<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" threshold="null" debug="null"> + + <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> + <param name="Target" value="System.out" /> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-executor-sample-spring [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/> + </layout> + </appender> + + <appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender"> + <param name="file" value="/data/applogs/xxl-job/xxl-job-executor-sample-spring.log"/> + <param name="append" value="true"/> + <param name="encoding" value="UTF-8"/> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-executor-sample-spring [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/> + </layout> + </appender> + + <root> + <level value="INFO" /> + <appender-ref ref="CONSOLE" /> + <appender-ref ref="FILE" /> + </root> + + <!--<logger name="com.xxl.job.executor.service.jobhandler" additivity="false"> + <level value="INFO" /> + <appender-ref ref="CONSOLE" /> + <appender-ref ref="FILE" /> + </logger>--> + +</log4j:configuration>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/xxl-job-executor.properties b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/xxl-job-executor.properties new file mode 100644 index 0000000..4032e67 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/xxl-job-executor.properties @@ -0,0 +1,15 @@ +### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" +xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin + +### xxl-job executor address +xxl.job.executor.appname=xxl-job-executor-sample +xxl.job.executor.ip= +xxl.job.executor.port=9998 + +### xxl-job, access token +xxl.job.accessToken= + +### xxl-job log path +xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler +### xxl-job log retention days +xxl.job.executor.logretentiondays=30 diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/webapp/WEB-INF/web.xml b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..9179af7 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" + id="WebApp_ID" version="2.5"> + + <display-name>xxl-job-executor-sample-spring</display-name> + <context-param> + <param-name>webAppRootKey</param-name> + <param-value>xxl-job-executor-sample-spring</param-value> + </context-param> + + <!-- spring --> + <context-param> + <param-name>contextConfigLocation</param-name> + <param-value>classpath*:applicationcontext-*.xml</param-value> + </context-param> + + <listener> + <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> + </listener> + <listener> + <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> + </listener> + + + <welcome-file-list> + <welcome-file>index.html</welcome-file> + </welcome-file-list> + +</web-app>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/webapp/index.html b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/webapp/index.html new file mode 100644 index 0000000..7085239 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/webapp/index.html @@ -0,0 +1 @@ +i am alive.
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-spring/xxl-job-executor-sample-spring.iml b/xxl-job-executor-samples/xxl-job-executor-sample-spring/xxl-job-executor-sample-spring.iml new file mode 100644 index 0000000..77aee8b --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-spring/xxl-job-executor-sample-spring.iml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> + <component name="FacetManager"> + <facet type="web" name="Web"> + <configuration> + <descriptors> + <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/main/webapp/WEB-INF/web.xml" /> + </descriptors> + <webroots> + <root url="file://$MODULE_DIR$/src/main/webapp" relative="/" /> + </webroots> + </configuration> + </facet> + <facet type="Spring" name="Spring"> + <configuration /> + </facet> + </component> + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7"> + <output url="file://$MODULE_DIR$/target/classes" /> + <output-test url="file://$MODULE_DIR$/target/test-classes" /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> + <excludeFolder url="file://$MODULE_DIR$/target" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="library" name="Maven: org.springframework:spring-webmvc:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-aop:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-beans:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-context:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-core:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: commons-logging:commons-logging:1.2" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-expression:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-web:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:slf4j-log4j12:1.7.29" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.29" level="project" /> + <orderEntry type="library" name="Maven: log4j:log4j:1.2.17" level="project" /> + <orderEntry type="module" module-name="xxl-job-core" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-rpc-core:1.5.0" level="project" /> + <orderEntry type="library" name="Maven: io.netty:netty-all:4.1.43.Final" level="project" /> + <orderEntry type="library" name="Maven: com.caucho:hessian:4.0.63" level="project" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-registry-client:1.1.0" level="project" /> + <orderEntry type="library" name="Maven: org.codehaus.groovy:groovy:2.5.8" level="project" /> + </component> +</module>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/pom.xml b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/pom.xml new file mode 100644 index 0000000..e46f77e --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/pom.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-executor-samples</artifactId> + <version>2.2.0-SNAPSHOT</version> + </parent> + <artifactId>xxl-job-executor-sample-springboot</artifactId> + <packaging>jar</packaging> + + <name>${project.artifactId}</name> + <description>Example executor project for spring boot.</description> + <url>https://www.xuxueli.com/</url> + + <properties> + </properties> + + <dependencyManagement> + <dependencies> + <dependency> + <!-- Import dependency management from Spring Boot (依赖管理:继承一些默认的依赖,工程需要依赖的jar包的管理,申明其他dependency的时候就不需要version) --> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>${spring-boot.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <!-- spring-boot-starter-web (spring-webmvc + tomcat) --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + + <!-- xxl-job-core --> + <dependency> + <groupId>com.xuxueli</groupId> + <artifactId>xxl-job-core</artifactId> + <version>${project.parent.version}</version> + </dependency> + + </dependencies> + + <build> + <plugins> + <!-- spring-boot-maven-plugin (提供了直接运行项目的插件:如果是通过parent方式继承spring-boot-starter-parent则不用此插件) --> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <version>${spring-boot.version}</version> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + +</project>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/XxlJobExecutorApplication.java b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/XxlJobExecutorApplication.java new file mode 100644 index 0000000..d427acc --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/XxlJobExecutorApplication.java @@ -0,0 +1,16 @@ +package com.xxl.job.executor; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author xuxueli 2018-10-28 00:38:13 + */ +@SpringBootApplication +public class XxlJobExecutorApplication { + + public static void main(String[] args) { + SpringApplication.run(XxlJobExecutorApplication.class, args); + } + +}
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/core/config/XxlJobConfig.java b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/core/config/XxlJobConfig.java new file mode 100644 index 0000000..0ac3a3d --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/core/config/XxlJobConfig.java @@ -0,0 +1,74 @@ +package com.xxl.job.executor.core.config; + +import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * xxl-job config + * + * @author xuxueli 2017-04-28 + */ +@Configuration +public class XxlJobConfig { + private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class); + + @Value("${xxl.job.admin.addresses}") + private String adminAddresses; + + @Value("${xxl.job.executor.appname}") + private String appName; + + @Value("${xxl.job.executor.ip}") + private String ip; + + @Value("${xxl.job.executor.port}") + private int port; + + @Value("${xxl.job.accessToken}") + private String accessToken; + + @Value("${xxl.job.executor.logpath}") + private String logPath; + + @Value("${xxl.job.executor.logretentiondays}") + private int logRetentionDays; + + + @Bean + public XxlJobSpringExecutor xxlJobExecutor() { + logger.info(">>>>>>>>>>> xxl-job config init."); + XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); + xxlJobSpringExecutor.setAdminAddresses(adminAddresses); + xxlJobSpringExecutor.setAppName(appName); + xxlJobSpringExecutor.setIp(ip); + xxlJobSpringExecutor.setPort(port); + xxlJobSpringExecutor.setAccessToken(accessToken); + xxlJobSpringExecutor.setLogPath(logPath); + xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays); + + return xxlJobSpringExecutor; + } + + /** + * 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP; + * + * 1、引入依赖: + * <dependency> + * <groupId>org.springframework.cloud</groupId> + * <artifactId>spring-cloud-commons</artifactId> + * <version>${version}</version> + * </dependency> + * + * 2、配置文件,或者容器启动变量 + * spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.' + * + * 3、获取IP + * String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress(); + */ + + +}
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/mvc/controller/IndexController.java b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/mvc/controller/IndexController.java new file mode 100644 index 0000000..37c9071 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/mvc/controller/IndexController.java @@ -0,0 +1,18 @@ +//package com.xxl.job.executor.mvc.controller; +// +//import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +//import org.springframework.stereotype.Controller; +//import org.springframework.web.bind.annotation.RequestMapping; +//import org.springframework.web.bind.annotation.ResponseBody; +// +//@Controller +//@EnableAutoConfiguration +//public class IndexController { +// +// @RequestMapping("/") +// @ResponseBody +// String index() { +// return "xxl job executor running."; +// } +// +//}
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java new file mode 100644 index 0000000..b895bcf --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java @@ -0,0 +1,197 @@ +package com.xxl.job.executor.service.jobhandler; + +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.handler.annotation.XxlJob; +import com.xxl.job.core.log.XxlJobLogger; +import com.xxl.job.core.util.ShardingUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.TimeUnit; + +/** + * XxlJob开发示例(Bean模式) + * + * 开发步骤: + * 1、在Spring Bean实例中,开发Job方法,方式格式要求为 "public ReturnT<String> execute(String param)" + * 2、为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")",注解value值对应的是调度中心新建任务的JobHandler属性的值。 + * 3、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志; + * + * @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 ReturnT<String> demoJobHandler(String param) throws Exception { + XxlJobLogger.log("XXL-JOB, Hello World."); + + for (int i = 0; i < 5; i++) { + XxlJobLogger.log("beat at:" + i); + TimeUnit.SECONDS.sleep(2); + } + return ReturnT.SUCCESS; + } + + + /** + * 2、分片广播任务 + */ + @XxlJob("shardingJobHandler") + public ReturnT<String> shardingJobHandler(String param) throws Exception { + + // 分片参数 + ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo(); + XxlJobLogger.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardingVO.getIndex(), shardingVO.getTotal()); + + // 业务逻辑 + for (int i = 0; i < shardingVO.getTotal(); i++) { + if (i == shardingVO.getIndex()) { + XxlJobLogger.log("第 {} 片, 命中分片开始处理", i); + } else { + XxlJobLogger.log("第 {} 片, 忽略", i); + } + } + + return ReturnT.SUCCESS; + } + + + /** + * 3、命令行任务 + */ + @XxlJob("commandJobHandler") + public ReturnT<String> commandJobHandler(String param) throws Exception { + String command = param; + int exitValue = -1; + + BufferedReader bufferedReader = null; + try { + // command process + 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) { + XxlJobLogger.log(line); + } + + // command exit + process.waitFor(); + exitValue = process.exitValue(); + } catch (Exception e) { + XxlJobLogger.log(e); + } finally { + if (bufferedReader != null) { + bufferedReader.close(); + } + } + + if (exitValue == 0) { + return IJobHandler.SUCCESS; + } else { + return new ReturnT<String>(IJobHandler.FAIL.getCode(), "command exit value("+exitValue+") is failed"); + } + } + + + /** + * 4、跨平台Http任务 + */ + @XxlJob("httpJobHandler") + public ReturnT<String> httpJobHandler(String param) throws Exception { + + // request + HttpURLConnection connection = null; + BufferedReader bufferedReader = null; + try { + // connection + URL realUrl = new URL(param); + connection = (HttpURLConnection) realUrl.openConnection(); + + // connection setting + connection.setRequestMethod("GET"); + connection.setDoOutput(true); + 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(); + + //Map<String, List<String>> map = connection.getHeaderFields(); + + // 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(); + + XxlJobLogger.log(responseMsg); + return ReturnT.SUCCESS; + } catch (Exception e) { + XxlJobLogger.log(e); + return ReturnT.FAIL; + } finally { + try { + if (bufferedReader != null) { + bufferedReader.close(); + } + if (connection != null) { + connection.disconnect(); + } + } catch (Exception e2) { + XxlJobLogger.log(e2); + } + } + + } + + /** + * 5、生命周期任务示例:任务初始化与销毁时,支持自定义相关逻辑; + */ + @XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy") + public ReturnT<String> demoJobHandler2(String param) throws Exception { + XxlJobLogger.log("XXL-JOB, Hello World."); + return ReturnT.SUCCESS; + } + + + + + public void init(){ + logger.info("init"); + } + public void destroy(){ + logger.info("destory"); + } + + +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties new file mode 100644 index 0000000..7b8865f --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties @@ -0,0 +1,22 @@ +# web port +server.port=8081 + +# log config +logging.config=classpath:logback.xml + + +### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" +xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin + +### xxl-job executor address +xxl.job.executor.appname=xxl-job-executor-sample +xxl.job.executor.ip= +xxl.job.executor.port=9996 + +### xxl-job, access token +xxl.job.accessToken= + +### xxl-job log path +xxl.job.executor.logpath=./data/applogs/xxl-job/jobhandler +### xxl-job log retention days +xxl.job.executor.logretentiondays=30 diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/logback.xml b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/logback.xml new file mode 100644 index 0000000..66b325f --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/logback.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration debug="false" scan="true" scanPeriod="1 seconds"> + + <contextName>logback</contextName> + <property name="log.path" value="./data/applogs/xxl-job/xxl-job-executor-sample-springboot.log"/> + + <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${log.path}</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern> + </rollingPolicy> + <encoder> + <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n + </pattern> + </encoder> + </appender> + + <root level="info"> + <appender-ref ref="console"/> + <appender-ref ref="file"/> + </root> + +</configuration>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/test/java/com/xxl/job/executor/test/XxlJobExecutorExampleBootApplicationTests.java b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/test/java/com/xxl/job/executor/test/XxlJobExecutorExampleBootApplicationTests.java new file mode 100644 index 0000000..fdccb3b --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/test/java/com/xxl/job/executor/test/XxlJobExecutorExampleBootApplicationTests.java @@ -0,0 +1,17 @@ +package com.xxl.job.executor.test; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class XxlJobExecutorExampleBootApplicationTests { + + @Test + public void test() { + + } + +}
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/application.properties b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/application.properties new file mode 100644 index 0000000..7b8865f --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/application.properties @@ -0,0 +1,22 @@ +# web port +server.port=8081 + +# log config +logging.config=classpath:logback.xml + + +### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" +xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin + +### xxl-job executor address +xxl.job.executor.appname=xxl-job-executor-sample +xxl.job.executor.ip= +xxl.job.executor.port=9996 + +### xxl-job, access token +xxl.job.accessToken= + +### xxl-job log path +xxl.job.executor.logpath=./data/applogs/xxl-job/jobhandler +### xxl-job log retention days +xxl.job.executor.logretentiondays=30 diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/com/xxl/job/executor/XxlJobExecutorApplication.class b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/com/xxl/job/executor/XxlJobExecutorApplication.class Binary files differnew file mode 100644 index 0000000..48038f7 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/com/xxl/job/executor/XxlJobExecutorApplication.class diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/com/xxl/job/executor/core/config/XxlJobConfig.class b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/com/xxl/job/executor/core/config/XxlJobConfig.class Binary files differnew file mode 100644 index 0000000..69dc558 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/com/xxl/job/executor/core/config/XxlJobConfig.class diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/com/xxl/job/executor/service/jobhandler/SampleXxlJob.class b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/com/xxl/job/executor/service/jobhandler/SampleXxlJob.class Binary files differnew file mode 100644 index 0000000..205995a --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/com/xxl/job/executor/service/jobhandler/SampleXxlJob.class diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/logback.xml b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/logback.xml new file mode 100644 index 0000000..66b325f --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/classes/logback.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration debug="false" scan="true" scanPeriod="1 seconds"> + + <contextName>logback</contextName> + <property name="log.path" value="./data/applogs/xxl-job/xxl-job-executor-sample-springboot.log"/> + + <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${log.path}</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern> + </rollingPolicy> + <encoder> + <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n + </pattern> + </encoder> + </appender> + + <root level="info"> + <appender-ref ref="console"/> + <appender-ref ref="file"/> + </root> + +</configuration>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/test-classes/com/xxl/job/executor/test/XxlJobExecutorExampleBootApplicationTests.class b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/test-classes/com/xxl/job/executor/test/XxlJobExecutorExampleBootApplicationTests.class Binary files differnew file mode 100644 index 0000000..e44388d --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/target/test-classes/com/xxl/job/executor/test/XxlJobExecutorExampleBootApplicationTests.class diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/xxl-job-executor-sample-springboot.iml b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/xxl-job-executor-sample-springboot.iml new file mode 100644 index 0000000..1474773 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/xxl-job-executor-sample-springboot.iml @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> + <component name="FacetManager"> + <facet type="Spring" name="Spring"> + <configuration /> + </facet> + <facet type="web" name="Web"> + <configuration> + <webroots /> + <sourceRoots> + <root url="file://$MODULE_DIR$/src/main/java" /> + <root url="file://$MODULE_DIR$/src/main/resources" /> + </sourceRoots> + </configuration> + </facet> + </component> + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7"> + <output url="file://$MODULE_DIR$/target/classes" /> + <output-test url="file://$MODULE_DIR$/target/test-classes" /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> + <excludeFolder url="file://$MODULE_DIR$/target" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:1.5.22.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:1.5.22.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:1.5.22.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:1.5.22.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:1.5.22.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.1.11" level="project" /> + <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.1.11" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.26" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.26" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:log4j-over-slf4j:1.7.26" level="project" /> + <orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.17" level="project" /> + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:1.5.22.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:8.5.43" level="project" /> + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-annotations-api:8.5.43" level="project" /> + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:8.5.43" level="project" /> + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:8.5.43" level="project" /> + <orderEntry type="library" name="Maven: org.hibernate:hibernate-validator:5.3.6.Final" level="project" /> + <orderEntry type="library" name="Maven: javax.validation:validation-api:1.1.0.Final" level="project" /> + <orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.2.Final" level="project" /> + <orderEntry type="library" name="Maven: com.fasterxml:classmate:1.3.4" level="project" /> + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.8.11.3" level="project" /> + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.8.0" level="project" /> + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.8.11" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-web:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-aop:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-beans:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-context:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-webmvc:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-expression:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:1.5.22.RELEASE" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:1.5.22.RELEASE" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:1.5.22.RELEASE" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.2.0" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.2.1" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.1" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.3" level="project" /> + <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.26" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:2.6.0" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:1.10.19" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.1" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.4.0" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" /> + <orderEntry type="library" name="Maven: org.springframework:spring-core:4.3.25.RELEASE" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:4.3.25.RELEASE" level="project" /> + <orderEntry type="module" module-name="xxl-job-core" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-rpc-core:1.5.0" level="project" /> + <orderEntry type="library" name="Maven: io.netty:netty-all:4.1.43.Final" level="project" /> + <orderEntry type="library" name="Maven: com.caucho:hessian:4.0.63" level="project" /> + <orderEntry type="library" name="Maven: com.xuxueli:xxl-registry-client:1.1.0" level="project" /> + <orderEntry type="library" name="Maven: org.codehaus.groovy:groovy:2.4.17" level="project" /> + </component> +</module>
\ No newline at end of file diff --git a/xxl-job-executor-samples/xxl-job-executor-samples.iml b/xxl-job-executor-samples/xxl-job-executor-samples.iml new file mode 100644 index 0000000..c16e738 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-samples.iml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7"> + <output url="file://$MODULE_DIR$/target/classes" /> + <output-test url="file://$MODULE_DIR$/target/test-classes" /> + <content url="file://$MODULE_DIR$"> + <excludeFolder url="file://$MODULE_DIR$/target" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module>
\ No newline at end of file |
