javaWeb-filter(过滤器一)

本文详细介绍了Java Web中的过滤器Filter,包括过滤器的作用、应用场景、手动XML配置和注解实现、执行流程、生命周期、拦截路径配置、默认不拦截转发资源及其修改、过滤器链的实现和执行顺序分析。通过实际案例展示了过滤器在解决POST中文乱码和登录权限控制中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

01学习目标

  1. 能够说出过滤器的作用
  2. 能够编写过滤器
  3. 能够说出过滤器生命周期相关方法
  4. 能够根据过滤路径判断指定的过滤器是否起作用
  5. 能够说出什么是过滤器链
  6. 能够编写过滤器解决全局乱码

02.过滤器介绍与应用场景【理解】

目标

掌握过滤器的作用与应用场景

为什么学习过滤器

浏览器提交post传递中文数据给不同的Servlet去处理,那所有接收post中文数据的Servlet都要处理乱码,非常麻烦。可以使用一种拦截请求的方式,拦截所有Servlet的请求,进行集中对中文乱码处理,处理完成以后再去各自的目标Servlet, 这样每个Servlet就不用处理乱码。那么这个拦截所有Servlet的请求就是过滤器。

过滤器介绍

过滤器是javaEE体系提供的一个Filter接口,我们只需要实现Filter接口就可以拦截任意的请求与响应。

过滤器的作用

拦截请求与响应

应用场景介绍

  1. 解决post提交中文乱码应用场景

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UtcfDueO-1606226675658)(assets/image-20200508093708142.png)]

  2. 登录权限控制

    需求:服务器某一类资源(很多资源)需要登录后才可以访问,就是登录权限控制

    传统解决方案:访问这一类中每个资源都要判断是否登录,登录了允许访问,否则return结束

过滤器:使用过滤器拦截这一类资源的请求,进行统一判断是否登录,登录了允许继续访问,否则return结束。节省了每个资源都不需要判断了。

小结

  1. 过滤器的作用?

    拦截请求与响应

  2. 过滤器是解决什么问题的?

    解决如果每一个操作是每个资源都要操作的,那么可以将这个操作放入过滤器中集中处理

  3. 过滤器的应用场景

    统一解决post中文乱码

    统一解决登录权限控制

03.开发方式1-手动XML配置【理解】

目标

理解手动xml配置实现过滤器

实现步骤

1、创建Demo1Servlet资源,输出“执行了Demo1Servlet”

2、创建过滤器类实现Filter接口,重写拦截请求与响应的doFilter方法

3、在web.xml中配置过滤器类要拦截的资源路径

Servlet代码

package _01_创建web资源;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebServlet(name = "Demo1Servlet", urlPatterns = "/Demo1Servlet")
public class Demo1Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("执行了Demo1Servlet");
    }
}

过滤器代码

package _02_手动xml创建过滤器;


import javax.servlet.*;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
public class Demo1Filter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    //拦截请求与响应的方法
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {

        //1、拦截请求
        System.out.println("==执行了Demo1Filter的拦截请求的任务代码==");

        //2.放行(放行就是允许去访问目标资源,如果不放行就不会去目标资源)
        filterChain.doFilter(request,response);//本质:调用目标资源去执行
        //注意:有这句代码就是放行,否则不放行

        //3.拦截响应
        System.out.println("==执行了Demo1Filter的拦截响应的任务代码==");

    }

    @Override
    public void destroy() {

    }
}

web.xml代码

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--在web.xml中配置过滤器类要拦截的资源路径
        1、定义过滤器,配置过滤器类全名
        2、配置过滤器拦截的资源路径
    -->
    <!--定义过滤器,配置过滤器类全名-->
    <filter>
        <filter-name>Demo1Filter</filter-name>
        <filter-class>_02_手动xml创建过滤器.Demo1Filter</filter-class>
    </filter>
    <!--配置过滤器拦截的资源路径-->
    <filter-mapping>
        <filter-name>Demo1Filter</filter-name>
        <url-pattern>/Demo1Servlet</url-pattern>
    </filter-mapping>

</web-app>

访问地址

