昨天遇到这个问题,在项目启动的时候添加一个定时器隔一段时间扫描有没有定时发送的邮件(当然也可以是你自己的业务逻辑),也在网上找了资料,加上自己的修改,终于成功了。所以来做个记录。

1、ServletContextListener

我们需要在web容器启动的时候,就添加自己的业务。那么有没有一个类或接口能监听web容器的生命周期呢?当然是有的,在Servlet API 中有一个 ServletContextListener 接口,它能够监听 ServletContext 对象的生命周期,也就满足我们的要求。

2、WebApplicationContext

ApplicationContext是Spring的核心,Context我们通常解释为上下文环境,我想用“容器”来表述它更容易理解一些,ApplicationContext则是“应用的容器”了;在Web应用中,我们会用到WebApplicationContext,WebApplicationContext继承自ApplicationContext;WebApplicationContext的初始化方式和BeanFactory.ApplicationContext有所区别,因为WebApplicationContext需要ServletContext实例,也就是说它必须拥有Web容器的前提下才能完成启动的工作。

3、Java代码:

 package com.defer.mail.util;

 import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.defer.mail.domain.Email;
import com.defer.mail.domain.User;
import com.defer.mail.service.EmailService;
import com.defer.mail.service.UserService;
public class SendEmailTimer implements ServletContextListener{ private Timer timer = null; /**
* @Name: contextInitialized
* @Description:容器初始化
**/
@Override
public void contextInitialized(ServletContextEvent event) {
//通过给spring的WebApplicationContextUtils传入ServletContext的监听对象来获取获取当前的web容器
WebApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext());
//创建定时器
timer = new Timer(true);
System.out.println("定时器已经启动");
//设定每7200秒查询一次是否有定时发送邮件
timer.schedule(new QuerySendEmail(ac), 0, 7200*1000);
System.out.println("已经添加查询任务");
} /**
* ClassName: QuerySendEmail
* @Description: 业务类,继承TimerTask类,添加自己的业务
*/
private static class QuerySendEmail extends TimerTask {
private static boolean isRunning = false;
private WebApplicationContext context = null; public QuerySendEmail(WebApplicationContext context) {
this.context = context;
} @SuppressWarnings("static-access")
@Override
public void run() {
if(!isRunning) {
isRunning = true;
// TODO 自己的业务流程
EmailService emailService = (EmailService) context.getBean("emailServiceImpl");
UserService userService = (UserService) context.getBean("userServiceImpl");
List<Email> emailList = emailService.findNoSendEmail();
if(emailList != null && emailList.size() >0) {
for (Email email : emailList) {
User user = userService.getById(email.getUser().getId());
String fromUser = user.getEmail();
String code = email.getCode();
String topic = email.getTopic();
String content = email.getContent();
String toUser = email.getToUser();
SendEmail sendEmail = new SendEmail();
boolean status = false;
while(status==false) { status = sendEmail.sendEmail(fromUser, toUser, code, topic, content);
if(status) {
email.setStatus("1"); //设置邮件状态为已发送
email.setSendDate(new Date()); //设置发送时间
emailService.update(email);
status = true;
System.out.println("发送成功=========");
} else {
status = false;
System.out.println("发送失败=========");
} }
}
} else {
System.out.println("没有定时邮件");
} isRunning = false;
System.out.println("查询结束");
} else {
System.out.println("上一次查询还未结束");
} } } /**
*
* @Name: contextDestroyed
* @Description:容器销毁
*/
@Override
public void contextDestroyed(ServletContextEvent servletcontextevent) {
// TODO Auto-generated method stub } }

4、虽然该类实现了ServletContextListener接口,如何让spring容器加载的时候能初始化该类中的操作呢?那肯定少不了配置spring的配置文件

 <!-- 用于定时器工作的监听器。配置在spring的ContextLoaderListener之后,因为需要用到spring的容器对象 -->
<listener>
<listener-class>
<!-- 自己的类路径 -->
com.defer.mail.util.SendEmailTimer
</listener-class>
</listener>

5、测试成功

Spring容器初始化的时候如何添加一个定时器?的更多相关文章

  1. spring容器初始化执行某个方法

    在做web项目开发中,尤其是企业级应用开发的时候,往往会在工程启动的时候做许多的前置检查. 比如检查是否使用了我们组禁止使用的Mysql的group_concat函数,如果使用了项目就不能启动,并指出 ...

  2. 当spring 容器初始化完成后执行某个方法

    在做web项目开发中,尤其是企业级应用开发的时候,往往会在工程启动的时候做许多的前置检查. 比如检查是否使用了我们组禁止使用的Mysql的group_concat函数,如果使用了项目就不能启动,并指出 ...

  3. 当spring 容器初始化完成后执行某个方法 防止onApplicationEvent方法被执行两次

    在做web项目开发中,尤其是企业级应用开发的时候,往往会在工程启动的时候做许多的前置检查. 比如检查是否使用了我们组禁止使用的Mysql的group_concat函数,如果使用了项目就不能启动,并指出 ...

  4. 【sping揭秘】3、Spring容器中bean默认是保持一个实例

    Spring容器中bean默认是保持一个实例 这里做一个测试,基础代码 package cn.cutter.start.provider; import org.springframework.con ...

  5. spring容器初始化bean和销毁bean之前进行一些操作的定义方法

    关于在spring  容器初始化 bean 和销毁前所做的操作定义方式有三种:        第一种,通过在xml中定义init-method和destory-method方法        第二种, ...

  6. 【Spring实战】Spring容器初始化完成后执行初始化数据方法

    一.背景知识及需求 在做WEB项目时,经常在项目第一次启动时利用WEB容器的监听.Servlet加载初始化等切入点为数据库准备数据,这些初始化数据是系统开始运行前必须的数据,例如权限组.系统选项.默认 ...

  7. Spring容器初始化数据(数据库)BeanPostProcessor的应用

    1.目的:在Spring启动的时候加载在数据库保存的配置信息,一方面杜绝随意修改,一方面方便管理 2.BeanPostProcessor是Spring提供的一个方法通过implements方式实现 会 ...

  8. ApplicationListener接口,在spring容器初始化后执行的方法

    一.如果我们希望在Spring容器将所有的Bean都初始化完成之后,做一些操作,那么就可以使用ApplicationListener接口,实现ApplicationListener接口中的onAppl ...

  9. Spring容器初始化过程

    一.Spring 容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配号Bean之间的依 ...

随机推荐

  1. 解决gremlin-dirver访问tinkerpop服务器提示序列化错误

    解决gremlin-dirver访问tinkerpop服务器提示序列化错误 问题描述 程序集成了gremlin-driver,访问远程tinkerpop服务器,在执行创建节点操作时,返回如下错误栈: ...

  2. Apache服务器 403 Forbidden的几种错误原因小结!

    403 Forbidden错误原因详解 403 - Forbidden(禁止访问),服务器拒绝请求 - forbidden request (matches a deny filter) => ...

  3. VirtualBox虚拟机和主机之间的通信

    - VirtualBox的NAT网络模式,主机不能访问虚拟机- 端口转发可以访问,但是性能非常差,第一次连接30秒左右- 有条件的还是推荐VmWare

  4. PHP学习笔记(5)GD库画验证码

    <?php header("content-type:image/png"); $width = 500; $height = 500; $img = imagecreate ...

  5. Win7下 OpenCV+Qt开发环境搭建

    1.所需软件工具: (1)OpenCV开发库,2.4.9版:包括源文件(source文件夹)和编译后的文件(build文件夹),但最好自己使用CMake又一次编译.否则easy出错. (2)Qt Cr ...

  6. 查看网络连接数目(解决TIME_WAIT过多造成的问题_转)

      转自:解决TIME_WAIT过多造成的问题 (eroswang的csdn) #netstat -n | awk '/^tcp/ {++S[$NF]} END { for(a in S) print ...

  7. quick-cocos2d-x的热更新机制实现

    quick-cocos2d-x的热更新机制实现 0 依赖 这里说的热更新,指的是客户端的更新. 大致的流程是,客户端在启动后访问更新api,根据更新api的反馈,下载更新资源,然后使用新的资源启动客户 ...

  8. telnet master主机的NodePort服务不通的问题

    硬件环境: 两台物理机: 172.16.114.210(master主机) 172.16.114.211(node主机) 软件环境: kubernetes 1.5.2 flannel 0.5.5 问题 ...

  9. nginx 为什么要反向代理 影藏后端 高效连接(给nginx,他自己返回) 端口冲突解决 多个服务

    nginx 为什么要反向代理  影藏后端   高效连接(给nginx,他自己返回)  端口冲突解决  多个服务 单机使用反向代理可以根据不同url匹配到不同站点   rsync 的工作原理和应用实例 ...

  10. R语言安装sqldb包报错解决办法

    我使用Rtudio环境,安装sqldb几次出错.网上没有好的教程. 经过自己试验之后,这样处理.我写出来以后,供大家参考. > install.packages("sqldf" ...