方法任务支持:由原来基于JobHandler类任务开发方式,优化为支持基于方法的任务开发方式;因此,可以支持单个类中开发多个任务方法,进行类复用

master
xuxueli 5 years ago
parent 49f7e16954
commit f083bb2695
  1. 17
      doc/XXL-JOB官方文档.md
  2. 58
      xxl-job-core/src/main/java/com/xxl/job/core/executor/impl/XxlJobSpringExecutor.java
  3. 6
      xxl-job-core/src/main/java/com/xxl/job/core/handler/IJobHandler.java
  4. 15
      xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/JobHandler.java
  5. 30
      xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/XxlJob.java
  6. 1
      xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/GlueJobHandler.java
  7. 69
      xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/MethodJobHandler.java
  8. 2
      xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/DemoJobHandler.java
  9. 44
      xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java

@ -1630,10 +1630,19 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
- 25、项目依赖升级至较新稳定版本,如spring、spring-boot、mybatis、slf4j、groovy等等; - 25、项目依赖升级至较新稳定版本,如spring、spring-boot、mybatis、slf4j、groovy等等;
### 6.27 版本 v2.1.2 Release Notes[迭代中] ### 6.27 版本 v2.1.2 Release Notes[迭代中]
- 1、调度中心dispatcher servlet加载顺序优化; - 1、方法任务支持:由原来基于JobHandler类任务开发方式,优化为支持基于方法的任务开发方式;因此,可以支持单个类中开发多个任务方法,进行类复用(TODO:JobHandler移除);
- 2、执行器回调乱码问题修复; ```
- 3、[迭代中]移除commons-exec,采用原生方式实现; @XxlJob("demoJobHandler2")
- 4、[迭代中]任务操作API服务调整为restful方式,降低接入成本; public ReturnT<String> execute(String param) {
XxlJobLogger.log("hello world");
return ReturnT.SUCCESS;
}
```
- 2、调度中心dispatcher servlet加载顺序优化;
- 3、执行器回调乱码问题修复;
- 4、[迭代中]移除commons-exec,采用原生方式实现;
- 5、[迭代中]任务操作API服务调整为restful方式,降低接入成本;
### TODO LIST ### TODO LIST

