第十二章过滤器Fliter

什么是过滤器

  • 过滤器实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理
  • 通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理

image-20221217144533167

过滤器三要素

拦截

  • 过滤器之所以能够对请求进行预处理,关键是对请求进行拦截,把请求拦截下来才能够做后续的操作。而且对于一个具体的过滤器,它必须明确它要拦截的请求,而不是所有请求都拦截。

过滤

  • 根据业务功能实际的需求,看看在把请求拦截到之后,需要做什么检查或什么操作,写对应的代码即可。

放行

  • 过滤器完成自己的任务或者是检测到当前请求符合过滤规则,那么可以将请求放行。所谓放行,就是让请求继续去访问它原本要访问的资源。

过滤器的实例

filter拦截器代码

@WebFilter("/demo1.do")
public class filter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("拦截了request");
        //在放行操作之前算前置操作,也就是拦截了request,然后进行操作
        filterChain.doFilter(servletRequest,servletResponse);//这一步就是我们的放行操纵
        //在放行操作之前算后置操作,也就是拦截了request,然后进行操作
        System.out.println("拦截了response");
    }

    @Override
    public void destroy() {

    }
}
  • 实现Filter接口,必须实现三个方法 init() ,doFilter()。destory()方法
  • 重要的就是理解我们的"放行操作"
  • @WebFilter(“/demo1.do”)确定过滤什么请求

也可以通过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">

    <filter>
        <filter-name>Demo01Filter</filter-name>
        <filter-class>com.lsc.Filters.filter1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Demo01Filter</filter-name>
        <url-pattern>/demo01.do</url-pattern>
    </filter-mapping>

</web-app>

对应是Servlt实例

@WebServlet("/demo1.do")
public class demo1 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo01 service.....");
        request.getRequestDispatcher("succ.html").forward(request,response);
    }
}

  • 我们最后去访问/demo1.do的请求

image-20221217174300064

过滤器的匹配规则

精确匹配

指定被拦截资源的完整路径:

	<filter>
        <filter-name>Demo01Filter</filter-name>
        <filter-class>com.lsc.Filters.filter1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Demo01Filter</filter-name>
        <url-pattern>/demo01.do</url-pattern>
    </filter-mapping>

模糊匹配

相比较精确匹配,使用模糊匹配可以让我们创建一个Filter就能够覆盖很多目标资源,不必专门为每一个目标资源都创建Filter,提高开发效率。

前杠后星

在我们配置了url-pattern为/user/*之后,请求地址只要是/user开头的那么就会被匹配。

<filter-mapping>
    <filter-name>Target02Filter</filter-name>

    <!-- 模糊匹配:前杠后星 -->
    <!--
        /user/Target02Servlet
        /user/Target03Servlet
        /user/Target04Servlet
    -->
    <url-pattern>/user/*</url-pattern>
</filter-mapping>

极端情况:/*匹配所有请求

前星后缀

下面我们使用png图片来测试后缀拦截的效果,并不是只能拦截png扩展名。

创建一组img标签
    <img th:src="@{/./images/img017.png}"/><br/>
    <img th:src="@{/./images/img018.png}"/><br/>
    <img th:src="@{/./images/img019.png}"/><br/>
    <img th:src="@{/./images/img020.png}"/><br/>
    <img th:src="@{/./images/img024.png}"/><br/>
    <img th:src="@{/./images/img025.png}"/><br/>
创建Filter
<filter>
    <filter-name>Target04Filter</filter-name>
    <filter-class>com.atguigu.filter.filter.Target04Filter</filter-class>
</filter>
<filter-mapping>
    <filter-name>Target04Filter</filter-name>
    <url-pattern>*.png</url-pattern>
</filter-mapping>

前杠后缀,星号在中间

配置方式如下:

<url-pattern>/*.png</url-pattern>

java.lang.IllegalArgumentException: Invalid /*.png in filter mapping

**结论:这么配是*不允许*的!

匹配Servlet名称

<filter-mapping>
    <filter-name>Target05Filter</filter-name>

    <!-- 根据Servlet名称匹配 -->
    <servlet-name>Target01Servlet</servlet-name>
</filter-mapping>

过滤器链

  • 多个Filter的拦截范围如果存在重合部分,那么这些Filter会形成Filter链
  • 浏览器请求重合部分对应的目标资源时,会依次经过Filter链中的每一个Filter。
  • Filter链中每一个Filter执行的顺序是由web.xml中filter-mapping配置的顺序决定的。
@WebFilter("*.do")
public class filter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter1拦截了request");
        //在放行操作之前算前置操作,也就是拦截了request,然后进行操作
        filterChain.doFilter(servletRequest,servletResponse);//这一步就是我们的放行操纵
        //在放行操作之前算后置操作,也就是拦截了request,然后进行操作
        System.out.println("filter1拦截了response");
    }
    @Override
    public void destroy() {

    }
}
@WebFilter("*.do")
public class filter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter2拦截了request");
        //在放行操作之前算前置操作,也就是拦截了request,然后进行操作
        filterChain.doFilter(servletRequest,servletResponse);//这一步就是我们的放行操纵
        //在放行操作之前算后置操作,也就是拦截了request,然后进行操作
        System.out.println("filter2拦截了response");
    }

    @Override
    public void destroy() {

    }
}
@WebFilter("*.do")
public class filter3 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter3拦截了request");
        //在放行操作之前算前置操作,也就是拦截了request,然后进行操作
        filterChain.doFilter(servletRequest,servletResponse);//这一步就是我们的放行操纵
        //在放行操作之前算后置操作,也就是拦截了request,然后进行操作
        System.out.println("filter3拦截了response");
    }

    @Override
    public void destroy() {

    }
}

image-20221217175714192

Filter生命周期

和Servlet生命周期类比,Filter生命周期的关键区别是:在Web应用启动时创建对象

生命周期阶段执行时机执行次数
创建对象Web应用启动时一次
初始化创建对象后一次
拦截请求接收到匹配的请求多次
销毁Web应用卸载前一次
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

库里不会投三分

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值