Filter和Listener是Servlet规范里的两个高级特性,可认为是servlet的一种“加强版”。它们不同于servlet,Filter不进行处理客户端请求,只是对用户请求进行预处理,也可对响应进行后处理,或者是对context、session、request事件进行监听。很好地使用这两个高级特性可轻松解决一些特殊问题。
一、过滤器Filter
我们很少会用Filter相用户请求生成响应,使用Filter的完整的流程是:Filter对用户请求进行预处理,接着将请求交给servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
ServletFilte体现的是设计模式中的Filter模式。一个FilterChain包括多个Filter,请求是在抵达Servlet之前会经过FilterChain里的所有Filter,响应也会在抵达客户端浏览器之前经过FilterChain里的所有Filter。一个Filter必须实现javax.servlet.Filter接口,该接口中定义了三个方法:init(),destroy(),doFilter(),要实现过滤功能,就要对每个请求响应增进行外的处理,这三个方法也反映了Filter的生命周期,其中init()和destroy()方法只会被调用一次,分别在web程序加载或者卸载的时候调用。转载doFilter()方法每次有客户端请求都会被调用一次。Filter所有工作都集中在doFilter()方法中了。Filter可以拦截多个请求或响应,一个请求或响应也可被多个Filter拦截。
Filter有如下几种用途:
在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest,
根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据,
在HttpServletResponse到达客户端之前,拦截HttpServletResponse,
根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。
Filter有如下几类:
用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求。
日志Filter:详细记录某些特殊的用户请求。
负责解码的Filter:包括对非标准编码的请求解码。
XSLT Filter,Gzip压缩Filter等
Filter的使用配置: 自定义的Filter需要实现Filter接口,将自己的逻辑写入到doFilter中,如 chain.doFilter(request,response);
像servlet一样,类似的配置如下:
<filter>
<filter-class>com.demo.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在<filter-mapping>里有个 <dispatcher>配置,其配置到达Servlet的方式,有4种取值:REQUEST,FORWARD,INCLUDE,ERROR,可以同时配置多个<dispatcher>,如果没有配置默认使用REQUEST,它们的区别如下:
REQUEST:表示仅当直接请求Servlet时才生效
FORWARD:表示仅当某Servlet通过forward到该Servlet时才生效
INCLUDE:JSP中可以通过<jsp:include/>请求某Servlet,仅这种情况下有效
ERROR:JSP中可以通过<%@ page errorPage="error.jsp" %>指定错误处理页面,仅在这种情况下才有效。
另外,<url-pattern>与<dispatcher>的关系是“且” 的关系,只有两者都满足了,Filter才能生效。Filter的配置是有先后顺序的,配置在前的早于后面的执行,而且多个Filter之间会相互影响。
二)监听器Listener
Listener用于监听java web程序中的事件,例如创建、修改、删除Session、Request、Context等,并触发相应的事件,Servlet提供了大量的监听器API,Listener对象设计模式中的Listener模式。
使用相应的Listener需要实现相应的Listener接口,当事件发生的时候会自动触发该事件对应的Listener。servlet规范中有8种Listener,分别用于监听Request、Session、 Context等创建与销毁、属性变化等,而且还可以监听Session中的对象。
ServletContextListener:用于监听Web应用的启动和关闭,ContextInitialized,ContextDestroyed
HttpSession Listener:用于监听用户Session的开始和结束,sessionCreated,sessionDestroyed
ServletRequestListener:用于监听用户请求,requestInitialized,requestDestroyed
另外还有三个监听器用于监听对象的属性变化,有ServletRequestAttributeListener ,HttpSessionAttributeListener,ServletContextAttributeListener ,当想被监听的对象中添加、删除、更新属性时,会分别执行xxxAdded(),xxxReplaced(),xxxRemoved()方法。
HttpSessionBindingListener与HttpSessionActivationListener用来监控Session内的对象,它们的触发时机分别为:
HttpSessionBindingListener:当对象被放到Session里是执行valueBound()方法,当对象被从Session里移除时执行valueUnbound()方法。HttpSessionActivationListener:服务器关闭时,会将Session里的内容保存到硬盘上,这个过程叫钝化,服务器重新启动时,会将Session内容从硬盘上重新加载,当Session里的对象被钝化时会执行sessionWillPassivate()方法,当对象被重新加载时执行sessionDidActivate()方法。 对象必须实现Listener接口。
我们使用Listener时仍然需要配置:
<listener>
</listener>
Listener和Filter与Servlet、JSP等没有业务耦合, 可自由拆卸,合理设计Listener和Filter会使程序更高效!