@ -1,9 +1,11 @@
package com.xxl.job.core.executor.impl; package com.xxl.job.core.executor.impl;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.executor.XxlJobExecutor; import com.xxl.job.core.executor.XxlJobExecutor;
import com.xxl.job.core.glue.GlueFactory; import com.xxl.job.core.glue.GlueFactory;
import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler; import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.handler.impl.MethodJobHandler; import com.xxl.job.core.handler.impl.MethodJobHandler;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
@ -29,11 +31,13 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
// init JobHandler Repository // init JobHandler Repository
initJobHandlerRepository(applicationContext); initJobHandlerRepository(applicationContext);
// init JobHandler Repository (for method)
initJobHandlerMethodRepository(applicationContext); initJobHandlerMethodRepository(applicationContext);
// refresh GlueFactory // refresh GlueFactory
GlueFactory.refreshInstance(1); GlueFactory.refreshInstance(1);
// super start // super start
super.start(); super.start();
} }
@ -71,21 +75,59 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
if (applicationContext == null) { if (applicationContext == null) {
return; return;
} }
// init job handler from method
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) { for (String beanDefinitionName : beanDefinitionNames) {
Object bean = applicationContext.getBean(beanDefinitionName); Object bean = applicationContext.getBean(beanDefinitionName);
Method[] methods = bean.getClass().getDeclaredMethods(); Method[] methods = bean.getClass().getDeclaredMethods();
for (int i = 0; i < methods.length; i++) { for (Method method: methods) {
JobHandler jobHandler = AnnotationUtils.findAnnotation(methods[i], JobHandler.class); XxlJob xxlJob = AnnotationUtils.findAnnotation(method, XxlJob.class);
if (jobHandler != null) { if (xxlJob != null) {
String name = jobHandler.value();
if (name.isEmpty()) { // name
name = methods[i].getName(); String name = xxlJob.value();
if (name.trim().length() == 0) {
throw new RuntimeException("xxl-job method-jobhandler name invalid, for[" + bean.getClass() + "#"+ method.getName() +"] .");
} }
if (loadJobHandler(name) != null) { if (loadJobHandler(name) != null) {
throw new RuntimeException("xxl-job jobhandler[" + name + "] naming conflicts."); throw new RuntimeException("xxl-job jobhandler[" + name + "] naming conflicts.");
} }
registJobHandler(name, new MethodJobHandler(bean, methods[i], jobHandler));
// execute method
if (!(method.getParameterTypes()!=null && method.getParameterTypes().length==1 && method.getParameterTypes()[0].isAssignableFrom(String.class))) {
throw new RuntimeException("xxl-job method-jobhandler param-classtype invalid, for[" + bean.getClass() + "#"+ method.getName() +"] , " +
"The correct method format like \" public ReturnT<String> execute(String param) \" .");
}
if (!method.getReturnType().isAssignableFrom(ReturnT.class)) {
throw new RuntimeException("xxl-job method-jobhandler return-classtype invalid, for[" + bean.getClass() + "#"+ method.getName() +"] , " +
"The correct method format like \" public ReturnT<String> execute(String param) \" .");
}
method.setAccessible(true);
// init and destory
Method initMethod = null;
Method destroyMethod = null;
if(xxlJob.init().trim().length() > 0) {
try {
initMethod = bean.getClass().getDeclaredMethod(xxlJob.init());
initMethod.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new RuntimeException("xxl-job method-jobhandler initMethod invalid, for[" + bean.getClass() + "#"+ method.getName() +"] .");
}
}
if(xxlJob.destroy().trim().length() > 0) {
try {
destroyMethod = bean.getClass().getDeclaredMethod(xxlJob.destroy());
destroyMethod.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new RuntimeException("xxl-job method-jobhandler destroyMethod invalid, for[" + bean.getClass() + "#"+ method.getName() +"] .");
}
}
// registry jobhandler
registJobHandler(name, new MethodJobHandler(bean, method, initMethod, destroyMethod));
} }
} }
} }

@ -2,6 +2,8 @@ package com.xxl.job.core.handler;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import java.lang.reflect.InvocationTargetException;
/** /**
* job handler * job handler
* *
@ -31,7 +33,7 @@ public abstract class IJobHandler {
/** /**
* init handler, invoked when JobThread init * init handler, invoked when JobThread init
*/ */
public void init() { public void init() throws InvocationTargetException, IllegalAccessException {
// do something // do something
} }
@ -39,7 +41,7 @@ public abstract class IJobHandler {
/** /**
* destroy handler, invoked when JobThread destroy * destroy handler, invoked when JobThread destroy
*/ */
public void destroy() { public void destroy() throws InvocationTargetException, IllegalAccessException {
// do something // do something
} }

@ -8,23 +8,16 @@ import java.lang.annotation.Target;
/** /**
* annotation for job handler * annotation for job handler
*
*
* @author 2016-5-17 21:06:49 * @author 2016-5-17 21:06:49
* @author liuzh 2019-12-07
*/ */
@Target({ElementType.TYPE, ElementType.METHOD}) @Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Inherited @Inherited
@Deprecated
public @interface JobHandler { public @interface JobHandler {
String value() default ""; String value() default "";
/**
* init handler, invoked when JobThread init
*/
String init() default "";
/**
* destroy handler, invoked when JobThread destroy
*/
String destroy() default "";
} }

@ -0,0 +1,30 @@
package com.xxl.job.core.handler.annotation;
import java.lang.annotation.*;
/**
* annotation for method jobhandler
*
* @author xuxueli 2019-12-11 20:50:13
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface XxlJob {
/**
* jobhandler name
*/
String value() default "";
/**
* init handler, invoked when JobThread init
*/
String init() default "";
/**
* destroy handler, invoked when JobThread destroy
*/
String destroy() default "";
}