http://localhost:8080/day15_01_filter_war_exploded/Demo1Servlet

效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tOdBA51D-1606226675662)(assets/image-20200508100412266.png)]

小结

  1. 实现过滤器的接口是什么?

    javax.servlet.Filter
    
  2. 过滤器拦截请求与响应的方法是什么?

    doFilter
    

04.开发方式2-注解实现【应用】

目标

使用模板向导和注解配置路径实现过滤器

实现步骤

1、创建Demo2Servlet资源,输出“执行了Demo2Servlet”

2、使用过滤器模板向导创建过滤器类,重写拦截请求与响应的doFilter方法

3、配置过滤器类的注解实现拦截路径配置

Servlet资源代码

package _01_创建web资源;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebServlet(name = "Demo2Servlet", urlPatterns = "/Demo2Servlet")
public class Demo2Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("执行了Demo2Servlet");
    }
}

过滤器代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jVDpSVS5-1606226675666)(assets/image-20200508102127549.png)]

package _03_注解方式创建过滤器;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @author 黑马程序员
 *
 * @WebFilter 过滤器注解类
 * filterName = "Demo2Filter",设置过滤器别名,功能与xml<filter-name>一样, 可有可无的属性
 * urlPatterns = "/Demo2Servlet", 设置拦截的资源路径,如果拦截多个路径使用数组, 这个属性必须有
 *
 * 注解简写方式:@WebFilter("/Demo2Servlet") 只需要配置拦截路径即可
 */
@WebFilter(filterName = "Demo2Filter",urlPatterns = "/Demo2Servlet")
public class Demo2Filter implements Filter {
    public void destroy() {
    }

    //拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //1、拦截请求
        System.out.println("==执行了Demo2Filter的拦截请求的任务代码==");

        //2.放行
        chain.doFilter(request,response);

        //3.拦截响应
        System.out.println("==执行了Demo2Filter的拦截响应的任务代码==");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

运行效果

方法地址

http://localhost:8080/day15_01_filter_war_exploded/Demo2Servlet

效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C2ltZPk2-1606226675667)(assets/image-20200508102712129.png)]

小结

  • 注解实现代码是什么?

    @WebFilter(filename="过滤器",urlPatterns={"/资源路径",“/xxx”})
    

    注意:这里配置的资源路径与Servlet资源路径保存一致,必须以“/”开头

  • 注解配置与xml配置出现冲突的时候,谁的优先级高?

    xml的优先级高
    

05.过滤器执行流程【理解】

执行流程(时序图)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QIspu0Ty-1606226675669)(assets/1566385548791.png)]

注意:1、先走过滤器拦截请求

​ 2、只有放行才可以去目标资源

​ 3、拦截响应什么都不做就会响应给浏览器数

06.过滤器生命周期【理解】

目标

1.过滤器对象什么时候被创建?

2.服务创建过滤器对象创建了几次?

3.什么时候销毁过滤器?

实现步骤

1. 创建Demo3Servlet资源
2. 创建LifeCycleFilter拦截请求与响应,重写3个方法(init方法, doFilter方法, destroy方法)
3. 观察运行

Demo3Servlet资源代码

package _01_创建web资源;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebServlet(name = "Demo3Servlet", urlPatterns = "/Demo3Servlet")
public class Demo3Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("执行了Demo3Servlet");
    }
}

过滤器代码

package _04_过滤器的生命周期;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @author 黑马程序员
 *
 * 1.过滤器对象什么时候被创建?
 *   答:关注init的运行时间,服务器启动的时候就运行了init方法
 *       说明过滤器是在服务器启动的时候服务器创建的
 * 2.服务创建过滤器对象创建了几次?
 *   答:关注init方法执行了几次,发现init方法只运行一次
 *       说明服务器值创建了一次过滤器对象,全局唯一,节省内存
 * 3.什么时候销毁过滤器?
 *   答:服务器关闭就销毁了
 */
@WebFilter(filterName = "LifeCycleFilter",urlPatterns = "/Demo3Servlet")
public class LifeCycleFilter implements Filter {

