方法任务支持:由原来基于JobHandler类任务开发方式,优化为支持基于方法的任务开发方式;因此,可以支持单个类中开发多个任务方法,进行类复用
This commit is contained in:
parent
49f7e16954
commit
f083bb2695
|
@ -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…
Reference in New Issue