@ -6,6 +6,7 @@ import com.xxl.job.core.log.XxlJobLogger;
/** /**
* glue job handler * glue job handler
*
* @author xuxueli 2016-5-19 21:05:45 * @author xuxueli 2016-5-19 21:05:45
*/ */
public class GlueJobHandler extends IJobHandler { public class GlueJobHandler extends IJobHandler {

@ -2,52 +2,26 @@ package com.xxl.job.core.handler.impl;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
/** /**
* @author liuzh 2019-12-07 * @author xuxueli 2019-12-11 21:12:18
*/ */
public class MethodJobHandler extends IJobHandler { public class MethodJobHandler extends IJobHandler {
private static Logger logger = LoggerFactory.getLogger(MethodJobHandler.class);
private final Object target; private final Object target;
private final Method method; private final Method method;
private final JobHandler jobHandler;
private Method initMethod; private Method initMethod;
private Method destroyMethod; private Method destroyMethod;
public MethodJobHandler(Object target, Method method, JobHandler jobHandler) { public MethodJobHandler(Object target, Method method, Method initMethod, Method destroyMethod) {
this.target = target; this.target = target;
this.method = method; this.method = method;
this.jobHandler = jobHandler;
this.method.setAccessible(true);
this.prepareMethod();
}
protected void prepareMethod() { this.initMethod =initMethod;
String init = jobHandler.init(); this.destroyMethod =destroyMethod;
if(!init.isEmpty()) {
try {
initMethod = target.getClass().getDeclaredMethod(init);
initMethod.setAccessible(true);
} catch (NoSuchMethodException e) {
logger.warn(e.getMessage(), e);
}
}
String destroy = jobHandler.destroy();
if(!destroy.isEmpty()) {
try {
destroyMethod = target.getClass().getDeclaredMethod(destroy);
destroyMethod.setAccessible(true);
} catch (NoSuchMethodException e) {
logger.warn(e.getMessage(), e);
}
}
} }
@Override @Override
@ -56,42 +30,21 @@ public class MethodJobHandler extends IJobHandler {
} }
@Override @Override
public void init() { public void init() throws InvocationTargetException, IllegalAccessException {
super.init();
if(initMethod != null) { if(initMethod != null) {
try { initMethod.invoke(target);
initMethod.invoke(target);
} catch (IllegalAccessException e) {
logger.warn(e.getMessage(), e);
} catch (InvocationTargetException e) {
logger.warn(e.getMessage(), e);
}
} }
} }
@Override @Override
public void destroy() { public void destroy() throws InvocationTargetException, IllegalAccessException {
super.destroy();
if(destroyMethod != null) { if(destroyMethod != null) {
try { destroyMethod.invoke(target);
destroyMethod.invoke(target);
} catch (IllegalAccessException e) {
logger.warn(e.getMessage(), e);
} catch (InvocationTargetException e) {
logger.warn(e.getMessage(), e);
}
} }
} }
public Object getTarget() { @Override
return target; public String toString() {
} return super.toString()+"["+ target.getClass() + "#" + method.getName() +"]";
public Method getMethod() {
return method;
}
public JobHandler getJobHandler() {
return jobHandler;
} }
} }

@ -10,6 +10,8 @@ import java.util.concurrent.TimeUnit;
/** /**
* 类方式任务开发即将废弃建议采用方法方式开发参考com.xxl.job.executor.service.jobhandler.SampleXxlJob
*
* 任务Handler示例Bean模式 * 任务Handler示例Bean模式
* *
* 开发步骤 * 开发步骤

@ -0,0 +1,44 @@
package com.xxl.job.executor.service.jobhandler;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.log.XxlJobLogger;
import org.springframework.stereotype.Component;
/**
* 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 {
@XxlJob("demoJobHandler2")
public ReturnT<String> execute(String param) {
XxlJobLogger.log("222");
return ReturnT.SUCCESS;
}
@XxlJob(value="demoJobHandler3", init = "init", destroy = "destory")
public ReturnT<String> execute3(String param) {
XxlJobLogger.log("333");
return ReturnT.SUCCESS;
}
public void init(){
System.out.println("init");
}
public void destory(){
System.out.println("destory");
}
}
Loading…
Cancel
Save