Filter
Filter 的作用是拦截请求和响应的,拦截之后,是为了修改请求和响应中的内容。
生命周期 filter 的生命周期:
由web 服务器进行管理,也就是说,filter的整个过程中的方法调用,都是由web 服务器进行调用执行。程序员无法控制其执行。
//Filter 是在应用被启动时被创建以及初始化的。
//filter 是单例多线程的。
//filter 是在应用被停止的时候销毁的
//dofilter() 方法,无论是哪个线程进行访问,就会执行Filter 的doFilter() 方法。
//并且每过滤一次,就会执行一次dofilter() 方法
//由于filter 是单例多线程的,为了保证其线程安全性,一般是不为filter 添加可修改的成员变量的。
Filter 的注册流程:
(1)写一个类实现 filter 接口
(2)拷贝类全名,然后再web.xml 中注册
Eg:
<filter>
<!--filter 的名称 -->
<filter-name>some-Filter</filter-name>
<filter-class>com.cau.filters.SomeFilter</filter-class><!-- filter 的实现类 -->
<!--初始化参数 -->
<init-param>
<param-name>college</param-name>
<param-value>csu</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>some-Filter</filter-name>
<url-pattern>/*</url-pattern><!--所有请求他通通过滤拦截 -->
</filter-mapping>
Filter 的工作原理:
可以在请求到达目标资源之前对请求先进行拦截过滤,及对请求进行处理。也可以在响应到达客户端之前对响应进行处理,即对响应进行过滤和拦截。
Filter 一般是有三个方法:
(1) public void init(FilterConfig filterConfig)
filterConfig 指的是filter 在web.xml中的注册信息,filterConfig 和ServletConfig 类似,是一个接口。
有以下几种方法,以及方法的使用如下:
// 获取filter 的name
String name = filterConfig.getFilterName();
System.out.println("filterName" + name);
// 获取所有的初始化参数的名称
Enumeration<String> names = filterConfig.getInitParameterNames();
// 遍历枚举
while (names.hasMoreElements()) {
String name1 = names.nextElement();
String value = filterConfig.getInitParameter(name1);
System.out.println("filterName" + name1 + "==" + "value" + value);
}
//获取全局域
ServletContext servletContext = filterConfig.getServletContext();
System.out.println("ServletContext="+servletContext);
//将请求放到下一资源
chain.doFilter(request, response);
(2)public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
(3)public void destroy()
详解 filter 中的<Filter-mapping />
<!--
若filter 为全路径匹配方式(也就是说所有的请求都可以拦截)url-pattern 只能写成 /*,而不能写为 /
/* 表示servlet 可以匹配所有的请求,无论是静态资源还是动态资源
/ 不会拦截动态资源请求,只会拦截静态
-->
<!-- filter-mapping 中可以不使用 url-pattern ,但是需要指定servlet-name,即当前过滤器,只针对指定的servlet请求, -->
<Filter-mapping/> 中的dispatcher
(1)FORWARD
当前过滤器只会拦截RequestDispatcher的 forward()方法,所转发的请求。其余请求均不拦截
(2)INCLUDE
(3)REQUEST
当前过滤器会拦截普通请求。,但是对于forward 和include的跳转不进行拦截,是默认值
(4)ERROR
表示当跳转到指定的 错误处理页面时,这个跳转请求,会被当前过滤器拦截。
Filte执行的顺序
当存在多个Filter 的时候,其执行顺序。与注册顺序一致。
Filter的执行原理,以及与servlet 执行原理的比较:
/**
* 回顾servlet的执行原理
* 两个map:
* web 容器中存在两个map,这连个map的key 均为注册时的 utl-pattern 的值。但是其value 是不同的
* 第一个map的value是servlet 实例对象的引用
* 第二个mapde的value 为 <servlet-class/> 的值,即servlet 的全限定名
*
* 执行原理:
* 当servlet的请求到达servlet容器时,会先对请求进行解析,使用解析出的uti,作为比较对象。
* 从第一个map中察找是否有相同的key值
* 若存在相同的key,读取value ,即servlet 对象的引用,执行servlet() 的service() 方法
* 若不存在相同的key,那么再从第二个map中查找是否存在相同的key,若存在则读取其value,即要访问的servlet的全限定类名。
* 然后使用反射机制创建servlet 实例,并将实例写入第一个map中,然后再执行该servlet的service() 方法。
* 若第二个map中也没有找到,就是 404 not found
*/
/**
*filter的执行原理:
*一个数组,一个map
*map 的key为<url-pattern/> 的值,value 为filter 实例对象的引用。
*数组: 存放着 与请求相匹配的所有filter
*
*执行原理:
*当对某资源的web请求到达web容器时,会先对请求进行解析,使用解析出的uri作为比较对象,在map中查找是否存在相匹配的key
*若存在,读取其value,即filter对象的引用,将该引用存入到数组中。然后继续向后查找,直到将该map查找完毕,这样数组中就会有
*按照查找顺序排好序的filter 引用
*数组初始化完毕之后 ,开始按照数组元素顺序进行执行,所有数组中德 filter全部执行完毕之后,在跳到所请求的资源
*
*/
/**
* servlet 与filter的不同的原因是 两者的实例创建时机是不一样的。
* servlet 是在请求的时候
* filter 是在项目启动的时候,就创建了。
*/