    //init初始化方法,当前过滤器创建时候调用
    public void init(FilterConfig config) throws ServletException {

        System.out.println("==调用了LifeCycleFilter的init方法==");
    }


    //doFilter拦截请求与响应的方法,每次浏览器访问符合拦截路径的资源都会触发
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        System.out.println("==调用了LifeCycleFilter的doFilter方法==");
        //注意:没有放行,所以目标资源Demo3Servlet不会运行
    }

    //destroy销毁方法,服务器关闭之前的时候调用
    public void destroy() {
        System.out.println("==调用了LifeCycleFilter的destroy方法==");
    }



}

运行效果

访问地址

http://localhost:8080/day15_01_filter_war_exploded/Demo3Servlet

效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8F4lDkdt-1606226675670)(assets/image-20200508105015183.png)]

小结

  • 过滤器对象什么时候创建?对象全局唯一吗?

    服务器启动时创建,全局唯一
    
  • 过滤器对象什么时候销毁?

    服务器关闭前
    

07.过滤器拦截路径的配置【理解】

思考

  • 一个过滤器只能拦截一个资源吗?如何做到一个过滤器拦截多个资源?

    需要学习拦截路径的配置
    

目标

过滤器通过拦截路径配置可以拦截一个或多个资源

过滤路径映射配置介绍

拦截路径配置方式有2种:
第一种:精确匹配,配置的路径与资源访问的路径要一模一样就可以拦截
	   任何资源路径都是可以的
	   urlPatterns = "/img/3.jpg",
	   urlPatterns = "/index.jsp"
第二种:模糊匹配,只能使用一个“*”号通配符操作,代表0~多个字符
	   1.前缀匹配,匹配开头一致的
	   	要求:以“/”开头,以"/*"结尾
	   	例子:
	   		/abc/*,拦截资源访问路径以/abc开头的所有资源
	   		/*,拦截所有资源
	   2.后缀匹配,匹配结尾一致的
	   	要求:以“*”开头,以“.扩展名”方式结尾
	   	例子:
	   		*.action,拦截资源访问路径以.action为结尾的所有资源
	   		*.do,拦截资源访问路径以.do为结尾的所有资源

注意

1.urlPatterns = "/abc/*/abc",这是精确匹配(完全匹配)
2.在过滤器里面可以使用“/*”,(但是在Servlet里面不可以,否则静态资源无法访问), 在过滤器里面有放行,所以不影响静态资源的执行。

过滤器代码

package _05_过滤器拦截路径的配置;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @author 黑马程序员
 *
 * 拦截路径配置方式有2种(与servlet路径配置一致):
 * 第一种:完全匹配(精确匹配),配置的拦截路径与资源访问的路径要一模一样就可以拦截
 * 	   任何资源路径都是可以的
 * 	   urlPatterns = "/img/3.jpg",
 * 	   urlPatterns = "/index.jsp"
 * 第二种:模糊匹配,只能使用一个“*”号通配符操作,代表0~多个任意字符
 * 	   1.目录匹配(前缀匹配),匹配目录开头一致的
 * 	   	要求:以“/”开头,以"/*"结尾
 * 	   	例子:
 * 	   		/abc/*,拦截资源访问路径以/abc目录开头的所有资源
 * 	   		/*,拦截所有资源
 * 	   2.扩展名匹配(后缀匹配),匹配结尾一致的
 * 	   	要求:以“*”开头,以“.扩展名”方式结尾
 * 	   	例子:
 * 	   		*.action,拦截资源访问路径以.action为结尾的所有资源
 * 	   		*.do,拦截资源访问路径以.do为结尾的所有资源
 */
@WebFilter(filterName = "UrlPatternsFilter",
        urlPatterns ={
            //完全匹配
            "/img/3.jpg","/index.jsp",   //3.jpg资源没有也可以拦截
            "/abc/*/abc",  //注意:这个是完全匹配
            //模糊目录匹配
            "/abc/*",
            //扩展名匹配
            "*.do"
        } )
