使用Spring自定义注解实现任务路由的方法

作者:wangyan9110 时间:2023-12-20 22:34:11 

在Spring mvc的开发中,我们可以通过RequestMapping来配,当前方法用于处理哪一个URL的请求.同样我们现在有一个需求,有一个任务调度器,可以按照不同的任务类型路由到不同的任务执行器。其本质就是通过外部参数进行一次路由和Spring mvc做的事情类似。简单看了Spring mvc的实现原理之后,决定使用自定义注解的方式来实现以上功能。

自定义TaskHandler注解


@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface TaskHandler {

String taskType() default "";
}

以上定义了任务处理器的注解,其中@Component表示在spring 启动过程中,会扫描到并且注入到容器中。taskType表示类型。

任务处理器定义


public abstract class AbstractTaskHandler {

/**
  * 任务执行器
  *
  * @param task 任务
  * @return 执行结果
  */
  public abstract BaseResult execute(Task task);
}

以上定义了一个任务执行的处理器,其他所有的具体的任务执行器继承实现这个方法。其中Task表示任务的定义,包括任务Id,执行任务需要的参数等。

任务处理器实现

接下来,我们可以实现一个具体的任务处理器。


@TaskHandler(taskType = "UserNameChanged")
public class UserNameChangedSender extends AbstractTaskHandler {
 @Override
 public BaseResult execute(Task task) {
  return new BaseResult();
 }
}

以上我们就实现一个用户名修改通知的任务处理器,具体的业务逻辑这里没有实现。

其中:@TaskHandler(taskType = "UserNameChanged"),这里我们指定这个Handler用于处理用户名变更的任务

任务处理Handler注册


public class TaskHandlerRegister extends ApplicationObjectSupport {

private final static Map<String, AbstractTaskHandler> TASK_HANDLERS_MAP = new HashMap<>();

private static final Logger LOGGER = LoggerFactory.getLogger(TaskHandlerRegister.class);

@Override
 protected void initApplicationContext(ApplicationContext context) throws BeansException {
   super.initApplicationContext(context);
   Map<String, Object> taskBeanMap = context.getBeansWithAnnotation(TaskHandler.class);
   taskBeanMap.keySet().forEach(beanName -> {
     Object bean = taskBeanMap.get(beanName);
     Class clazz = bean.getClass();
     if (bean instanceof AbstractTaskHandler && clazz.getAnnotation(TaskHandler.class) != null) {
       TaskHandler taskHandler = (TaskHandler) clazz.getAnnotation(TaskHandler.class);
       String taskType = taskHandler.taskType();
       if (TASK_HANDLERS_MAP.keySet().contains(taskType)) {
         throw new RuntimeException("TaskType has Exits. TaskType=" + taskType);
       }
       TASK_HANDLERS_MAP.put(taskHandler.taskType(), (AbstractTaskHandler) taskBeanMap.get(beanName));
       LOGGER.info("Task Handler Register. taskType={},beanName={}", taskHandler.taskType(), beanName);
     }
   });
 }

public static AbstractTaskHandler getTaskHandler(String taskType) {
   return TASK_HANDLERS_MAP.get(taskType);
 }
}

这里继承了Spring的ApplicationObjectSupport类,具体的注册过程如下

  1. Spring完成bean的初始化

  2. 查找spring的容器中,所有带有TaskHandler注解的bean

  3. 校验bean是否为AbstractTaskHandler类型,获取到taskType

  4. 把该bean放到TASK_HANDLERS_MAP容器中,即注册完成

任务执行

接下来我们来看下任务执行


public class TaskExecutor implements Job {

private static final String TASK_TYPE = "taskType";

@Override
 public BaseResult execute(Task task){
   String taskType=task.getTaskType();
   if (TaskHandlerRegister.getTaskHandler(taskType) == null) {
     throw new RuntimeException("can't find taskHandler,taskType=" + taskType);
   }
   AbstractTaskHandler abstractHandler = TaskHandlerRegister.getTaskHandler(taskType);
   return abstractHandler.execute(task);
 }
}

这里发起任务执行的是一个Job,具体过程如下

  1. 校验该任务类型,有没有在注册中心注册相关Handler

  2. 从任务注册中心获取到对应的处理的Handelr

  3. 执行该Handelr

以上过程就完成了,可以实现基于注解的一个任务路由过程。其实现思路来自于Spring mvc的RequestMapping的设计思路.希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

来源:https://my.oschina.net/wangyan9110/blog/1492511

标签:Spring,路由
0
投稿

猜你喜欢

  • java使用IO流对数组排序实例讲解

    2023-09-04 02:24:19
  • Java实例讲解多态数组的使用

    2021-08-30 19:34:46
  • Java中的private、protected、public和default的区别(详解)

    2023-01-10 01:55:51
  • Java实现年兽大作战游戏详解

    2023-11-08 04:28:05
  • Java 1.8使用数组实现循环队列

    2022-02-11 04:00:10
  • 实例讲解Android中的AutoCompleteTextView自动补全组件

    2022-05-10 15:35:10
  • Java中list.contains()的用法及拓展

    2022-11-06 21:04:59
  • Java中缀表达式转后缀表达式实现方法详解

    2021-08-25 02:57:20
  • ChatGPT介绍及Java API调用

    2021-07-06 07:53:55
  • C#使用第三方组件生成二维码汇总

    2023-10-03 22:15:21
  • Android4.4新增函数访问外部存储

    2022-09-14 18:34:04
  • Android界面一键变灰开发深色适配模式编程示例

    2021-11-25 04:22:25
  • Java创建对象(显式创建和隐含创建)

    2022-10-26 13:58:33
  • Android的Activity跳转动画各种效果整理

    2022-05-05 03:43:35
  • Android开发之设置开机自动启动的几种方法

    2021-12-04 20:35:37
  • springboot static关键字真能提高Bean的优先级(厉害了)

    2023-03-10 07:39:12
  • C#在Excel表格中插入、编辑和删除批注

    2023-01-12 13:52:20
  • Android模仿微信收藏文件的标签处理功能

    2022-07-17 05:32:18
  • 浅谈JVM之java class文件的密码本

    2023-05-28 13:02:39
  • Android实现自动变换大小的ViewPager

    2023-03-19 06:56:15
  • asp之家 软件编程 m.aspxhome.com