过滤器

发表时间:2017-05-15 16:28:21 浏览量( 13 ) 留言数( 0 )

学习目标:

1、了解Java的历史

2、为什么要学习Java语言

3、端正学习态度


学习过程:

一、什么是过滤器filter

与Servlet相似,可以绑定到一个Web应用程序中。但是与其他Web应用程序组件不同的是,过滤器是“链”在容器的处理过程中的。这就意味着它们会在servlet处理器之前访问一个进入的请求,并且在外发的响应信息返回到客户前访问这些响应信息。这种访问使得过滤器可以检查并修改请求和响应的内容。 通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截。

过滤器放在Web资源之前,可以在请求抵达它所应用的Web资源(可以是一个servlet、一个JSP页面)之前截获进入的请求,并且在它返回到客户之前也会截获输出请求。也就说过滤器会在请求前后都会经过这个过滤器:

attcontent/4023a830-2889-4168-adb4-6675a8aec01d.png

在Servlet作为过滤器使用时,它可以对客户的请求进行处理。 处理完成后,它会交给下一个过滤器处理,这样,客户的请求在过滤链里逐个处理,直到请求发送到目标为止.

filter在很多地方都可以使用,你可以把servlet中的一些共用代码抽象到filter中,比如对提交的数据进行统一编码,也可以把登录拦截放到filter中进行,也可以把发送给客户端的静态页面先进行压缩后再发送,还可以实现过滤敏感词汇、等等等功能。

二、定义过滤器filter

Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter

1、实现过滤器。

新建一个普通类FirstFilter,然后实现Filter接口。并实现其三个方法

  FirstFilter Filter{
    
    init(FilterConfig arg0) ServletException {
        System.out.println();
        
    }
    
    doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) IOException, ServletException {
                System.out.println();
        chain.doFilter(request, response);
        System.out.println();
    }
    
    destroy() {
        System.out.println();
    }

}

2、过滤器的配置。

上面我们定义了一个过滤器,因为过滤器的生命周期有web容器管理,和servlet一样,我们需要在web.xml中配置这个过滤器,这样web容器启动的时候就会初始化这个过滤器。打开web.xml,添加一下代码:

    <>
    <-name>firstFilter</filter-name>
    <-class>com.filter.FirstFilter</filter-class>
  </>
  
  <!-- 拦截路径 -->
  <-mapping>
    <-name>firstFilter</filter-name>
    <-pattern>/userServlet</url-pattern>
  </-mapping>

和servlet差不多的一个配置,其中url-pattern是需要过滤的路径,我们可以直接写一个url路径,同时它也支持通配符(*)的使用,比如“/*”就表示过滤所有的信息,“/admin/*”就表示过滤所有的在admin访问路径下的所有的信息,这里我们先拦截的是“/userServlet”这个路径。

3、过滤器的生命周期

这个时候你就可以启动tomcat服务器了,注意filter是在服务器启动的时候就会初始化了,并且在服务器关闭的时候才会销毁,所以filter整个生命周期由服务器维护。

重点是doFilter方法,这个方法在每一次拦截的时候都会执行。在这个方法里面有三个参数其中有两个我们非常属性的request和response对象,还有就是FilterChain对象,这个对象一般会调用doFilter方法,表示把交给下一个链操作,可能是servlet,也可能是下一个过滤器。

现在你可以打开浏览器输入访问/userServlet这个网址。

http://localhost:8080/userdemo/userServlet。

查看控制台的输入,会先输出:

FirstFilter访问业务核心前执行

执行了核心的逻辑servlet

FirstFilter访问业务核心后执行

4、过滤器的先后顺序

注意过滤器在web.xml的定义顺序是会影响其拦截的先后顺序的,如果两个过滤器都会拦截同一个路径,那么先定义的就会先拦截。比如我们再定义一个过滤器:

SecondFilter Filter{

    destroy() {
        
        
    }

    doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) IOException, ServletException {
                System.out.println();
        chain.doFilter(request, response);
        System.out.println();
        
    }

    init(FilterConfig arg0) ServletException {
        
        
    }

}

在web.xml中配置时,是在第一个过滤器的后面定义的,也是一样拦截同一个路径;

<>
    <-name>secondFilter</filter-name>
    <-class>com.filter.SecondFilter</filter-class>
</>
   <!-- 拦截路径 -->
<-mapping>
    <-name>secondFilter</filter-name>
    <!-- 支持通配符 * -->
    <-pattern>/userServlet</url-pattern>
</-mapping>

这是时候我们在访问/userServlet这个网址。

http://localhost:8080/userdemo/userServlet。

结果输出如下:

FirstFilter访问业务核心前执行

SecondFilter访问业务核心前执行

执行了核心的逻辑servlet

SecondFilter访问业务核心后执行

FirstFilter访问业务核心后执行

先拦截的过滤器,与返回给客户端的顺序相反,也就是和栈的结构是一样的,先进后出。当然这个也是很容易理解的,可以参考下图:

attcontent/d6764663-a813-4fc3-a324-b518261365ee.png

三、过滤器的应用

1、编码过滤器

下面我们可以讲两个简单的应用,因为每一个servlet都需要设置编码,代码如下:

  request.setCharacterEncoding();
response.setCharacterEncoding();

所以我们放到filter中配置,先进一个编码过滤器:

  ChaFilter Filter {
    init(FilterConfig arg0) ServletException {
    }
    doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) IOException, ServletException {
                request.setCharacterEncoding();
        response.setCharacterEncoding();
        chain.doFilter(request, response);
    }
    destroy() {
    }
}

在web.xml配置如下;

      <>
    <-name>chaFilter</filter-name>
    <-class>com.filter.ChaFilter</filter-class>
  </>
  
  <!-- 拦截路径 -->
  <-mapping>
    <-name>chaFilter</filter-name>
    <-pattern>/*</url-pattern>
  </-mapping>

好,这样就不要在每个servlet都写上编码的代码了。

2、登录拦截器

要做这个登录拦截器,我们必须先做好规划,比如需要登录才能访问的路径,我们一律都是放在admin的访问路径之下的。这样我们就只需要拦截这个路径就可以了,凡是没有登录的就去登录页面,登录就去下一个操作就行了。实现代码如下:

  LoginFilter Filter {
    init(FilterConfig arg0) ServletException {
    
    }
    doFilter(ServletRequest req, ServletResponse resp,
    FilterChain chain) IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
                User user1 = (User) request.getSession().getAttribute();
        (user1 == null) {
            response.sendRedirect();
        } {
            chain.doFilter(request, response);
        }
    }
    destroy() {
    
    }
}

web.xml配置文件如下;

     <>
    <-name>loginFilter</filter-name>
    <-class>com.filter.LoginFilter</filter-class>
  </>
  
  <!-- 拦截路径 -->
  <-mapping>
    <-name>loginFilter</filter-name>
    <-pattern>/admin/*</url-pattern>
  </-mapping>