public class UrlPatternsFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //1、拦截请求
        System.out.println("==执行了UrlPatternsFilter的拦截请求的任务代码==");

        //2.放行
        chain.doFilter(request,response);

        //3.拦截响应
        System.out.println("==执行了UrlPatternsFilter的拦截响应的任务代码==");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

小结

  1. 过滤器的映射路径配置方式有几种?

    3种
    1、完全匹配: 拦截的路径与访问的路径一模一样
    2、模糊匹配-目录匹配:以“/”开头,“/*”结尾, 例如:/abc/*
    3、模糊匹配-扩展名匹配:以“*”开头,“.扩展名”结尾, 例如: *.do
    
  2. 常用的路径配置如下,分别代表什么意思?

    路径含义
    /admin/*拦截所有以admin目录开头访问的所有资源
    /*拦截所有资源

08.默认不拦截转发跳转目标资源【应用】

疑问

  • 是不是所有资源配置了拦截路径默认都会拦截?

    默认不会拦截转发的目标资源
    

目标

测试过滤器默认不拦截请求转发跳转的目标资源

过滤器默认不拦截请求转发访问的资源演示,实现步骤

1、创建2个资源 ,分别是OneServlet和TwoServlet

2、实现OneServlet转发跳转到TwoServlet

3、创建过滤器类Demo3Filter,拦截TwoServlet

4、运行观察,访问OneServlet转发跳转到TwoServlet,过滤器默认没有拦截TwoServlet

 

OneServlet代码

package _01_创建web资源;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebServlet(name = "OneServlet", urlPatterns = "/OneServlet")
public class OneServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //转发跳转到TwoServlet
        request.getRequestDispatcher("/TwoServlet").forward(request,response);
    }
}

TwoServlet代码

package _01_创建web资源;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebServlet(name = "TwoServlet", urlPatterns = "/TwoServlet")
public class TwoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("执行了TwoServlet");
    }
}

过滤器代码

package _06_过滤器默认不拦截转发跳转的目标资源TwoServlet;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebFilter(filterName = "Demo3Filter",urlPatterns = "/TwoServlet")
public class Demo3Filter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //1、拦截请求
        System.out.println("==执行了Demo3Filter的拦截请求的任务代码==");

        //2.放行
        chain.doFilter(request,response);

        //3.拦截响应
        System.out.println("==执行了Demo3Filter的拦截响应的任务代码==");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

效果

访问地址

http://localhost:8080/day15_01_filter_war_exploded/OneServlet

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H38FvOKk-1606226675671)(assets/image-20200508114120701.png)]

小结

  • 过滤器默认可以拦截请求转发访问的目标资源请求与响应吗?

    不可以
    

09.修改拦截方式拦截转发资源【应用】

目标

1、理解过滤器拦截方式

2、掌握拦截方式的修改

拦截方式介绍

拦截方式是浏览器访问资源的方式,可以分为:直接访问和间接访问资源

直接访问资源:浏览器直接的资源路径,包含2个方式

​ 第一个方式:在浏览器地址栏上直接输入资源访问路径

​ 第二个方式:重定向跳转访问的资源,因为2次请求都是浏览器地址栏发出的请求

​ 注意:直接访问资源方式,过滤器默认都可以拦截

间接访问资源:请求转发跳转访问的资源, 比如访问OneServlet转发跳转到TwoServlet

​ 直接访问的是OneServlet, 间接访问的TwoServlet

​ 注意:间接访问资源方式,过滤器默认不拦截

拦截方式类型

类型介绍
REQUEST直接访问资源方式,默认方式
FORWARD间接访问资源方式,如果设置成这个方式,转发跳转的目标资源也可以拦截了

注解方式修改拦截方式的语法

注解属性说明
dispatcherTypes = {DispatcherType.REQUEST}设置采用默认拦截方式,拦截浏览器直接url访问的资源请求与响应
dispatcherTypes = {DispatcherType.FORWARD}设置采用请求转发拦截方式(间接资源访问方式),注意,如果只配置这种方式,默认方式直接url访问资源将无效不能拦截
dispatcherTypes = {DispatcherType.REQUEST,
DispatcherType.FORWARD}
设置采用直接url与请求转发2种拦截方式

扩展web.xml配置过滤器修改拦截方式设置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dWkxEA0c-1606226675672)(assets/1551581167805.png)]

过滤器实现拦截请求转发访问和直接url访问的资源演示,实现步骤

  1. 创建2个Servlet,OneServlet2与TwoServlet2
  2. 在OneServlet2实现转发跳转到TwoServlet2
  3. 创建过滤器拦截TwoServlet2资源请求与响应, 配置拦截方式支持2种(直接和间接)
  4. 观察运行,可以拦截

OneServlet2

package _07_修改过滤器拦截方式支持拦截2种类型直接与间接;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebServlet(name = "OneServlet2", urlPatterns = "/OneServlet2")
public class OneServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //转发跳转到TwoServlet2
        request.getRequestDispatcher("/TwoServlet2").forward(request,response);
    }
}

TwoServlet2

package _07_修改过滤器拦截方式支持拦截2种类型直接与间接;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebServlet(name = "TwoServlet2", urlPatterns = "/TwoServlet2")
public class TwoServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("执行了TwoServlet2");
    }
}

过滤器代码

package _07_修改过滤器拦截方式支持拦截2种类型直接与间接;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebFilter(filterName = "Demo4Filter",urlPatterns = "/TwoServlet2",
    //配置拦截方式支持直接访问资源方式REQUEST和间接访问资源方式FORWARD
    dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST}
)
public class Demo4Filter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //1、拦截请求
        System.out.println("==执行了Demo4Filter的拦截请求的任务代码==");

        //2.放行
        chain.doFilter(request,response);

        //3.拦截响应
        System.out.println("==执行了Demo4Filter的拦截响应的任务代码==");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VyYikwSs-1606226675673)(assets/image-20200508120309721.png)]

小结

1、过滤器拦截方式是什么

拦截方式就是浏览器访问资源的方式:

1、直接访问资源REQUEST

2、间接访问资源FORWARD

2、拦截方式如何修改

注解方式修改: dispatcherTypes={DispatcherType.REQUEST,DispatcherType.FORWARD}

xml方式forwardrequest

10.过滤器链介绍与实现【应用】

目标

掌握什么是过滤器链与实现

过滤器链介绍

一个资源被多个过滤器进行拦截请求与响应,多个过滤器是串型执行形成过滤器链条,叫过滤器链

实现过滤器链的步骤

1、创建一个资源Demo4Servlet并输出数据

2、创建Chain1Filter过滤器拦截Demo4Servlet的请求与响应

3、创建Chain2Filter过滤器拦截Demo4Servlet的请求与响应

4、观察运行效果

Demo4Servlet资源代码

package _08_实现过滤器链;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebServlet(name = "Demo4Servlet", urlPatterns = "/Demo4Servlet")
public class Demo4Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("执行了Demo4Servlet");
    }
}

Chain1Filter代码

package _08_实现过滤器链;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebFilter(filterName = "Chain1Filter",urlPatterns = "/Demo4Servlet")
public class Chain1Filter implements Filter {
    public void destroy() {
    }

    //拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //1、拦截请求
        System.out.println("==执行了Chain1Filter的拦截请求的任务代码==");

        //2.放行
        chain.doFilter(request,response);

        //3.拦截响应
        System.out.println("==执行了Chain1Filter的拦截响应的任务代码==");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

Chain2Filter代码

package _08_实现过滤器链;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebFilter(filterName = "Chain2Filter",urlPatterns = "/Demo4Servlet")
public class Chain2Filter implements Filter {
    public void destroy() {
    }

    //拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //1、拦截请求
        System.out.println("==执行了Chain2Filter的拦截请求的任务代码==");

        //2.放行
        chain.doFilter(request,response);

        //3.拦截响应
        System.out.println("==执行了Chain2Filter的拦截响应的任务代码==");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

运行效果

访问地址

http://localhost:8080/day15_01_filter_war_exploded/Demo4Servlet

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OLO46K5j-1606226675674)(assets/image-20200508141638954.png)]

小结

  • 什么是过滤器链?

    一个资源被多个过滤器拦截请求与响应,串行执行的过程就是过滤器链

11.过滤器链执行顺序分析与修改【理解】

目标

理解过滤器执行的顺序

理解过滤器执行顺序的修改

执行顺序分析

注解方式通过过滤器类的名字:class chain1Filter 升序继续排序, 不是注解上属性的名字

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BJ2bHYCL-1606226675675)(assets/image-20200229112333031.png)]

案例需求

使用web.xml修改过滤器运行顺序,先运行Chain2Filter,再运行Chain1Filter

Demo4Servlet2

package _09_通过xml配置过滤器链执行顺序;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebServlet(name = "Demo4Servlet2", urlPatterns = "/Demo4Servlet2")
public class Demo4Servlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("执行了Demo4Servlet2");
    }
}

Chain1Filter2

package _09_通过xml配置过滤器链执行顺序;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebFilter(filterName = "Chain1Filter2",urlPatterns = "/Demo4Servlet2")
public class Chain1Filter2 implements Filter {
    public void destroy() {
    }

    //拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //1、拦截请求
        System.out.println("==执行了Chain1Filter2的拦截请求的任务代码==");

        //2.放行
        chain.doFilter(request,response);

        //3.拦截响应
        System.out.println("==执行了Chain1Filter2的拦截响应的任务代码==");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

Chain2Filter2

package _09_通过xml配置过滤器链执行顺序;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebFilter(filterName = "Chain2Filter2",urlPatterns = "/Demo4Servlet2")
public class Chain2Filter2 implements Filter {
    public void destroy() {
    }

    //拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //1、拦截请求
        System.out.println("==执行了Chain2Filter2的拦截请求的任务代码==");

        //2.放行
        chain.doFilter(request,response);

        //3.拦截响应
        System.out.println("==执行了Chain2Filter2的拦截响应的任务代码==");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

web.xml配置

<!--
    目标:先执行Chain2Filter2,之后再执行Chain1Filter2
    -->
    <!--定义过滤器,配置过滤器类全名-->
    <filter>
        <filter-name>Chain2Filter2</filter-name>
        <filter-class>_09_通过xml配置过滤器链执行顺序.Chain2Filter2</filter-class>
    </filter>
    <!--配置过滤器拦截的资源路径-->
    <filter-mapping>
        <filter-name>Chain2Filter2</filter-name>
        <url-pattern>/Demo4Servlet2</url-pattern>
    </filter-mapping>

    <!--定义过滤器,配置过滤器类全名-->
    <filter>
        <filter-name>Chain1Filter2</filter-name>
        <filter-class>_09_通过xml配置过滤器链执行顺序.Chain1Filter2</filter-class>
    </filter>
    <!--配置过滤器拦截的资源路径-->
    <filter-mapping>
        <filter-name>Chain1Filter2</filter-name>
        <url-pattern>/Demo4Servlet2</url-pattern>
    </filter-mapping>

运行效果

访问地址

http://localhost:8080/day15_01_filter_war_exploded/Demo4Servlet2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cIP1OJMu-1606226675677)(assets/image-20200508143337527.png)]

12.案例1-解决全站post中文乱码【应用】

需求

解决访问项目任何资源请求post传输中文乱码问题

实现步骤

  1. 准备一个表单数据提交post中文请求
  2. 新建一个EncodingServlet处理请求接收中文数据并控制台打印输出
  3. 创建一个过滤器EncodingFilter拦截所有资源解决全站post中文乱码

Form.jsp页面(素材代码)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="encoding" method="post">
    <input type="text" name="name"/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

EncodingServlet代码

package _10_案例_解决全站Post中文乱码;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebServlet(name = "EncodingServlet", urlPatterns = "/encoding")
public class EncodingServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1、获取post提交传递的中文数据
        String name = request.getParameter("name");

        //2、控制台打印输出
        System.out.println(name);
    }
}

运行form.jsp提交中文的乱码效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BQ6H2Hd2-1606226675678)(assets/image-20200508144053132.png)]

EncodingFilter代码

package _10_案例_解决全站Post中文乱码;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @author 黑马程序员
 *
 * 目标:拦截所有资源的请求,处理post提交中文乱码
 */
