文档章节

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

wangyan9110
 wangyan9110
发布于 2017/07/31 09:52
字数 734
阅读 3710
收藏 218

在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的设计思路.

关注公众号

输入图片说明

© 著作权归作者所有

共有 人打赏支持
wangyan9110
粉丝 39
博文 10
码字总数 13360
作品 2
杭州
程序员
私信 提问
加载中

评论(8)

wangyan9110
wangyan9110

引用来自“joshuazhan”的评论

从任务注册中心获取到对应的处理的Handelr
执行该Handelr

有点拼写上的问题

@joshuazhan 多谢指正
wpfc
wpfc

引用来自“wangyan9110”的评论

引用来自“wpfc”的评论

实现job接口,默认实现execute方法,但是自带参数JobExecutionContext类型,请问下job用的是哪个包下的job对象

@wpfc 内部接口
你好,我想问下你这个job对象是如何处理的?做了一定的封装吗?谢谢
joshuazhan
joshuazhan
从任务注册中心获取到对应的处理的Handelr
执行该Handelr

有点拼写上的问题
happut
happut
以前尝试过,在AbstractTaskHandler中增加getName(),每个类实现该方法 返回处理类的名称
还是这个方法好,使用也比以前那种方便
wangyan9110
wangyan9110

引用来自“月夜筱风”的评论

不错,简单明了

@月夜筱风 多谢支持
wangyan9110
wangyan9110

引用来自“wpfc”的评论

实现job接口,默认实现execute方法,但是自带参数JobExecutionContext类型,请问下job用的是哪个包下的job对象

@wpfc 内部接口
月夜筱风
月夜筱风
不错,简单明了
wpfc
wpfc
实现job接口,默认实现execute方法,但是自带参数JobExecutionContext类型,请问下job用的是哪个包下的job对象
Spring Boot实践--定时任务两种(Schedule与Quartz整合)

Spring Boot实践--定时任务两种(Schedule与Quartz整合) 最近在项目中使用到定时任务,之前一直都是使用Quartz 来实现,最近看Spring 基础发现其实Spring 提供 Spring Schedule 可以帮助我们实...

spinachgit
02/11
0
0
Spring注解方式实现任务调度

原文:http://docs.spring.io/spring/docs/4.0.1.BUILD-SNAPSHOT/javadoc-api/ 注解类型:EnableScheduling @Target(value=TYPE) @Retention(value=RUNTIME)@Import(value=SchedulingConfigu......

Mr_Tank_
2014/01/04
0
1
Spring探秘|妙用BeanPostProcessor

最近,在给项目组使用Spring搭建Java项目基础框架时,发现使用Spring提供的BeanPostProcessor可以很简单方便地解决很多看起来有点难解决的问题。本文将会通过一个真实案例来阐述BeanPostPro...

圆圆仙人球
2017/08/06
0
0
Spring Cloud Stream应用与自定义RocketMQ Binder:编程模型

前言: 本文作者张天,节选自笔者与其合著的《Spring Cloud微服务架构进阶》,即将在八月出版问世。本文将其中Spring Cloud Stream应用与自定义Rocketmq Binder的内容抽取出来,主要介绍Spr...

aoho
06/23
0
0
用Spring Cloud Stream实现Event Driven Architectures

微服务的出现和原生的云架构触发了DDD,CQRS和Event Sourcing的复苏。所有这些方式实现的核心是Domain Event(领域事件), 它是分布式系统中实现一整套DDD架构及实现最终一致性的主要机制。...

Big_BoBo
2017/10/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Docker安装踩坑:E_FAIL 0x80004005的解决

参考 菜鸟教程--Windows Docker 安装 http://www.runoob.com/docker/windows-docker-install.html 官方文档-Install Docker Toolbox on Windows https://docs.docker.com/toolbox/toolbox_in......

karma123
12分钟前
0
0
js垃圾回收机制和引起内存泄漏的操作

JS的垃圾回收机制了解吗? Js具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的执行。 JS中最常见的垃圾回收方式是标记清除。 工作原理:是当变量进入环境时,将这个变量标记为“...

Jack088
昨天
17
0
大数据教程(10.1)倒排索引建立

前面博主介绍了sql中join功能的大数据实现,本节将继续为小伙伴们分享倒排索引的建立。 一、需求 在很多项目中,我们需要对我们的文档建立索引(如:论坛帖子);我们需要记录某个词在各个文...

em_aaron
昨天
27
0
"errcode": 41001, "errmsg": "access_token missing hint: [w.ILza05728877!]"

Postman获取微信小程序码的时候报错, errcode: 41001, errmsg: access_token missing hint 查看小程序开发api指南,原来access_token是直接当作parameter的(写在url之后),scene参数一定要...

两广总督bogang
昨天
31
0
MYSQL索引

索引的作用 索引类似书籍目录,查找数据,先查找目录,定位页码 性能影响 索引能大大减少查询数据时需要扫描的数据量,提高查询速度, 避免排序和使用临时表 将随机I/O变顺序I/O 降低写速度,占用磁...

关元
昨天
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部