一、Filter简介
Filter也称之为过滤器,它是WEB开发人员通过Filter技术,对web服务器管理的所有web资源:
例如 Jsp,Servlet, 静态图片文件或静态html文件等进行拦截,从而实现一些特殊的功能。
例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等
一些高级功能。Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter
技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,Filter接口源代码:
- public abstract interface Filter{
- public abstract void init(FilterConfig paramFilterConfig) throws ServletException;
- public abstract void doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain
- paramFilterChain) throws IOException, ServletException;
- public abstract void destroy();
- }
二、Filter的工作原理(实现拦截)
Filter接口中有一个doFilter方法,在编写好Filter,且配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:
调用目标资源之前,让一段代码执行。
是否调用目标资源(即是否让用户访问web资源)。
调用目标资源之后,让一段代码执行。
arg0.setCharacterEncoding(encoding);
arg2.doFilter(arg0,arg1);//在这句之前的处理就是前置处理,在这句之后的处理就是后置处理
arg1.setCharacterEncoding(encoding);
概念: FilterChain--过滤链
web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个
doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问
三、 Filter开发流程
(1) Filter开发分为2步:
* 编写java类实现Filter接口,并实现其doFilter方法。
* 在web.xml 文件中使用<filter>和<filter-mapping>元素对编写的filter类进行注册,并设置它所能拦截的资源。
1、定义过滤器类 直接或者间接实现Filter接口的类
publicclass EncoderFilter implements Filter {
privateString encoding = "UTF-8";
//在Filter对象创建完毕后立即执行,且只执行一次,主要用于获取配置参数
publicvoid init(FilterConfig config) throws ServletException {
Stringss = config.getInitParameter("encoding");
if(ss != null && ss.trim().length() > 0)
encoding= ss.trim();
}
//在Filter对象销毁之前执行,一般用于资源回收
publicvoid destroy() {
System.out.println("销毁filter对象");
}
//满足条件后执行的处理逻辑
publicvoid doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChainarg2) throws IOException, ServletException {
//filterChain对象提供了一个方法doFilter,表示继续向后执行下一个节点
arg0.setCharacterEncoding(encoding);
arg2.doFilter(arg0,arg1);//在这句之前的处理就是前置处理,在这句之后的处理就是后置处理
arg1.setCharacterEncoding(encoding);
}
}
2、在web.xml中配置过滤器生效的条件--不是访问路径
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!--配置过滤器-->
<filter>
<filter-name>FilterTest</filter-name>
<filter-class>com.yangcq.filter.FilterTest</filter-class>
</filter>
<!--映射过滤器-->
<filter-mapping>
<filter-name>FilterTest</filter-name>
<!--“/*”表示拦截所有的请求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
(2) Filter链在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。web服务器根据Filter在web.xml文件中的注册顺序,
决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter
方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,
如果没有,则调用目标资源。
四,Spring框架下,过滤器的配置
如果项目中使用了Spring框架,那么,很多过滤器都不用自己来写了,Spring为我们写好了一些常用的过滤器。下面我们就以字符编码的
过滤器CharacterEncodingFilter为例,来看一下Spring框架下,如何配置过滤器。
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
接下来,我们看一下CharacterEncodingFilter这个过滤器的关键代码:
public classCharacterEncodingFilter extends OncePerRequestFilter{
private static final booleanresponseSetCharacterEncodingAvailable = ClassUtils.hasMethod(
class$javax$servlet$http$HttpServletResponse,"setCharacterEncoding", new Class[] { String.class });
// 需要设置的编码方式,为了支持可配置,Spring把编码方式设置成了一个变量
private String encoding;
// 是否强制使用统一编码,也是为了支持可配置
private boolean forceEncoding;
// 构造器,在这里,Spring把forceEncoding的值默认设置成了false
public CharacterEncodingFilter(){
this.forceEncoding = false;
}
// encoding/forceEncoding的setter方法
public void setEncoding(String encoding){
this.encoding = encoding;
}
public void setForceEncoding(booleanforceEncoding){
this.forceEncoding =forceEncoding;
}
// Spring通过GenericFilterBean抽象类,对Filter接口进行了整合,
protected void doFilterInternal(HttpServletRequestrequest, HttpServletResponse response, FilterChain filterChain)
throws ServletException,IOException{
if ((this.encoding != null) &&(((this.forceEncoding) || (request.getCharacterEncoding() == null)))) {
request.setCharacterEncoding(this.encoding);
if ((this.forceEncoding) &&(responseSetCharacterEncodingAvailable)) {
response.setCharacterEncoding(this.encoding);
}
}
filterChain.doFilter(request,response);
}
}