@WebFilter(filterName = "EncodingFilter",urlPatterns = "/*")
public class EncodingFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        //ServletRequest 父接口,没有提供getMethod()方法
        //HttpServletRequest 子接口,提供getMethod()方法
        //将父接口转换为子接口
        HttpServletRequest request = (HttpServletRequest) req;

        //1、判断请求的类型是否是post
        //获取请求方法类型
        String method = request.getMethod();
        //判断
        if("post".equalsIgnoreCase(method)) {

            //2、如果请求类型是post ,解决乱码
            request.setCharacterEncoding("utf-8");
        }

        chain.doFilter(request, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

过滤器处理乱码后效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t1VXpkUE-1606226675679)(assets/image-20200508144844213.png)]

小结

  • 过滤器如何可以拦截所有资源?

    urlPatterns="/*"

13.案例2-登录权限控制1-登录功能【理解】

需求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J2MXuhhk-1606226675681)(assets/1566384570819.png)]

如何知道是否登录?

答:登录成功后要将登录数据写入session会话对象中,session有数据就代表登录,否则代表没有登录

环境搭建

  1. 创建一个项目

  2. 导入页面素材(“资料\原型”)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RPazAqhE-1606226675682)(assets/image-20200229114512777.png)]

  3. 实现登录

搭建环境结构(导入选中的资源)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gFboQf5L-1606226675683)(assets/image-20200508150714245.png)]

