基础篇-SpringBoot过滤器Filter的使用


1.过滤器 Filter 简介

1.1 过滤器 Filter 介绍

Filter 是 JavaEE 中 Servlet 规范的一个组件,位于包javax.servlet 中,它可以在 HTTP 请求到达 Servlet 之前,被一个或多个Filter处理。
Filter 工作流程如图:


Filter在生产环境中有很广泛的应用,如:修改请求和响应、防止xss攻击、包装二进制流使其可以多次读等。

1.2 过滤器 Filter 原理

Filter接口 doFilter 的方法,这个方法实现了对用户请求的过滤。具体流程如下:

  1. 用户发送请求到 web 服务器,请求会先到过滤器;
  2. 过滤器会对请求进行一些处理比如过滤请求的参数、修改返回给客户端的 response 的内容、判断是否让用户访问该接口等等。
  3. 用户请求响应完毕。
  4. 进行一些其他操作。

1.3 过滤器 Filter 使用场景

  • 过滤敏感词汇(防止sql注入)
  • 设置字符编码
  • URL级别的权限访问控制
  • 压缩响应信息

1.4 如何自定义过滤器Filter?

1.4.1 通过JavaConfig实现

显式配置 Filter ,功能强大,配置灵活。只需要把每个自定义的 Filter 声明成 Bean 交给 Spring 管理即可,还可以设置匹配的 URL 、指定 Filter 的先后顺序

MyFilter.java

/**
 * 功能描述: 自定义过滤器
 * @author  TuYong
 * @date  2022/6/13 10:26
 */
@Slf4j
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("init filter {}", filterConfig.getFilterName());
    }


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("do filter");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String requestUri = request.getRequestURI();
        log.info("请求的接口为 {}", requestUri);
        long startTime = System.currentTimeMillis();
        filterChain.doFilter(servletRequest, servletResponse);
        long endTime = System.currentTimeMillis();
        log.info("该用户的请求已经处理完毕,请求花费的时间为 {}" , (endTime - startTime));
    }

    @Override
    public void destroy() {
        log.info("destroy filter");
    }
}

MyFilterConfig.java

/**
 * 功能描述: 过滤器配置
 * @author  TuYong
 * @date  2022/6/13 10:29
 */
@Configuration
public class MyFilterConfig {

    @Bean
    public FilterRegistrationBean filterRegistration(){
        // 新建过滤器注册类
        FilterRegistrationBean registration = new FilterRegistrationBean<>();
        // 添加自定义 过滤器
        registration.setFilter(myFilter());
        // 设置过滤器的URL模式
        registration.addUrlPatterns("/api/*");
        //设置过滤器顺序
        registration.setOrder(1);
        return registration;
    }
    @Bean
    public MyFilter myFilter(){
        return new MyFilter();
    }
}

测试接口ApiController.java

/**
 * 功能描述: 测试接口
 * @author  TuYong
 * @date  2022/6/13 10:39
 */
@RestController
@RequestMapping("/api")
public class ApiController {

    @GetMapping("/test1")
    public Object test1(){
        return "success";
    }
}

测试结果
访问接口
http://127.0.0.1:8080/api/test1后,可以看到控制台打印如下:

1.4.2 使用@WebFilter+@ServletComponentScan注解实现

@WebFilter+@ServletComponentScan 注解方式支持对 Filter 匹配指定URL,但是不支持指定 Filter 的执行顺序。

@Slf4j
@WebFilter(urlPatterns = "/api/*")
public class MyFilter2 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("init filter2 {}", filterConfig.getFilterName());
    }


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("do filter2");
    }

    @Override
    public void destroy() {
        log.info("destroy filter2");
    }
}
/**
 * 功能描述: Sb启动类
 * @author  TuYong
 * @date  2022/6/13 11:19
 */
@SpringBootApplication
@ServletComponentScan("com.example.springbootfilter.filter")
public class SpringbootFilterApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootFilterApplication.class, args);
    }

}

测试结果如下:
访问接口
http://127.0.0.1:8080/api/test1后,可以看到控制台打印如下:

1.4.3 基于@Component+@Order注解实现

MyFilter类上加上@Component和@Order注解即可。
当有多个Filter时,这里的@Order(1)注解会指定执行顺序,数字越小,越优先执行,如果只写@Order,默认顺序值是Integer.MAX_VALUE。
@Component + @Order 注解方式配置简单,支持自定义 Filter 顺序。缺点是只能拦截所有URL,不能通过配置去拦截指定的 URL。

@Slf4j
@Component
@Order(1)
public class MyFilter3 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("init filter3 {}", filterConfig.getFilterName());
    }


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("do filter3");
    }

    @Override
    public void destroy() {
        log.info("destroy filter3");
    }
}



发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章