java web 三要素 Filter, Servlet 前面分别进行了介绍,接下来我们看一下 Listener 的相关知识点,本篇博文主要内容为 SpringBoot 环境下,如何自定义 Listener 并注册到 spring 容器
I. 环境配置
1. 项目搭建
首先我们需要搭建一个 web 工程,以方便后续的 servelt 注册的实例演示,可以通过 spring boot 官网创建工程,也可以建立一个 maven 工程,在 pom.xml 中如下配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
II. Listener 注册
我们这里说到的 Listener 专指 java web 相关的监听器,与 Spring 本身的 Listener 并不一样。在 java web 中 Listener 的知识点为 servlet 规范的那一套,这里不详细展开。下面主要介绍在 SpringBoot 中使用 Servlet Listener 的四种方式
1. WebListener 注解
@WebListener
注解为 Servlet3+提供的注解,可以标识一个类为 Listener,使用姿势和前面的 Listener、Filter 并没有太大的区别
@WebListener
public class AnoContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("@WebListener context 初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("@WebListener context 销毁");
}
}
因为 WebListener 注解不是 spring 的规范,所以为了识别它,需要在启动类上添加注解@ServletComponentScan
@ServletComponentScan
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
2. 普通 bean
第二种使用方式是将 Listener 当成一个普通的 spring bean,spring boot 会自动将其包装为ServletListenerRegistrationBean
对象
@Component
public class BeanContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("bean context 初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("bean context 销毁");
}
}
3. ServletListenerRegistrationBean
通过 java config 来主动将一个普通的 Listener 对象,塞入ServletListenerRegistrationBean
对象,创建为 spring 的 bean 对象
public class ConfigContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("config context 初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("java context 销毁");
}
}
上面只是一个普通的类定义,下面的 bean 创建才是关键点
@Bean
public ServletListenerRegistrationBean configContextListener() {
ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();
bean.setListener(new ConfigContextListener());
return bean;
}
4. ServletContextInitializer
这里主要是借助在 ServletContext 上下文创建的实际,主动的向其中添加 Filter,Servlet, Listener,从而实现一种主动注册的效果
public class SelfContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContextInitializer context 初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContextInitializer context 销毁");
}
}
@Component
public class ExtendServletConfigInitializer implements ServletContextInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.addListener(SelfContextListener.class);
}
}
注意 ExtendServletConfigInitializer 的主动注册时机,在启动时添加了这个 Listenrer,所以它的优先级会是最高
5. 测试
上面介绍了四种注册方式,都可以生效,在我们的实际开发中,按需选择一种即可,不太建议多种方式混合使用;
项目启动和关闭之后,输出日志如下
II. 其他
web 系列博文
191120-SpringBoot 系列教程 Web 篇之开启 GZIP 数据压缩[1]
191018-SpringBoot 系列教程 web 篇之过滤器 Filter 使用指南扩展篇[2]
191012-SpringBoot 系列教程 web 篇之自定义异常处理 HandlerExceptionResolver
190213-SpringBoot 文件上传异常之提示 The temporary upload location xxx is not valid
项目源码
工程:https://github.com/liuyueyi/spring-boot-demo[3]
项目:https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/212-web-listener[4]
1. 一灰灰 Blog
尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现 bug 或者有更好的建议,欢迎批评指正,不吝感激
下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
一灰灰 Blog 个人博客 https://blog.hhui.top[5]
一灰灰 Blog-Spring 专题博客 http://spring.hhui.top[6]
![](https://i-blog.csdnimg.cn/blog_migrate/7f4f13c33da63e5b4dd239291b44d7ce.png)
参考资料
[1]
191120-SpringBoot系列教程Web篇之开启GZIP数据压缩: http://spring.hhui.top/spring-blog/2019/11/20/191120-SpringBoot%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8BWeb%E7%AF%87%E4%B9%8B%E5%BC%80%E5%90%AFGZIP%E6%95%B0%E6%8D%AE%E5%8E%8B%E7%BC%A9/
[2]191018-SpringBoot系列教程web篇之过滤器Filter使用指南扩展篇: http://spring.hhui.top/spring-blog/2019/10/18/191018-SpringBoot%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8Bweb%E7%AF%87%E4%B9%8B%E8%BF%87%E6%BB%A4%E5%99%A8Filter%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97%E6%89%A9%E5%B1%95%E7%AF%87/
[3]https://github.com/liuyueyi/spring-boot-demo: https://github.com/liuyueyi/spring-boot-demo
[4]https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/212-web-listener: https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/212-web-listener
[5]https://blog.hhui.top: https://blog.hhui.top
[6]http://spring.hhui.top: http://spring.hhui.top