在Listener(监听器)定时启动的TimerTask(定时任务)中使用[email protected]注解的bean

1.有时候在项目中需要定时启动某个任务,对于这个需求,基于JavaEE规范,我们可以使用Listener与TimerTask来实现,代码如下:

public class TestTaskListener implements ServletContextListener {
      //Context()初始化方法
      @Override
      public void contextInitialized(ServletContextEvent sce) {
          //新建一个定时管理器
          new TestTimerManager();
      }
      public TestTaskListener() {
          super();
      }
      @Override
      public void contextDestroyed(ServletContextEvent sce) {
      }
  }

2.contextInitialized方法中新建了一个定时管理器,代码如下:

public class TestTimerManager {
      //新建一个定时器
      Timer timer = new Timer();
      public TestTimerManager() {
          super();
          //新建一个定时任务
          TestTimerTask task = new TestTimerTask();
          //设置定时任务
          timer.schedule(task, firstTimeToStartTheTask, period);
      }
  }

3.在定时任务的Constructor中新建了一个定时任务,其代码如下:

@Configuration
  public class TestTimerTask extends TimerTask {
      //采用Spring框架的依赖注入
      @Autowired
      private SelectDataService selectDataService;

      public TestTimerTask() {
          super();
      }
      @Override
      public void run(){
          try {
              //访问数据库
              MyData myData = selectDataService.selectMyDataById(id);
          }catch(Exception ex) {
              System.out.println("定时任务出错");
              ex.printStackTrace();
          }
      }
  }

spring是个性能非常优秀的抽象工厂,可以生产出工程所需要的实例,这里采用Spring容器的自动注入selectDataService实例。上面代码中,selectDataService这个类是采用Spring的@Service注解的,在项目中主要通过Spring容器注入到Controller中,其作用主要用来访问数据库

运行项目将会发现NullPointerException,也就是说SelectDataService的实例没有被注入到变量selectDataService中。那么,这是什么原因呢?首先来看看配置文件。 
下面是web.xml:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
    <listener-class>com.test.TestTaskListener</listener-class>
</listener>

在启动web项目时,Servlet容器(比如Tomcat)会读web.xml配置文件中的两个节点和,节点用来加载appliactionContext.xml(即Spring的配置文件),节点用来创建监听器(比如TestTaskListener)实例。Listener的生命周期是由servlet容器管理的,例中的TestTaskListener是由servlet容器实例化并调用其contextInitialized方法的,但是,SelectDataService是通过@Service注解的,也就是说SelectDataService是由Spring容器管理的,在Spring容器外无法直接通过依赖注入得到Spring容器管理的bean实例的引用。为了在Spring容器外得到Spring容器管理的bean,可以使用Spring提供的工具类WebApplicationContextUtils。也就是说,可以在servlet容器管理的Listener中使用该工具类获Spring管理的bean。

看如下代码:

public class TestTaskListener implements ServletContextListener {
      //Context()初始化方法
      @Override
      public void contextInitialized(ServletContextEvent sce) {
          //获得Spring容器
          WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
          //从Spring容器中获得SelectDataServlet的实例
          SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
          //新建一个定时管理器
          new TestTimerManager();
      }
      public TestTaskListener() {
          super();
      }
      @Override
      public void contextDestroyed(ServletContextEvent sce) {
      }
  }

那么在Listener中获得的SelectDataService实例如何在TestTimerTask中使用呢?可以通过作为参数传递过去,看如下代码:

public class TestTaskListener implements ServletContextListener {
      //Context()初始化方法
      @Override
      public void contextInitialized(ServletContextEvent sce) {
          //获得Spring容器
          WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
          //从Spring容器中获得SelectDataServlet的实例
          SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
          //新建一个定时管理器
          new TestTimerManager(selectDataService);
      }
      public TestTaskListener() {
          super();
      }
      @Override
      public void contextDestroyed(ServletContextEvent sce) {
      }
  }

public class TestTimerManager {
      //新建一个定时器
      Timer timer = new Timer();

      public TestTimerManager(SelectDataService selectDataService) {
          super();
          //新建一个定时任务
          TestTimerTask task = new TestTimerTask(selectDataService);
          //设置定时任务
          timer.schedule(task, firstTimeToStartTheTask, period);
      }
  }

@Configuration
  public class TestTimerTask extends TimerTask {
      private SelectDataService selectDataService;

      public TestTimerTask(SelectDataService selectDataService) {
          super();
          this.selectDataService = selectDataService;
      }
      @Override
      public void run(){
          try {
              //访问数据库
              MyData myData = selectDataService.selectMyDataById(id);
          }catch(Exception ex) {
              System.out.println("定时任务出错");
              ex.printStackTrace();
          }
      }
  }

