Listener监听器
监听器分类
- 第一类:监听请求域对象、会话域对象、全局域对象的创建与销毁
- 第二类:监听请求域对象、会话域对象、全局域对象的属性的创建、获取、销毁
- 第三类:监听会话域对象的value的绑定与解绑、活化与钝化
第一类监听器
请求域对象
创建:客户端向服务器发送请求时创建
销毁:客户端收到请求并返回响应后销毁
-
创建类
public class RequestServletListener implements ServletRequestListener { @Override public void requestDestroyed(ServletRequestEvent servletRequestEvent) { System.out.println("请求对象被销毁了" + servletRequestEvent); } @Override public void requestInitialized(ServletRequestEvent servletRequestEvent) { System.out.println("请求对象被创建了" + servletRequestEvent); } }
-
配置web.xml文件
<listener> <listener-class>ListenerClassOne.RequestServletListener</listener-class> </listener>
会话域对象
创建:当服务器使用到了session时创建
销毁:session的过期时间到了就销毁
-
创建类
public class SessionListener implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent httpSessionEvent) { System.out.println("sessionCreated" + httpSessionEvent.getSession().getId()); } @Override public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { System.out.println("sessionDestroyed" + httpSessionEvent.getSession().getId()); } }
-
配置web.xml文件
<listener> <listener-class>ListenerClassOne.SessionListener</listener-class> </listener>
全局域对象
创建:当项目启动时创建
销毁:当项目结束时销毁
使用场景:
- 初始化与配置(在web.xml中配置<context-param>标签设置参数,通过contextInitialized()方法进行一次性的初始化工作)
- 资源清理(在contextDestroyed()中执行必要的清理工作)
-
创建类
public class ServletContextListener implements javax.servlet.ServletContextListener { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { System.out.println("ServletContextListener contextInitialized"); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println("servletContextListener contextDestroyed"); } }
-
配置web.xml文件
<listener> <listener-class>ListenerClassOne.ServletContextListener</listener-class> </listener>
第二类监听器
三种监听器都是请求域对象、会话域对象、全局域对象的属性的创建、替换、删除动作进行监听
请求域对象属性
创建类
@WebListener
public class RequestAttrListener implements ServletRequestAttributeListener {
@Override
public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
String name = servletRequestAttributeEvent.getName();
Object value = servletRequestAttributeEvent.getValue();
System.out.println("request attribute Added: " + name + ":" + value);
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
String name = servletRequestAttributeEvent.getName();
Object value = servletRequestAttributeEvent.getValue();
System.out.println("request attribute removed: " + name + ":" + value);
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
String name = servletRequestAttributeEvent.getName();
Object value = servletRequestAttributeEvent.getValue();
System.out.println("request attribute replaced: " + name + ":" + value);
}
}
会话域对象属性
@WebListener
public class SessionAttrListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
String name = httpSessionBindingEvent.getName();
Object value = httpSessionBindingEvent.getValue();
System.out.println("session Attribute Added" + name + ":" + value);
}
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
String name = httpSessionBindingEvent.getName();
Object value = httpSessionBindingEvent.getValue();
System.out.println("session Attribute Removed" + name + ":" + value);
}
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
String name = httpSessionBindingEvent.getName();
Object value = httpSessionBindingEvent.getValue();
System.out.println("session Attribute Replaced" + name + ":" + value);
}
}
全剧域对象属性
@WebListener
public class ServletContextAttrListener implements ServletRequestAttributeListener {
@Override
public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
String name = servletRequestAttributeEvent.getName();
Object value = servletRequestAttributeEvent.getValue();
System.out.println("application attribute Added: " + name + ":" + value);
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
String name = servletRequestAttributeEvent.getName();
Object value = servletRequestAttributeEvent.getValue();
System.out.println("application attribute removed: " + name + ":" + value);
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
String name = servletRequestAttributeEvent.getName();
Object value = servletRequestAttributeEvent.getValue();
System.out.println("application attribute replaced: " + name + ":" + value);
}
}
第三类监听器
会话域对象的对象属性的绑定与解绑、活化与钝化
该监听器不需要进行
web.xml
进行配置或者@WebListener
注解,是针对
session
的JavaBean属性
的监听主要包括:
- 绑定与解绑
- 活化与钝化(序列化与反序列化)
假设有一个类User
,创建监听器就需要在这个实体类中实现HttpSessionBindingListener
、HttpSessionActivationListener
、Serializable
三个接口
public class User implements HttpSessionBindingListener, HttpSessionActivationListener , Serializable {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
//...........................
@Override
public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {
//从session中添加该对象属性
System.out.println(this + "被绑定了");
}
@Override
public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
//从session中移除该对象属性
System.out.println(this + "被解除绑定了");
}
@Override
public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
//钝化对象属性
System.out.println("session钝化了" + this);
}
@Override
public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
//活化对象属性
System.out.println("session活化了" + this);
}
}
活化与钝化还需要额外配置context.xml
(web\META-INF\context.xml
)
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!--
maxIdleSwap:"1": session如果1分钟没有使用就序列化
directory: 序列化后文件所保存的路径
-->
<Manager className="org.apache.catalina.session.PersistentManager"
maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore"
directory="D:\JAVA\tomcat-demo5\JavaBeanSession" />
</Manager>
</Context>
对象被序列化之后,会在directory
这个路径下生成以session
的id
为文件名,以.session
为拓展名的文件
在session的过期时间内,并且服务器正常关闭的情况下,session会钝化对象,重新启动启动服务器,session会活化对象
如果session超时,则无法活化对象;如果session调用invalidate方法,session无法钝化对象;如果服务器未正常关闭,session无法钝化对象
面试题
- 钝化:当服务器正常关闭时,还存活着的session(在设置时间内没有销毁) 会随着服务器的关闭被以文件(“SESSIONS.ser”)的形式存储在tomcat 的work 目录下,这个过程叫
做Session 的钝化。
- 活化:当服务器再次正常开启时,服务器会找到之前的“SESSIONS.ser” 文件,从中恢复之前保存起来的Session 对象,这个过程叫做Session的活化。
- 想要随着Session 被钝化、活化的对象它的类必须实现Serializable 接口,还有的是只有在服务器正常关闭的条件下,还未超时的Session 才会被钝化成文件。当Session 超时、调用invalidate方法或者服务器在非正常情况下关闭时,Session 都不会被钝化,因此也就不存在活化。
- 在被钝化成“SESSIONS.ser” 文件时,不会因为超过Session 过期时间而消失,这个文件会一直存在,等到下一次服务器开启时消失。(sesison超时,无法活化)
- 当多个Session 被钝化时,这些被钝化的Session 都被保存在一个文件中,并不会为每个Session 都建立一个文件。
Filter过滤器
-
创建类
public class MyFilter implements Filter {//继承自Filter @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("过滤器初始化"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("过滤前"); filterChain.doFilter(servletRequest, servletResponse); System.out.println("过滤后"); } @Override public void destroy() { System.out.println("过滤器被销毁了"); } }
-
在web.xml中配置
<filter> <filter-name>xxx</filter-name> <filter-class>Filter.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>xxx</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping>
Filter的生命周期
创建:项目启动时创建,先调用构造方法、然后调用init() 方法
销毁:项目正常关闭时销毁,destroy() 方法
注意:Filter是单例模式
思考题:多个Filter的创建顺序?无序,因为底层是多线程
思考题:多个Filter的调用顺序?如果使用web.xml进行配置,则是按照配置顺序(从上到下);如果使用注解@WebFilter进行配置,则是按照类名字进行字典排序
使用注解配置
@WebFilter(urlPatterns = {"/Servlet","/servlet01"}, initParams = {@WebInitParam(name = "name", value = "value")})
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤前");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("过滤后");
}
@Override
public void destroy() {
System.out.println("过滤器被销毁了");
}
}
常用参数:
- urlPatterns/value: 可以指定需要过滤的资源或者目录
- initParams:初始化参数(k-v)
使用场景
- 自动登录
- 统一编码格式
- 控制访问权限
- 敏感词过滤