过滤器
什么是过滤器
· 过滤器是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上下文绑定的数据可以被整个应用上的所有组件共享,并且可以一直访问;