实现分析

1、创建LoginServleet处理login.jsp进行登录请求

2、LoginServlet校验登录,登录成功将登录数据写入session,登录失败提示消息

LoginServlet代码

package com.itheima.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 */
@WebServlet(name = "LoginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        /*
        * 目标:LoginServlet校验登录,登录成功将登录数据写入session,登录失败提示消息
        * */

        //1、获取用户名与密码
        String user = request.getParameter("user");
        String password = request.getParameter("password");

        //2、校验登录(用户名必须为admin,密码必须为123)
        if("admin".equals(user) && "123".equals(password)) {

            //3、校验通过
            //将登录数据写入session
            request.getSession().setAttribute("loginUser",user);
            //跳转到list.jsp页面
            response.sendRedirect(request.getContextPath()+"/list.jsp");
        }else {

            //4、校验失败
            //请求域存储错误消息
            request.setAttribute("errorMsg","用户名或密码错误");
            //跳转到login.jsp页面显示错误消息
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }
    }
}

修改login.jsp页面显示的错误消息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-onvpRjaH-1606226675684)(assets/1566446428446.png)]

运行效果

访问地址

http://localhost:8080/day15_02_login_control_war_exploded/login.jsp

登录失败效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VIn1vjug-1606226675685)(assets/image-20191227112807525.png)] 

