【Spring 深入学习】过滤器详解

8 篇文章 0 订阅
文章详细介绍了过滤器在Web开发中的作用,如URL权限控制和敏感信息过滤,并阐述了过滤器的执行时机,即在请求到达Servlet之前。还讲解了过滤器的生命周期,包括构造方法、初始化方法、拦截请求方法和销毁方法。同时,提供了通过配置文件和注解两种方式配置过滤器的示例。最后,给出一个综合案例,展示如何通过过滤器判断请求的header或cookie属性来验证请求的有效性。
摘要由CSDN通过智能技术生成

过滤器详解

1. 概述

今天会详细的讲述下过滤器,过滤器在我们业务开发中占有非常重要地位,比如:
Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能 处理编码

2. 所处位置

那么一般都是什么时候开始执行过滤器的呢,看下图:

在这里插入图片描述

通过上图我们可以得知,其实是在请求到达servlet之前开始执行的。

接下来我们简单看下 过滤器使用过程

  • HttpServletRequest到达 Servlet 之前,拦截客户的HttpServletRequest 。根据需要检查HttpServletRequest,也可以修改HttpServletRequest 头和数据

  • HttpServletResponse到达客户端之前,拦截HttpServletResponse 。根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据

  • Filter接口中有一个doFilter方法,当开发人员编写好Filter,并配置对哪个web资源进行拦截后,Web服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,doFilter方法中有一个filterChain对象,用于继续传递给下一个filter,在传递之前我们可以定义过滤请求的功能,在传递之后,我们可以定义过滤响应的功能

各位看众,不知道是否在Node使用过Koa。这个拦截器链跟整个Koa的思想保持一致。方法filterChain 可以理解为next方法。
设置response的响应值的方法可以理解为ctx.body
都是一种链式调用的思想

3. 生命周期

  • 构造方法

实例化一个Filter对象的方法. 初期的时候执行,执行一次

  • 初始化方法

和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象

  • 拦截请求方法

这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器

  • 销毁方法

Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销毁。在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源

4. 配置过滤器

4.1 通过配置文件配置

定义拦截规则

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean registrationBean() {
        FilterRegistrationBean<MyFilter> myFilterFilterRegistrationBean = new FilterRegistrationBean<>(new MyFilter());

        myFilterFilterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
        return myFilterFilterRegistrationBean;
    }
}

自定义Filter

public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("MyFilter 执行之前");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("MyFilter 执行之后");
    }
}

执行结果

在这里插入图片描述

4.2 通过注解配置

配置 Filter 扫描

@SpringBootApplication
@ServletComponentScan(basePackages = "plus.chendd.filter")
public class SpringBootFilterDemo02Application {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootFilterDemo02Application.class, args);
    }
}

通过注解ServletComponentScan 来配置Filter扫描

自定义 Filter

@WebFilter(urlPatterns = {"/*"})
public class MyFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("MyFilter 执行之前");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("MyFilter 执行之后");
    }
}

关于注解WebFilter 有哪些属性,可以参照下图:

在这里插入图片描述

执行结果

在这里插入图片描述

5. 综合案例

需求:
对所有的请求进行拦截,判断header 或是 cookie是否存在某一个特定属性,并且判断属性值是否符合规范。如果两者都满足说明是我们特定的请求,反之都是无效的请求

配置Filter 过滤规则

@Configuration
public class FilterSetupConfig {

    @Bean
    public FilterRegistrationBean invalidPathFilter() {
        FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>(new AInvalidPath());

        // 添加过滤路径
        filterFilterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
        return filterFilterRegistrationBean;
    }
}

定义Filter 来匹配内容

public class AInvalidPath implements Filter {

    /**
     * 共同的相应处理
     *
     * @param rep
     */
    public void commonRepHandle(HttpServletResponse rep) throws IOException {
        rep.setStatus(200);
        rep.setContentType("application/json; charset=utf-8");
        rep.getWriter().print(new JSONObject(R.fail(Utils.INVALID_PATH).put("msg", "无效的请求")));
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse rep = (HttpServletResponse) servletResponse;

        // 依次获取header 以及cookie的值  以header的优先
        String certificate = null;
        if (req.getHeader("certificate") != null) certificate = req.getHeader("certificate");
        if (StringUtils.isBlank(certificate)) certificate = Utils.getCookieByName(req, "certificate");

        if (StringUtils.isBlank(certificate)) {
            this.commonRepHandle(rep);
            return;
        }

        // 判断验证规范
        if (certificate.length() != 13) {
            this.commonRepHandle(rep);
            return;
        }
        String date = Utils.currDateYmd().replaceAll("-", "").substring(0, 6);
        if (certificate.indexOf("-") == -1 || !date.equals(certificate.substring(0, 6))) {
            this.commonRepHandle(rep);
            return;
        }

        filterChain.doFilter(servletRequest, servletResponse);
    }
}

6. 结论

Filter 过滤器的重要性 不言而喻,多多练习哦。 可以参照如下Demo 源码:配置文件版本, 注解版本

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值