springboot2启动时执行,初始化(或定时任务)servletContext问题
作者:亦寒2017 发布时间:2022-10-18 13:14:30
springboot2启动时执行,初始化(或定时任务)servletContext
需求:springboot 启动后自动执行,初始化数据,并将数据放到 servletContext 中。
首先,不可使用 ServletContextListener 即不能用 @WebListener ,因为 servlet 容器初始化后,spring 并未初始化完毕,不能使用 @Autowired 注入 spring 的对象。
代码如下:
可以实现 ApplicationListener
@Component
public class SettingDataInitListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
WebApplicationContext webApplicationContext =
(WebApplicationContext)contextRefreshedEvent.getApplicationContext();
ServletContext servletContext = webApplicationContext.getServletContext();
servletContext.setAttribute("key", "value");
}
}
使用注解注入
service
类里注入 servletContext
@Autowired private ServletContext servletContext;
service
类里要启动执行的方法加上注解
@PostConstruct
在定时任务里,也可以注入 servletContext,进行定时操作
@Component
public class MyTask {
@Autowired
private ServletContext servletContext;
// 秒 分 时 日 月 周
@Scheduled(cron = "0 * * * * *")
public void resetDays() {
// servletContext
}
}
springboot启动时初始化数据的几种方式
在我们用springboot搭建项目的时候,经常碰到在项目启动时初始化一些字典数据、地市数据、等各类需求,针对这种需求Spring与Spring boot为我们提供了以下几种方案供我们选择:
springboot提供的ApplicationRunner与CommandLineRunner接口
Spring Bean初始化的init-method、PostConstruct注解、
InitializingBean、BeanPostProcessor接口
Spring的事件机制: 实现 ApplicationListener 接口
一、ApplicationRunner与CommandLineRunner
如果需要在SpringApplication启动时执行一些特殊的代码,可以通过实现ApplicationRunner或CommandLineRunner接口,这两个接口都提供单一的run方法,且run方法仅在SpringApplication.run(…)完成之前调用。
区别:参数不一样,CommandLineRunner的参数是最原始的参数,没有进行任何处理,ApplicationRunner的参数是ApplicationArguments
ApplicationRunner接口只需要自己创建类实现ApplicationRunner接口
/**
* @author 重庆阿汤哥
* @Description: 测试
* @date 2021/11/26
*/
@Component
@Slf4j
public class ApplicationRunnerTest implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("ApplicationRunner init data.....");
}
}
CommandLineRunner
对于这个接口而言,我们可以通过Order注解或者使用Ordered接口来指定调用顺序,@Order()中的值越小,优先级越高
/**
* @author 重庆阿汤哥
* @Description: 测试
* @date 2021/11/26
*/
@Component
@Slf4j
@Order(1)
public class CommandLineRunnerTest implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
log.info("CommandLineRunner init data.....");
}
}
二、Spring Bean初始化的InitializingBean,init-method和PostConstruct
InitializingBean接口、BeanPostProcessor接口
InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet()方法。
在spring初始化bean的时候,如果bean实现了InitializingBean接口,在对象的所有属性被初始化后之后才会调用afterPropertiesSet()方法
/**
* @author 重庆阿汤哥
* @Description: 测试
* @date 2021/11/26
*/
@Component
@Slf4j
@Component
public class InitialingzingBeanTest implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
log.info("InitializingBean init....");
}
}
@PostConstruct
/**
* @author 重庆阿汤哥
* @Description: 测试
* @date 2021/11/26
*/
@Component
@Slf4j
public class DynamicRouteMonitor {
@PostConstruct
public void init() {
log.info("gateway route init...");
}
}
BeanPostProcessor接口
可以用于判断某些特定类加载完成后才能初始化数据的场景,只需要自己实现该接口中的方法进行前置条件判断
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
三、Spring的事件机制
在Spring中,默认对ApplicationEvent事件提供了如下支持:
ContextStartedEvent
:ApplicationContext启动后触发的事件ContextStoppedEvent
:ApplicationContext停止后触发的事件ContextRefreshedEvent
:ApplicationContext初始化或刷新完成后触发的事件;也就是容器初始化完成后调用。ContextClosedEvent
:ApplicationContext关闭后触发的事件;如web容器关闭时自动会触发spring容器的关闭。甚至大家听说过的钩子程序都是调用ctx.registerShutdownHook()进行注册虚拟机关闭。
利用ContextRefreshedEvent事件进行初始化操作
/**
* @author 重庆阿汤哥
* @Description:容器初始化完整后初始字典数据
* @date 2021/11/26 10:51
*/
@Component
public class ApplicationStartup implements ApplicationListener<ContextRefreshedEvent> {
public void onApplicationEvent(ContextRefreshedEvent event) {
//在容器加载完毕后获取dao层来操作数据库
ISysDictTypeService sysDictTypeService = (ISysDictTypeService) event.getApplicationContext().getBean(ISysDictTypeService.class);
sysDictTypeService.initDict();
IProvCityService provCityService = (IProvCityService) event.getApplicationContext().getBean(IProvCityService.class);
provCityService.initProvCity();
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
这几种方式都可以满足我们日常开发的需求,针对具体场景使用对应的方案,在微服务应用中使用也较广泛。
来源:https://blog.csdn.net/m0_37202351/article/details/86180998


猜你喜欢
- 一、项目搭建1、可以在新建项目的使用Spring MVC框架。或者创建一个简单的项目之后再用Add Framework Support来添加
- 微信支付最近公司要在微信公众号上做一个活动预报名,活动的门票等需要在微信中支付。微信支付前的准备微信支付需要一个微信支付商务号(https:
- 1.这是一个通过Java反射机制解析的工具类2.使用时只需创建对应的对象,并在Excel的第一行填上对应的属性名3.首先要添加相关的jar包
- 1. 引入依赖pom文件引入activemq依赖<!--activeMq配置--> &
- 一. CodeCache简介从字面意思理解就是代码缓存区,它缓存的是JIT(Just in Time)编译器编译的代码,简言之codeCac
- 一、前期工作创建工作空间 二、创建工作包创建完成后,文件夹的格式为:三、准备编译文件和代码3.1 更换编译文件中的内容将上图中的,
- ubuntu 安装jdk 的两种方法总结:1:通过ppa(源) 方式安装.2:通过官网下载安装包安装.这里推荐第1种,因为可以通过 apt-
- 本文实例讲述了Android实现在屏幕上移动图片的方法。分享给大家供大家参考。具体实现方法如下:1. Speed.java文件:packag
- 本文实例讲述了C#中派生类调用基类构造函数用法。分享给大家供大家参考。具体分析如下:这里的默认构造函数是指在没有编写构造函数的情况下系统默认
- 前言请看下面几个问题Spring为什么不推荐使用@Autowired 注解?为什么推荐使用@Resource 代替&nb
- 移动端微信消息页实现在上一篇中主界面实现说过微信四个页面中间都是是fragment的,并且四个fragment的布局都还没实现,所以这一篇主
- 在java开发的实际场景中,我们经常要对时间进行格式化处理,但是每次获取开发中自己需要的格式都要重新写一个方法,这样的代码看起来是非常的笨重
- Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都会有各自的用途,以及创建和销毁的时间,有的区
- 本文实例为大家分享了android实现录屏小功能的具体代码,供大家参考,具体内容如下思路android实现录屏功能有两种方案,一种是直接使用
- 本文实例讲述了Java模拟计算机的整数乘积计算功能。分享给大家供大家参考,具体如下:计算机计算整数乘积的原理:实现代码:package ma
- 简介本文介绍Idea如何根据maven依赖名查找它是哪个pom.xml引入的。有时候会有这样的问题:我们知道项目里用了某个依赖,想知道它是项
- Druid是数据库连接池,它能够提供强大的监控和扩展功能。官方文档Spring Boot整合第三方技术的两种方式:自定义找starter场景
- 场景最近在做数据分析项目,里面有这样一个业务:把匹配的数据打上标签,放到新的索引中。数据量:累计亿级的数据使用场景:可能会单次查询大量的数据
- 1.实现阴影或模糊边效果方式:2.通过shape来实现,具体是通过layer-list 多层叠放的方式实现的<?xml version
- 在很多其他框架中,比如Python的Flask、node.js的KOA,Controller要想能够响应前端的请求都需要我们主动去注册到应用