diff --git a/GLUE(SQL)WebIDE.png b/GLUE(SQL)WebIDE.png new file mode 100644 index 00000000..75fc76e6 Binary files /dev/null and b/GLUE(SQL)WebIDE.png differ diff --git a/GLUE(SQL)任务创建.png b/GLUE(SQL)任务创建.png new file mode 100644 index 00000000..b59f1745 Binary files /dev/null and b/GLUE(SQL)任务创建.png differ diff --git a/GLUE(SQL)执行日志.png b/GLUE(SQL)执行日志.png new file mode 100644 index 00000000..c2e78665 Binary files /dev/null and b/GLUE(SQL)执行日志.png differ diff --git a/README.md b/README.md index 3d66c3a4..926ea0e1 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,9 @@ XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅 - 34、线程池隔离:调度线程池进行隔离拆分,慢任务自动降级进入"Slow"线程池,避免耗尽调度线程,提高系统稳定性; - 35、用户管理:支持在线管理系统用户,存在管理员、普通用户两种角色; - 36、权限控制:执行器维度进行权限控制,管理员拥有全量权限,普通用户需要分配执行器权限后才允许相关操作; +- 37 GLUESQL支持: 支持界面编写sql executor端需要实现SQLJobHandler, + 可以参考xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/MYSQLJobHandler.java + 多sql实现需要注意修改com.xxl.job.core.biz.impl.ExecutorBizImpl 中的134行 ## Development diff --git a/xxl-job-admin/src/main/resources/application.properties b/xxl-job-admin/src/main/resources/application.properties index 8727b6c7..fe659657 100644 --- a/xxl-job-admin/src/main/resources/application.properties +++ b/xxl-job-admin/src/main/resources/application.properties @@ -25,7 +25,7 @@ mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml ### xxl-job, datasource spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai spring.datasource.username=root -spring.datasource.password=root_pwd +spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ### datasource-pool diff --git a/xxl-job-admin/src/main/resources/logback.xml b/xxl-job-admin/src/main/resources/logback.xml index d4b08c24..333051da 100644 --- a/xxl-job-admin/src/main/resources/logback.xml +++ b/xxl-job-admin/src/main/resources/logback.xml @@ -2,7 +2,7 @@ logback - + diff --git a/xxl-job-core/src/main/java/com/xxl/job/core/biz/impl/ExecutorBizImpl.java b/xxl-job-core/src/main/java/com/xxl/job/core/biz/impl/ExecutorBizImpl.java index 8bdf7093..17d6163d 100644 --- a/xxl-job-core/src/main/java/com/xxl/job/core/biz/impl/ExecutorBizImpl.java +++ b/xxl-job-core/src/main/java/com/xxl/job/core/biz/impl/ExecutorBizImpl.java @@ -4,9 +4,11 @@ import com.xxl.job.core.biz.ExecutorBiz; import com.xxl.job.core.biz.model.*; import com.xxl.job.core.enums.ExecutorBlockStrategyEnum; import com.xxl.job.core.executor.XxlJobExecutor; +import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; import com.xxl.job.core.glue.GlueFactory; import com.xxl.job.core.glue.GlueTypeEnum; import com.xxl.job.core.handler.IJobHandler; +import com.xxl.job.core.handler.SQLJobHandler; import com.xxl.job.core.handler.impl.GlueJobHandler; import com.xxl.job.core.handler.impl.ScriptJobHandler; import com.xxl.job.core.log.XxlJobFileAppender; @@ -114,6 +116,35 @@ public class ExecutorBizImpl implements ExecutorBiz { if (jobHandler == null) { jobHandler = new ScriptJobHandler(triggerParam.getJobId(), triggerParam.getGlueUpdatetime(), triggerParam.getGlueSource(), GlueTypeEnum.match(triggerParam.getGlueType())); } + }else if(GlueTypeEnum.GLUE_SQL == glueTypeEnum){ + // valid old jobThread + if (jobThread != null && + !(jobThread.getHandler() instanceof GlueJobHandler + && ((GlueJobHandler) jobThread.getHandler()).getGlueUpdatetime()==triggerParam.getGlueUpdatetime() )) { + // change handler or gluesource updated, need kill old thread + removeOldReason = "change job source or glue type, and terminate the old job thread."; + + jobThread = null; + jobHandler = null; + } + + // valid handler + if (jobHandler == null) { + try { + // todo 多sql实现这里要注意 + SQLJobHandler sqlJobHandler = (SQLJobHandler) XxlJobSpringExecutor.getApplicationContext().getBean(SQLJobHandler.class); + jobHandler = new SQLJobHandler(sqlJobHandler, triggerParam.getGlueUpdatetime(), triggerParam.getGlueSource()) { + + @Override + public void execSql(String[] sql) { + sqlJobHandler.execSql(sql); + } + }; + } catch (Exception e) { + logger.error(e.getMessage(), e); + return new ReturnT(ReturnT.FAIL_CODE, e.getMessage()); + } + } } else { return new ReturnT(ReturnT.FAIL_CODE, "glueType[" + triggerParam.getGlueType() + "] is not valid."); } diff --git a/xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java b/xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java index a5c835c9..0f81419f 100644 --- a/xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java +++ b/xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java @@ -8,6 +8,7 @@ public enum GlueTypeEnum { BEAN("BEAN", false, null, null), GLUE_GROOVY("GLUE(Java)", false, null, null), GLUE_SHELL("GLUE(Shell)", true, "bash", ".sh"), + GLUE_SQL("GLUE(SQL)", false, null, null), GLUE_PYTHON("GLUE(Python)", true, "python", ".py"), GLUE_PHP("GLUE(PHP)", true, "php", ".php"), GLUE_NODEJS("GLUE(Nodejs)", true, "node", ".js"), diff --git a/xxl-job-core/src/main/java/com/xxl/job/core/handler/SQLJobHandler.java b/xxl-job-core/src/main/java/com/xxl/job/core/handler/SQLJobHandler.java new file mode 100644 index 00000000..051dc51a --- /dev/null +++ b/xxl-job-core/src/main/java/com/xxl/job/core/handler/SQLJobHandler.java @@ -0,0 +1,45 @@ +package com.xxl.job.core.handler; + +import com.xxl.job.core.context.XxlJobHelper; +import com.xxl.job.core.handler.IJobHandler; + +/** + * glue job handler + * + * @author caigua 2022-11-11 16:29:45 + */ +public abstract class SQLJobHandler extends IJobHandler { + + + private long glueUpdatetime; + + // 具体sql实现 + private SQLJobHandler jobHandler; + private String[] sqlString; + + public SQLJobHandler(){ + } + + public SQLJobHandler(SQLJobHandler jobHandler, long glueUpdatetime, String sqlSourcesString) { + this.jobHandler = jobHandler; + this.glueUpdatetime = glueUpdatetime; + this.sqlString = sqlSourcesString.split("\n"); + + } + public long getGlueUpdatetime() { + return glueUpdatetime; + } + + @Override + public void execute() throws Exception { + XxlJobHelper.log("----------- glue.version:"+ glueUpdatetime +" -----------"); + execSql(sqlString); + } + + /** + * sql执行 + * @param sql + */ + public abstract void execSql(String sql[]); + +} 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 index 9175792a..c0a017b1 100644 --- a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/pom.xml +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/pom.xml @@ -50,6 +50,18 @@ ${project.parent.version} + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis-spring-boot-starter.version} + + + mysql + mysql-connector-java + ${mysql-connector-java.version} + + diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/core/config/JdbcConfig.java b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/core/config/JdbcConfig.java new file mode 100644 index 00000000..86249158 --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/core/config/JdbcConfig.java @@ -0,0 +1,25 @@ +package com.xxl.job.executor.core.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; + +import javax.sql.DataSource; + +/** + * glue job handler + * + * @author caigua 2022-11-11 16:29:45 + */ + +@Configuration +public class JdbcConfig { + @Autowired + private DataSource dataSource; + + @Bean({"jdbcTemplate"}) + public JdbcTemplate jdbcTemplate() { + return new JdbcTemplate(this.dataSource); + } +} diff --git a/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/MYSQLJobHandler.java b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/MYSQLJobHandler.java new file mode 100644 index 00000000..657a82dd --- /dev/null +++ b/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/MYSQLJobHandler.java @@ -0,0 +1,60 @@ +package com.xxl.job.executor.service.jobhandler; + +import com.xxl.job.core.context.XxlJobHelper; +import com.xxl.job.core.handler.SQLJobHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; + +/** + * glue job handler + * + * @author caigua 2022-11-11 16:29:45 + */ + +@Component +public class MYSQLJobHandler extends SQLJobHandler { + + @Autowired + private JdbcTemplate jdbcTemplate; + + MYSQLJobHandler() { + super(); + } + + + @Override + public void execSql(String sql[]) { + + boolean contains_select = false; + + for (String s : sql) { + if (s.trim().toLowerCase().startsWith("select")) { + contains_select = true; + break; + } + } + + if (contains_select) { + // 存在查询sql 一条一条执行 + for (String s : sql) { + if (s.trim().toLowerCase().startsWith("select")) { + + XxlJobHelper.log("exec sql : {} \n result: {}", s, jdbcTemplate.queryForList(s)); + + + } else { + XxlJobHelper.log("exec sql : {} \n rows:{}", s, jdbcTemplate.update(s)); + } + } + + } else { + + int rows[] = jdbcTemplate.batchUpdate(sql); + XxlJobHelper.log("exec rows:{}", rows); + + } + + + } +} 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 index 14c796e8..9385cbef 100644 --- 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 @@ -1,5 +1,5 @@ # web port -server.port=8081 +server.port=8089 # no web #spring.main.web-environment=false @@ -19,8 +19,27 @@ xxl.job.executor.appname=xxl-job-executor-sample xxl.job.executor.address= ### xxl-job executor server-info xxl.job.executor.ip= -xxl.job.executor.port=9999 +xxl.job.executor.port=9998 ### xxl-job executor log-path -xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler +xxl.job.executor.logpath=data/applogs/xxl-job/jobhandler ### xxl-job executor log-retention-days xxl.job.executor.logretentiondays=30 + + +### xxl-job, datasource +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +### datasource-pool +spring.datasource.type=com.zaxxer.hikari.HikariDataSource +spring.datasource.hikari.minimum-idle=10 +spring.datasource.hikari.maximum-pool-size=30 +spring.datasource.hikari.auto-commit=true +spring.datasource.hikari.idle-timeout=30000 +spring.datasource.hikari.pool-name=HikariCP +spring.datasource.hikari.max-lifetime=900000 +spring.datasource.hikari.connection-timeout=10000 +spring.datasource.hikari.connection-test-query=SELECT 1 +spring.datasource.hikari.validation-timeout=1000 \ No newline at end of file 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 index d5a0d2ca..ce5152a5 100644 --- 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 @@ -2,7 +2,7 @@ logback - +