ServletContext
ServletContext 被 Servlet
程序用来与 Web
容器通信。例如写日志,转发请求。每一个 Web
应用程序含有一个Context
,被Web
应用内的各个程序共享。因为Context
可以用来保存资源并且共享,所以ServletContext
的最大应用是Web缓存----把不经常更改的内容读入内存,所以服务器响应请求的时候就不需要进行慢速的磁盘I/O
了。
ServletContextListener
ServletContextListener 是 ServletContext
的监听者,如果 ServletContext
发生变化,如服务器启动时 ServletContext
被创建,就会调用contextInitialized()
方法,服务器关闭时 ServletContext
将要被销毁,serveltContextListener
就会调用contextDestroyed()
。
ServletContextListener源码
public interface ServletContextListener extends EventListener {
default void contextInitialized(ServletContextEvent sce) {
}
default void contextDestroyed(ServletContextEvent sce) {
}
}
ServletContextListener监听器实现代码
非springboot下
public class FirstListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized");
}
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed");
}
}
然后在web.xml
中配置监听器
<listener>
<listener-class>监听器类所在路径.监听器名字</listener-class>
</listener>
SpringBoot支持Servlet3.0
,Servlet3.0
中的监听器跟之前2.5
的差别不大,唯一的区别就是增加了对注解的支持。在3.0
以前监听器配置都是需要配置在web.xml
文件中的。在3.0
中有了更多的选择,之前在web.xml
文件中配置的方式还是可以的,同时还可以使用注解进行配置。对于使用注解的监听器就是在监听器类上使用@WebListener
进行标注,这样Web
容器就会把它当做一个监听器进行注册和使用了。
在SpringBoot中需要加上@WebListener
@WebListener
public class FirstListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed");
}
}
注:记得在启动类加上@ServletComponentScan
原因是:Servlet
、Filter
、Listener
可以直接通过 @WebServlet
、@WebFilter
、@WebListener
注解自动注册,无需其他代码
启动测试
可以看到在tomcat启动前把contextInitialized
在控制台输出
contextDestroyed()
没调用问题
想输出contextDestroyed
是不是把项目关掉就好了呢,结果是不行的,直接停止程序或者杀掉进程都是不会执行contextDestroyed()
,在contextDestroyed
中添加LOG
也没有运行
原因
不能直接关闭Tomcat
,而是应该用shutdown.bat
来关闭Tomcat
,但是SpringBoot
中是采用内置Tomcat
,怎么去shutdown
呢?
解决方法
引入spring-boot-starter-actuator
监控系统健康情况依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在application.yml
配置文件中设置
management:
endpoints:
web:
exposure:
include: shutdown
endpoint:
shutdown:
enabled: true
Spring Boot包含许多内置端点,默认情况下,除了shutdown
以外的所有端点都已启用
management.endpoint.shutdown.enabled
默认是false
,也就是关闭shutdown
端点,设置为ture
让端点打开
management.endpoints.web.exposure.include
:该include
属性列出了公开的端点的ID。而exclude
属性列出了不应该公开的端点的ID
。这里用来打开shutdown
端点,如果全部端点都打开可以使用*
更多端点可以参考
https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html
通过http请求来停止应用
http://IP地址:端口号/actuator/shutdown
,使用POST
请求
响应结果
{
"message": "Shutting down, bye..."
}
正常执行contextDestroyed()
,控制台正常输出contextDestroyed
,此时程序也停止了
Application(ServletContext)
作用域:所有的用户都可以取得此信息,此信息在整个服务器上被保留。Application
属性范围值,只要设置一次,则所有的网页窗口都可以取得数据。
一个JavaWeb
应用只创建一个ServletContext
对象,所有的客户端在访问服务器时都共享同一个ServletContext
对象;ServletContext
对象一般用于在多个客户端间共享数据时使用;所以application
的作用域是最大的
ServletContext
具体方法和使用可参考官方文档:
https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletContext.html