Filter相关知识点

Filter

     Filter也称之为过滤器,它是Servlet技术中最激动人心的技术之一,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp,
Servlet, 静态图片文件或静态html文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等
一些高级功能。
 Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截.
 Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,
都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:
调用目标资源之前,让一段代码执行。
是否调用目标资源(即是否让用户访问web资源)。
调用目标资源之后,让一段代码执行。
  web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。

	import java.io.IOException;  
	import javax.servlet.Filter;  
	import javax.servlet.FilterChain;  
	import javax.servlet.FilterConfig;  
	import javax.servlet.ServletException;  
	import javax.servlet.ServletRequest;  
	import javax.servlet.ServletResponse;  
	public class FilterTest implements Filter{  
	  
	    public void destroy() {  
	        System.out.println("----Filter销毁----");  
	    }  
	  
	    public void doFilter(ServletRequest request, ServletResponse response,FilterChain filterChain) throws IOException, ServletException {  
	        // 对request、response进行一些预处理  
	        request.setCharacterEncoding("UTF-8");  
	        response.setCharacterEncoding("UTF-8");  
	        response.setContentType("text/html;charset=UTF-8");  
	        System.out.println("----调用service之前执行一段代码----");  
	        filterChain.doFilter(request, response); // 执行目标资源,放行  
	        System.out.println("----调用service之后执行一段代码----");  
	    }  
	  
	    public void init(FilterConfig arg0) throws ServletException {  
	        System.out.println("----Filter初始化----");  
	    }  
	}  

在web. xml中配置过滤器:

	<?xml version="1.0" encoding="UTF-8"?>  
	<web-app version="3.0"   
	    xmlns="http://java.sun.com/xml/ns/javaee"   
	    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
	    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">  
	   <display-name></display-name>      
	   <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>  

这里边有个执行顺序问题 稍后会详细介绍这个顺序

在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

执行顺序

过滤器链调用原理与顺序:
web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法(放行)中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

根据在web.xml文件中的顺序还决定调用的顺序:和<filter-mapping》的配置先后顺序有关系.
在开发中:Servlet,Filter,Listener配置先后问题: 一般先配置Listener,再配置Filter,最后配置Servlet.

在这里插入图片描述

  • 配置路径的细节:

a.精确拦截指定资源
<url-pattern>/hello</url-pattern>:当前Filter只对/hello这个资源做过滤.
b.拦截所有资源
<url-pattern>/*</url-pattern>:当前Filter对所有的请求做过滤.如字符编码
c.对部分资源进行拦截(以什么开头)
<url-pattern>/system/*</url-pattern>:当前Filter 对/system/之后的请求做过滤.
比如:/system/list,/system/edit,/system/delete 如权限判断
d.对部分资源进行拦截(以什么结束)
<url-pattern>*.html</url-pattern>:当前Filter 对后缀是ejf的进行过滤。如假静态化

  • 过滤器过滤类型选择:

过滤器默认过滤的类型是:request。要想过滤其它的需要在web.xml中配置
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>

Filter默认情况下,就只能对一次请求做过滤.
<dispatcher>REQUEST</dispatcher>
若需要对请求转发做过滤:
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>

当然也可以使用注解的方式

@WebFilter(filterName="myfilter",urlPatterns="/images/*")  
public class MyFilter implements Filter {  
    ......  
}
//也可以指定多种过滤模式
@WebFilter(filterName="myfilter",urlPatterns={"/imageServlet","/images/*.jpg"})

属性filterName声明过滤器的名称,可选
属性urlPatterns指定要过滤 的URL模式,也可使用属性value来声明.(指定要过滤的URL模式是必选属性)

大家都知道,在web.xml中配置filter的时候,可以指定哪一个filter先执行,哪一个filter后执行,这是通过每个filter-mapping在web.xml中出现的先后顺序来确定的。通过注解配置filter时,没有专门的指令来配置filter执行的先后。确定filter执行的先后是根据filter类名的字母表顺序。

WebFilter 的属性

属性名 类型 描述
filterName String 指定过滤器的 name 属性,等价于 <filter-name>
value String[] 该属性等价于 urlPatterns 属性。但是两者不应该同时使用。
urlPatterns String [] 指定一组过滤器的 URL 匹配模式。等价于 <url-pattern> 标签。
servletNames String[] 指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 <servlet-name> 的取值。
dispatcherTypes DispatcherType 指定过滤器的转发模式。具体取值包括: ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。
initParams WebInitParam[] 指定一组过滤器初始化参数,等价于 <init-param> 标签。
asyncSupported boolean 声明过滤器是否支持异步操作模式,等价于 <async-supported> 标签。
description String 该过滤器的描述信息,等价于 <description> 标签。
displayName String 该过滤器的显示名,通常配合工具使用,等价于 <display-name> 标签。

dispatcher解析

filter的四种dispatcher
Java Web的开发都知道如何在web.xml里面配置过滤器,过滤器中有一个属性来探究一下这个属性的作用,首先写一个Filter:

public class DispatcherFilter implements Filter
{
    public void init(FilterConfig filterConfig) throws ServletException
    {
        
    }
    
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException
    {
        System.out.println("Enter DispatcherFilter.doFilter()");
        chain.doFilter(request, response);
    }
    
    public void destroy()
    {
        
    }
}
 

再来在web.xml里面定义一个filter:

<filter>
    <filter-name>dispatcher</filter-name>
    <filter-class>com.xrq.filter.DispatcherFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>dispatcher</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>XXX</dispatcher>
</filter-mapping>

注意<dispatcher></dispatcher>必须写在filter-mapping的最后。dispatcher的前提条件当然是要先满足url-pattern,然后dispatcher有四种可能的属性:
1、REQUEST
只要发起的操作是一次HTTP请求,比如请求某个URL发起了一个GET请求、表单提交方式为POST时提交表单则发起了一个POST请求、表单提交方式为GET时提交表单则发起了一次GET请求、一次重定向则前后相当于发起了两次请求,这些情况下有几次请求就会走几次指定过滤器
2、FOWARD
只有当当前页面是通过请求转发转发过来的场景,才会走指定的过滤器
3、INCLUDE
只要是通过<jsp:include page=“xxx.jsp” />,嵌入进来的页面,每嵌入的一个页面,都会走一次指定的过滤器
4、ERROR
这个可能开发者不是很熟悉,意思是当触发了一次error的时候,就会走一次指定的过滤器。什么叫做触发error,举个例子,我在web.xml里面配置了<error-page></error-page>:

<error-page>
    <error-code>400</error-code>
    <location>/filter/error.jsp</location>
</error-page>
  
<error-page>
    <error-code>404</error-code>
    <location>/filter/error.jsp</location>
</error-page>
  
<error-page>
    <error-code>500</error-code>
    <location>/filter/error.jsp</location>
</error-page>
 

意思是HTTP请求响应的状态码只要是400、404、500三种状态码之一(比如访问了一个不存在的页面,就是404),容器就会将请求转发到http://ip:port/工程名/filter/error.jsp下,这就触发了一次error,走进了我自己写的DispatchFilter。注意一点的是,虽然把请求转发到http://ip:port/工程名/filter/error.jsp是一次forward的过程,但是我试了一下,配置成<dispatcher>FORWARD</dispatcher>并不会走DispatchFilter这个过滤器。
这四种dispatcher方式可以单独使用,也可以组合使用,配置多个<dispatcher></dispatcher>就好了。

猜你喜欢

转载自blog.csdn.net/ZhouhbUp/article/details/82887490