登录成功效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LpsYraSh-1606226675686)(assets/image-20191227112825565.png)]

14.案例2-登录权限控制2-权限控制【应用】

目标

使用过滤器实现登录权限控制

  • 我们的目标是admin目录下的资源必须登录以后才可以访问,那就需要在admin目录的每个资源里面都要判断是否用户登录了,如果没有登录不能访问,这样操作是否麻烦?有没有更好的操作?

    使用过滤器

过滤器代码

package com.itheima.web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 黑马程序员
 *
 * 目标:拦截admin目录下所有资源,判断是否登录,登录了放行,没有登录跳转到登录页面
 */
@WebFilter(filterName = "LoginConrolFilter",urlPatterns = "/admin/*")
public class LoginConrolFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        //1、将请求与响应的父接口转换为子接口(因为子接口功能强大)
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        //2、判断用户是否登录
        //从session中获取登录数据
        String user = (String) request.getSession().getAttribute("loginUser");
        //判断登录是否有效
        if(user!=null) {
            //3、登录了,放行
            chain.doFilter(request,response);

        }else {
            //4、没有登录,跳转到登录页面
            response.sendRedirect(request.getContextPath()+"/login.jsp");
        }
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

小结

  • 过滤器如何拦截浏览器访问admin目录下的所有资源?

    urlPatterns="/admin/*"
    
  • 如何知道用户是否登录了?

    判断sesson中是否含有登录数据,有代表登录,没有代表没有登录
    

