过滤器
什么是过滤器
· 过滤器是Servlet2.3规范中定义的一种小型的、可插入的Web组件。用来拦截Servlet容器的请求和响应过程,以便查看、提取或以某种方式操作正在客户机和服务器之间交换的数据;
· 过滤器通常是封装了一些功能的Web组件,这些功能很重要,但对于处理客户端请求或发送响应来说不是决定性的;
· 典型的应用包括记录请求和响应的数据、管理会话属性等;
如何编写过滤器
(1)编写Java类,实现Filter类,在doFilter方法中实现拦截处理逻辑
/** * @author dream-it * 1.Filter用来处理多个请求之间的共性业务。 * 如记录日志、过滤敏感词等。 * 2.使用Filter解决问题不用修改任何Servlet, * 只需要新建Filter并配置即可,可以极大程度的 * 降低业务代码和Servlet之间的耦合度。 */ public class FirstFilter implements Filter { /** * 在tomcat关闭时自动销毁 */ public void destroy() { System.out.println("销毁FirstFilter"); } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { System.out.println("FirstFilter前"); //调用doFilter()是让请求继续执行,若没有调用此方法则请求中断,直接响应。 //请求继续执行会调用后续的Filter,并最终调用Servlet //在此过程中Filter与Filter之间是有序调用的, //并且任何Filter将请求中断,都会导致后续的Filter无法执行, //他们的关系像链条一样,环环相扣。因此该对象叫做过滤连FilterChain //详见过滤器调用过程图 chain.doFilter(req, res); System.out.println("FirstFilter后"); } /** * Filter在tomcat启动是只创建初始化一次,所以它是单例的。 * 由别人创建的对象基本都是单例的。 */ public void init(FilterConfig arg0) throws ServletException { System.out.println("初始化FirstFilter"); }
(2)将过滤器添加Web应用中
· 修改web.xml文件,增加注册过滤器的节点
<!-- 声明Filter --> <filter> <filter-name>first</filter-name> <filter-class>web.FirstFilter</filter-class> </filter> <!-- 声明此Filter可以过滤/拦截那些请求 --> <filter-mapping> <filter-name>first</filter-name> <!-- 可以拦截的Servlet的访问路径,如果写出/*就表示一切 --> <url-pattern>/*</url-pattern> </filter-mapping>
(3)过滤器和Web应用一起打包部署
· 与Web应用程序一起部署过滤器时,只需把过滤器类和其他Web组件类包括在一起;把web.xml文件(连同过滤器注册)放进web应用程序结构中,Servlet容器将处理之后的其他事情;
过滤器的执行流程
过滤器的优先级
· 如果有多个过滤器都满足过滤的条件,则容器依据<filter-mapping>的先后顺序来调用各个过滤器
<filter>...</filter> <filter>...</filter> <filter-mapping>...</filter-mapping> <filter-mapping>...</filter-mapping>
多个过滤器的执行流程
过滤器的初始化参数
· 容器启动之后,会创建过滤器实例;
· 接下来,容器会调用过滤器的init方法,而容器会事先创建FilterConfig对象。该对象可以访问web.xml文件中配置一些参数;
· 这些在web.xml文件中存储,由FilterConfig对象读取;
· 通过这些初始化参数可以方便快捷的配置及修改一些辅助参数;
初始化参数的配置
<filter> <filter-name>filter</filter-name> <filter-class>web.xxxFilter</filter-class> <!-- 给当前的filter预置一个参数 --> <init-param> <param-name>city</param-name> <param-value>北京</param-value> </init-param> </filter> <filter-mapping> <filter-name>filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
读取初始化参数
· 使用FilterConfig对象可以读取在web.xml中配置初始化参数
String config.getInitParamter("city");
过滤器的优点
· 实现代码的“可插拔性”,即增加或减少某个功能模块,不会影响程序的正常执行;
· 可以将多个相同处理逻辑的模块集中写在过滤器里面,方便代码的维护;
监听器
什么是监听器
· Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件进行相应的处理
· 容器产生的两大类事件:
- 生命周期相关事件;
- 绑定数据相关事件;
生命周期相关事件
· 容器创建或者销毁request、session、ServletContext时产生的事件;
· ServletRequestListener
requestDestroyed(ServletRequestEvent sre); requestInitialized(ServletRequestEvent sre);
· HttpSessionListener
sessionCreated(HttpSessionEvent se); sessionDestroyed(HttpSessionEvent se);
· ServletContextListener
contextDestroyed(ServletContextEvent sce); contextInitialized(ServletContextEvent sce);
注:实现不同的接口会有不同的实现;
绑定数据相关事件
· 调用request、session、ServletContext的setAttribute、removeAttribute方法时产生的事件
· ServletRequestAttributeListener
attributeAdded(ServletRequestAttributeEvent srae); attributeRemoved(ServletRequestAttributeEvent srae); attributeReplaced(ServletRequestAttributeEvent srae);
· HttpSessionAttributeListener
- 参考API文档
· ServletContextAttributeListener
- 参考API文档
如何编写监听器
(1)编写一个Java类,依据监听事件类型选择实现相应的监听接口。如:要监听Session对象的创建和销毁,就要实现HttpSessionListener;
(2)在监听接口方法中,实现相应的监听处理逻辑;
public class MyListener implements HttpSessionListener, HttpSessionAttributeListener { public void sessionCreated(HttpSessionEvent e) { System.out.println("session创建"); System.out.println(e.getSession()); } public void sessionDestroyed(HttpSessionEvent arg0) { System.out.println("session销毁"); } public void attributeAdded(HttpSessionBindingEvent arg0) { System.out.println("向session添加数据"); } public void attributeRemoved(HttpSessionBindingEvent arg0) { } public void attributeReplaced(HttpSessionBindingEvent arg0) { } }
(3)在web.xml文件中注册该监听器;
<listener> <listener-class>web.MyListener</listener-class> </listener>
注意:实现相同的Listener接口的多个监听器,在执行的时候按照web.xml注册出现的顺序来决定;
应用场景
· 由于ServletRequest、HttpSession、ServletContext对象都是容器创建的,通过对这些对象注册监听器,就可以得知何时创建了。比如:
1)在ContextDestroyed方法中对应用级别的资源进行释放;
2)统计在线人数可以通过HttpSessionListener监听器的sessionCreated方法监听session的创建动作;
Servlet上下文
什么是Servlet上下文
· 容器启动之后,会为每一个Web应用创建唯一的一个符合ServletContext接口要求的对象,该对象就是Servlet上下文;
· 特点
- 唯一性(一个Web应用对应一个servlet);
- 一直存在(只要容器不关闭,应用没有被卸载删除,servlet上下文就一直存在);
如何获取Servlet上下文
· 方式一
- 通过GenericServlet提供的 getServletContext();
· 方式二
- 通过ServletConfig提供的 getServletContext();
· 方式三
- 通过HttpSession提供的 getServletContext();
· 方式四
- 通过FilterConfig提供的getServletContext();
Servlet上下文的作用及特点
· 作用一
- 使用setAttribute绑定数据;
· 作用二
- 使用removeAttribute移除绑定数据;
· 作用三
- 使用getAttribute获取绑定数据;
· 特点
- servlet上下文绑定的数据可以被整个应用上的所有组件共享,并且可以一直访问;