再回到web.xml 
由于Servlet容器在初始化TestTaskListener时,获取了Spring容器,所以必须保证,在此之前,Spring容器已经初始化完成。因为Spring容器的初始化也是由Listener(ContextLoaderListener)完成,该监听器用Spring框架提供,可以在web应用启动时启动Spring容器。所以,在web.xml中,要先配置ContextLoaderListener,再配置TestTaskListener。

1.有时候在项目中需要定时启动某个任务,对于这个需求,基于JavaEE规范,我们可以使用Listener与TimerTask来实现,代码如下:

public class TestTaskListener implements ServletContextListener {
      //Context()初始化方法
      @Override
      public void contextInitialized(ServletContextEvent sce) {
          //新建一个定时管理器
          new TestTimerManager();
      }
      public TestTaskListener() {
          super();
      }
      @Override
      public void contextDestroyed(ServletContextEvent sce) {
      }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2.contextInitialized方法中新建了一个定时管理器,代码如下:

public class TestTimerManager {
      //新建一个定时器
      Timer timer = new Timer();
      public TestTimerManager() {
          super();
          //新建一个定时任务
          TestTimerTask task = new TestTimerTask();
          //设置定时任务
          timer.schedule(task, firstTimeToStartTheTask, period);
      }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3.在定时任务的Constructor中新建了一个定时任务,其代码如下:

@Configuration
  public class TestTimerTask extends TimerTask {
      //采用Spring框架的依赖注入
      @Autowired
      private SelectDataService selectDataService;

      public TestTimerTask() {
          super();
      }
      @Override
      public void run(){
          try {
              //访问数据库
              MyData myData = selectDataService.selectMyDataById(id);
          }catch(Exception ex) {
              System.out.println("定时任务出错");
              ex.printStackTrace();
          }
      }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

spring是个性能非常优秀的抽象工厂,可以生产出工程所需要的实例,这里采用Spring容器的自动注入selectDataService实例。上面代码中,selectDataService这个类是采用Spring的@Service注解的,在项目中主要通过Spring容器注入到Controller中,其作用主要用来访问数据库

运行项目将会发现NullPointerException,也就是说SelectDataService的实例没有被注入到变量selectDataService中。那么,这是什么原因呢?首先来看看配置文件。 
下面是web.xml:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
    <listener-class>com.test.TestTaskListener</listener-class>
</listener>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在启动web项目时,Servlet容器(比如Tomcat)会读web.xml配置文件中的两个节点和,节点用来加载appliactionContext.xml(即Spring的配置文件),节点用来创建监听器(比如TestTaskListener)实例。Listener的生命周期是由servlet容器管理的,例中的TestTaskListener是由servlet容器实例化并调用其contextInitialized方法的,但是,SelectDataService是通过@Service注解的,也就是说SelectDataService是由Spring容器管理的,在Spring容器外无法直接通过依赖注入得到Spring容器管理的bean实例的引用。为了在Spring容器外得到Spring容器管理的bean,可以使用Spring提供的工具类WebApplicationContextUtils。也就是说,可以在servlet容器管理的Listener中使用该工具类获Spring管理的bean。

看如下代码:

public class TestTaskListener implements ServletContextListener {
      //Context()初始化方法
      @Override
      public void contextInitialized(ServletContextEvent sce) {
          //获得Spring容器
          WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
          //从Spring容器中获得SelectDataServlet的实例
          SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
          //新建一个定时管理器
          new TestTimerManager();
      }
      public TestTaskListener() {
          super();
      }
      @Override
      public void contextDestroyed(ServletContextEvent sce) {
      }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

那么在Listener中获得的SelectDataService实例如何在TestTimerTask中使用呢?可以通过作为参数传递过去,看如下代码:

public class TestTaskListener implements ServletContextListener {
      //Context()初始化方法
      @Override
      public void contextInitialized(ServletContextEvent sce) {
          //获得Spring容器
          WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
          //从Spring容器中获得SelectDataServlet的实例
          SelectDataService selectDataService = ctx.getBean(SelectDataService.class);
          //新建一个定时管理器
          new TestTimerManager(selectDataService);
      }
      public TestTaskListener() {
          super();
      }
      @Override
      public void contextDestroyed(ServletContextEvent sce) {
      }
  }

public class TestTimerManager {
      //新建一个定时器
      Timer timer = new Timer();

      public TestTimerManager(SelectDataService selectDataService) {
          super();
          //新建一个定时任务
          TestTimerTask task = new TestTimerTask(selectDataService);
          //设置定时任务
          timer.schedule(task, firstTimeToStartTheTask, period);
      }
  }

@Configuration
  public class TestTimerTask extends TimerTask {
      private SelectDataService selectDataService;

