spring容器加载完成之后进行开启一个线程进行数据更新操作

原文:https://blog.csdn.net/wumanxin2018/article/details/80367948

 

最近在公司做项目时遇到一个问题,需要在Spring框架启动后启动一个线程接受别的系统发来的消息。因为这个线程里还需要处理自己的业务逻辑,所以会用到别的bean。 查找资料后又如下几种方式可以实现。

1. 使用Spring的InitializingBean 接口来实现

package com.irisian.picturelabel.listener;

import com.irisian.picturelabel.service.PictureService;
import com.irisian.picturelabel.service.TaskService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* Author:吴满心
* Date:2018/5/18
* Function:负责在spring容器加载完成之后进行图片和任务数据表的更新
*/
@Component
public class SpringFinishedListener implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(SpringFinishedListener.class);

@Autowired
private PictureService pictureService;

@Autowired
private TaskService taskService;

@Override
public void afterPropertiesSet() throws Exception {
new Thread(() -> {
while (true) {
logger.info("开始执行图片和任务的更新操作!");
try {
pictureService.updatePictureStatus();
//更新任务的完成状态信息
taskService.updateFinishStatus();
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage());
}
try {
Thread.sleep(1800000); //30分钟执行一次进行数据更新
} catch (InterruptedException e) {
e.printStackTrace();
logger.error(e.getMessage());
}
}
}).start();


}
}


2.开始还尝试过servlet的方法,如

package com.irisian.picturelabel.servlet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;

/**
 * Author:吴满心
 * Date:2018/5/18
 * Function:
 */
@WebServlet(name = "backServlet", urlPatterns = {"/backServlet"})
public class BackServlet extends HttpServlet {
    private static final Logger logger= LoggerFactory.getLogger(BackServlet.class);

    @Override
    public void init() throws ServletException {
        new Thread(()->{
            while(true){
                logger.info("我5秒钟执行一次");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    logger.error(e.getMessage());
                }
            }
        }).start();
    }


    @Override
    public void destroy() {
        logger.info("服务器关闭了");
    }
}

配置Configuration

package com.irisian.picturelabel.configuration;
import com.irisian.picturelabel.exception.MyExceptionResolver;
import com.irisian.picturelabel.servlet.BackServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerExceptionResolver;

/**
 * Author:吴满心
 * Date:2018/5/15
 * Function:
 */
@Configuration
public class SpringConfiguration {
    @Bean
    public HandlerExceptionResolver getHandlerExceptionResolver() {
        return new MyExceptionResolver();
    }

    /**
     * 配置一个后台运行的servlet
     * @return
     */
    @Bean
    public ServletRegistrationBean servletRegistrationBean() {
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new BackServlet(), "/backServlet");
        servletRegistrationBean.setLoadOnStartup(1);        //数字越小,启动优先级越高,但是必须大于0
        return servletRegistrationBean;
    }

}


3.尝试用listener方式是比较常用的。实际上,servelet API 提供了大量监听器来监听web应用的内部事件,从而允许当web应用内部事件发生时而回调监听器的方法,常见的事件有:web应用被启动、web应用被停止、用session开始、用户session结束、用户请求到达等。

其中ServletContextListener用于web应用的启动和关闭。对于我们刚刚提及的需求,我们需要在web应用启动的时候就开始启动后台的服务线程。

    ServletContextListener有两个常用的方法:

    void contextInitialized(ServletContextEvent sce)

    这个方法在Container初始化整个Web应用时调用,运行在该Web应用中servlet和filter初始化之前

    void contextDestroyed(ServletContextEvent sce)

    这个方法在Container卸载整个Web应用时调用,运行在该Web应用中servlet和filter的destroy()方法之后

例子:

    首先定义一个后台的服务线程

public class run implements Runnable{

 @Override
 public void run() {
  while(true){
   try {
       Thread.sleep(5000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
    System.out.println("you mother call you to go home to eat......")
  }

 }

}

    定义一个listener类

package com.cims; 
 
import javax.servlet.ServletContextEvent; 
import javax.servlet.ServletContextListener; 
 
 
public class MyListener implements ServletContextListener {  
    public void contextDestroyed(ServletContextEvent e) {   
    } 
 
    public void contextInitialized(ServletContextEvent e) {  
            System.out.println("------------web start-------");

            new Thread(new run()).start();

    } 

最后需要在web.xml进行一下配置:

Web应用启动时,后台自动启动一个线程
启动项目,会输出你想要的内容。

 

posted on   Msea  阅读(3027)  评论(0编辑  收藏  举报

(评论功能已被禁用)
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示