15.总结

1.能够说出过滤器的作用

拦截请求与响应

适合解决问题类型:如果某一个操作是你多资源都要进行的,可以将这个操作放入到过滤器中集中处理

2.能够编写过滤器

xml方式:

​ 1、创建一个类实现Filter接口,重写doFilter方法

​ 2、配置web.xml的过滤器拦截路径

注解方式:

​ 1、使用idea提供模板创建过滤器类,重写doFilter方法

​ 2、在注解上@WebFilter里面配置拦截路径

3.能够说出过滤器生命周期相关方法

init方法

doFilter方法

destroy方法

过滤器对象是服务器启动时创建的一个唯一对象

过滤器对象是服务器关闭前效果

4.能够根据过滤路径判断指定的过滤器是否起作用

1、完全匹配:拦截路径与访问的资源路径一模一样

2、目录匹配:拦截指定目录开头的所有资源,格式要求,以“/”开头,以“/*”结尾

3、扩展名匹配:拦截指定扩展名结尾的所有资源,格式要求:以“*”开头,以“.扩展名”结尾

5.能够说出什么是过滤器链

一个资源被多个过滤器拦截请求与响应,并进行串行执行

可以掌握过滤器执行顺序的修改:

注解方式:修改过滤器的类名,控制类名字符串比较升序

xml方式:配置顺序就是执行顺序

6.能够编写过滤器解决全局乱码

单词
Filter过滤器/ˈfɪltər/
chain/tʃeɪn/
encoding编码/ɪn’kodɪŋ/
dispatcher分配器/dɪˈspætʃər/

uest) req;
HttpServletResponse response = (HttpServletResponse) resp;

    //2、判断用户是否登录
    //从session中获取登录数据
    String user = (String) request.getSession().getAttribute("loginUser");
    //判断登录是否有效
    if(user!=null) {
        //3、登录了,放行
        chain.doFilter(request,response);

    }else {
        //4、没有登录,跳转到登录页面
        response.sendRedirect(request.getContextPath()+"/login.jsp");
    }
}

public void init(FilterConfig config) throws ServletException {

}

}


### 小结

* 过滤器如何拦截浏览器访问admin目录下的所有资源?

  ```java
  urlPatterns="/admin/*"
  • 如何知道用户是否登录了?

    判断sesson中是否含有登录数据,有代表登录,没有代表没有登录
    

15.总结

1.能够说出过滤器的作用

拦截请求与响应

适合解决问题类型:如果某一个操作是你多资源都要进行的,可以将这个操作放入到过滤器中集中处理

2.能够编写过滤器

xml方式:

​ 1、创建一个类实现Filter接口,重写doFilter方法

​ 2、配置web.xml的过滤器拦截路径

注解方式:

​ 1、使用idea提供模板创建过滤器类,重写doFilter方法

​ 2、在注解上@WebFilter里面配置拦截路径

3.能够说出过滤器生命周期相关方法

init方法

doFilter方法

destroy方法

过滤器对象是服务器启动时创建的一个唯一对象

过滤器对象是服务器关闭前效果

4.能够根据过滤路径判断指定的过滤器是否起作用

1、完全匹配:拦截路径与访问的资源路径一模一样

2、目录匹配:拦截指定目录开头的所有资源,格式要求,以“/”开头,以“/*”结尾

3、扩展名匹配:拦截指定扩展名结尾的所有资源,格式要求:以“*”开头,以“.扩展名”结尾

5.能够说出什么是过滤器链

一个资源被多个过滤器拦截请求与响应,并进行串行执行

可以掌握过滤器执行顺序的修改:

注解方式:修改过滤器的类名,控制类名字符串比较升序

xml方式:配置顺序就是执行顺序

6.能够编写过滤器解决全局乱码

单词
Filter过滤器/ˈfɪltər/
chain/tʃeɪn/
encoding编码/ɪn’kodɪŋ/
dispatcher分配器/dɪˈspætʃər/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值