      public TestTimerTask(SelectDataService selectDataService) {
          super();
          this.selectDataService = selectDataService;
      }
      @Override
      public void run(){
          try {
              //访问数据库
              MyData myData = selectDataService.selectMyDataById(id);
          }catch(Exception ex) {
              System.out.println("定时任务出错");
              ex.printStackTrace();
          }
      }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

再回到web.xml 
由于Servlet容器在初始化TestTaskListener时,获取了Spring容器,所以必须保证,在此之前,Spring容器已经初始化完成。因为Spring容器的初始化也是由Listener(ContextLoaderListener)完成,该监听器用Spring框架提供,可以在web应用启动时启动Spring容器。所以,在web.xml中,要先配置ContextLoaderListener,再配置TestTaskListener。

时间: 2024-12-29 09:55:22

在Listener(监听器)定时启动的TimerTask(定时任务)中使用[email protected]注解的bean的相关文章

mysql启动提示 access denied for user [email&#160;protected](using password:YES)

问题:遇到mysql启动提示 access denied for user [email protected](using password:YES) 1.检查密码有无错误,如果无就是权限问题. 2.打开SQL的图形工具,输入以下命令行 grant all privileges on *.* to 'root'@'localhost' identified by '你的密码' with grant option; flush privileges; 3.在本地环境运行没有问题,如有异常,请留下评

Oracle 监听器无法启动(TNS-12555,TNS-12560,TNS-00525)

启动监听器无法打开,报错! 1 [[email protected] ~]$ lsnrctl start 2 3 LSNRCTL for Linux: Version 11.2.0.1.0 - Production on 06-AUG-2014 19:40:52 4 5 Copyright (c) 1991, 2009, Oracle. All rights reserved. 6 7 Starting /opt/oracle/11g/bin/tnslsnr: please wait... 8

TimerTask定时任务

web.xml <listener> <listener-class>com.sign.listener.NFDFlightDataTaskListener</listener-class> </listener> 监听器类 package com.sign.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; impo

linux 定时执行shell脚本 定时任务

本文讲述crontab具体用法,以供备忘. 在oracle 中可以利用dbms_job包定时执行pl/sql.sql过程,在像备份等需要在操作系统级定时任务只能采用crontab来完成 利用crontab来定时执行任务大致有如下三步: 1.编写shell脚本 2.利用crontab加入到定时任务队列 3.查看作业完成情况 一.如何建立shell脚本 linux下有很多不同的shell,但我们通常使用bash(bourne again shell)进行编程,因为bash是免费的并且很容易使用 程序

Oracle 监听器无法启动(TNS-12537,TNS-12560,TNS-00507)

Oracle启动监听报错,提示 连接中断 [[email protected] ~]$ lsnrctl start LSNRCTL for Linux: Version 11.2.0.1.0 - Production on 06-AUG-2014 20:02:16 Copyright (c) 1991, 2009, Oracle. All rights reserved. Starting /opt/oracle/11g/bin/tnslsnr: please wait... TNS-12537

listener监听器

前言:之前写了一篇关于Filter的文章:http://tianweili.github.io/blog/2015/01/26/java-filter/,现在再来一篇Listener的,Filter和Listener在项目中是经常用到的,巧妙的使用可以达到事半功倍的效果.故把两者的用法总结一下. 原文链接:http://tianweili.github.io/blog/2015/01/27/java-listener/ 1.Listener的定义与作用 监听器Listener就是在applica

Java中的Listener 监听器

Listener的定义与作用 监听器Listener就是在application,session,request三个对象创建.销毁或者往其中添加修改删除属性时自动执行代码的功能组件. Listener是Servlet的监听器,可以监听客户端的请求,服务端的操作等. Listener的分类与使用 主要有以下三类: ServletContext监听 ServletContextListener:用于对Servlet整个上下文进行监听(创建.销毁). //上下文初始化 public void cont

使用监听器来启动spring

问题: 数据初始化监听器要注入spring容器的对象,必须先启动spring容器才能使用监听器初始化数据. 解决: 使用监听器来启动spring框架 问题:spring框架启动需要哪些参数? 1.需要指定配置文件或者配置类的位置 2.如果是使用注解的配置累,需要修改容器的类型 问题:监听器是不支持初始化参数的.参数如何传递到监听器里面? 答:通过设置再全局上下文参数里面,ContextLoaderListener监听器是通过获得上下文参数来解决这个问题的 <context-param> <

Centos定时启动和清除任务

因为需要定时并发执行任务,所以查到了crontab这个工具,介绍一下其用法: SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ # run-parts 01 * * * * root run-parts /etc/cron.hourly 02 4 * * * root run-parts /etc/cron.daily 22 4 * * 0 root run-parts /etc/cron.weekly 4