فهرست منبع

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

xuxueli 5 سال پیش
والد
کامیت
f083bb2695

+ 13 - 4
doc/XXL-JOB官方文档.md

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

+ 50 - 8
xxl-job-core/src/main/java/com/xxl/job/core/executor/impl/XxlJobSpringExecutor.java

@@ -1,9 +1,11 @@
 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.glue.GlueFactory;
 import com.xxl.job.core.handler.IJobHandler;
 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 org.springframework.beans.BeansException;
 import org.springframework.beans.factory.DisposableBean;
@@ -29,11 +31,13 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
 
         // init JobHandler Repository
         initJobHandlerRepository(applicationContext);
+
+        // init JobHandler Repository (for method)
         initJobHandlerMethodRepository(applicationContext);
+
         // refresh GlueFactory
         GlueFactory.refreshInstance(1);
 
-
         // super start
         super.start();
     }
@@ -71,21 +75,59 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
         if (applicationContext == null) {
             return;
         }
+
+        // init job handler from method
         String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
         for (String beanDefinitionName : beanDefinitionNames) {
             Object bean = applicationContext.getBean(beanDefinitionName);
             Method[] methods = bean.getClass().getDeclaredMethods();
-            for (int i = 0; i < methods.length; i++) {
-                JobHandler jobHandler = AnnotationUtils.findAnnotation(methods[i], JobHandler.class);
-                if (jobHandler != null) {
-                    String name = jobHandler.value();
-                    if (name.isEmpty()) {
-                        name = methods[i].getName();
+            for (Method method: methods) {
+                XxlJob xxlJob = AnnotationUtils.findAnnotation(method, XxlJob.class);
+                if (xxlJob != null) {
+
+                    // name
+                    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) {
                         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));
                 }
             }
         }

+ 4 - 2
xxl-job-core/src/main/java/com/xxl/job/core/handler/IJobHandler.java

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

+ 4 - 11
xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/JobHandler.java

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

+ 30 - 0
xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/XxlJob.java

@@ -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 "";
+
+}

+ 1 - 0
xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/GlueJobHandler.java

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

+ 11 - 58
xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/MethodJobHandler.java

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

+ 2 - 0
xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/DemoJobHandler.java

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

+ 44 - 0
xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java

@@ -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");
+    }
+
+}