Java Web Listener

0x01 Java Web中有三个不同的角色

  • Servlet是处理用户请求的载体,根据url映射将请求参数发给对应servlet进行数据处理并返回response
  • Filter介于web容器(Tomcat、Jetty等)和Servlet之间,主要是在请求到达servlet之前捕获HttpRequest进行预先处理,比较常见的filter是Login验证、CharacterEncodingFilter
  • Listener独立于Servlet和Filter之外,不存在先后关系。Listener是一种观察者模式,贯穿web应用的整个生命周期。主要作用是定义一系列事件,并对事件进行监听处理

0x02 8种Listener

Listener 说明
ServletContextListener 用于监听ServletContext的启动和销毁
ServletContextAttributeListener 用于监听Application范围属性变化
HttpSessionListener 用于监听Session的创建和销毁
HttpSessionIdListener 用于监听Session的id是否被更改
HttpSessionAttributeListener 用于监听session范围属性变化
HttpSessionActivationListener 用于监听绑定在HttpSession对象中的JavaBean状态
HttpSessionBindingListener 用于监听对象与session的绑定和解绑
ServletRequestListener 用于监听ServletRequest对象的初始化和销毁
ServletRequestAttributeListener 用于监听ServletRequest对象的属性变化

0x03 着重看ServletContextListener

这个Listener的作用是监听ServletContext的启动和销毁,也就是监听web应用的开始和结束。所以通常会使用这个监听器初始化工程和结束工程。
这里着重讲两个例子:

Log4jConfigListener:
如果在web.xml设置了这个监听,那么会对日志系统进行初始化,而日志的配置文件路径通过Context-param进行设置

1
2
3
4
5
6
7
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:soc-log4j.xml</param-value>
</context-param>

这里多说一嘴原理,context-param的设置会形成initParameters(Map<String,String>)存在ServletContext中,Log4jConfigListener读取到配置文件的路径即可进行初始化。初始化使用的是DOMConfigurator的configureAndWatch方法。这里是在web工程中初始化日志配置,web容器(tomcat、jetty等)会加载web.xml进行初始化,进而加载Log4jConfigListener,进而对日志进行初始化。但是在普通Java项目中,没有上述这一系列过程,所以需要自己手动加载log配置文件初始化配置,具体的过程就是使用DOMConfigurator调用configureAndWatch方法。

ContextLoaderListener
这个Listener需要和DispatcherServlet一起说明。
对于一个Spring项目(非mvc),只需要使用ContextLoaderListener对spring配置进行初始化

1
2
3
4
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring.xml</param-value>
</context-param>

主要作用是加载Bean并进行管理。在这个过程中会生成一个WebApplicationContext父容器。

总的说来:

  • DispatherServlet是Spring mvc工程不可缺少的,Spring MVC配置文件在基础上Spring上有所扩展,所以使用DispatcherServlet对Controller等进行初始化,并根据MVC的初始化过程(初始化文件传输、国际化、映射管理器、异常处理器、视图映射等)。
  • DispatherServlet也会生成一个WebApplicationContext,但是此Context是ContextLoaderListener生成的WebApplicationContext的子ApplicationContext。
  • 两个WebApplicationContext分别加载不同的Spring配置,生成不同的BeanFactory,所以在获取Bean的时候,会先从DispatcherServlet的WebApplicationContext中查找,如果没有再通过父ApplicationContext进行查找。