SpringBoot-过滤器

387 阅读3分钟


携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情

Servlet规范中有3个非常特殊的Servlet,分别是过滤器、监听器和拦截器,如果使用得当,利用它们可以简单地完成一般Servlet才能实现的烦琐功能。本文介绍过滤器。

过滤器简介

Java中的过滤器是一种特殊的Servlet,它不能处理用户请求,也不能为客户端生成响应信息,它主要用于对HttpServletRequest进行前处理,也可以对HttpServletResponse进行后处理,是一个典型的处理链程序。

过滤器(Filter)放在Web资源之前,可以在前端请求抵达Web资源之前被截获,并且还可以在资源返回客户之前截获输出的请求。过滤器是用来拦截请求的,处于客户端与被请求资源之间,目的是重用代码。在一个项目中可以配置多个过滤器,一个请求会依次通过配置的所有过滤器。

Web项目常用的过滤器有以下3种:

  • 用户授权的过滤器:负责检查用户请求,根据请求信息过滤用户的非法请求。
  • 日志过滤器:详细记录某些特殊的用户请求。
  • 负责编码/解码的过滤器:对请求参数的编码和解码。

过滤器实践

Spring Web提供了很多过滤器,这些过滤器都在org.springframework.web.filter包中,全部实现了javax.servlet.Filter接口。如果项目中需要自定义过滤器,有以下4种实现方式: 直接实现Filter接口。

  1. 继承抽象类GenericFilterBean,此类已经实现了javax.servlet.Filter接口,是普通的Filter实现。
  2. 继承抽象类OncePerRequestFilter,此类是GenericFilterBean的直接子类,主要用于对请求参数的处理。
  3. 继承抽象类AbstractRequestLoggingFilter,该类为OncePerRequestFilter的直接子类,主要用于处理日志过滤。
  4. 自定义过滤器。

下面实现一个自定义的过滤器,过滤请求URL为/test1的请求。如果是这个请求,则打印这个请求的所有参数并直接返回不再继续处理业务,否则直接放行。首先实现一个自定义的Filter,代码如下:

 package com.example.thymeleafdemo.filter;
 import org.springframework.stereotype.Component;
 import javax.servlet.*;
 import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Map;
 ​
 /**
  * 自定义过滤器的实现
  */
 @Component
 public class MyHttpFilter implements Filter {
     /**
      * 过滤方法
      */
     @Override
     public void doFilter(ServletRequest request, ServletResponse response,
                          FilterChain chain) throws IOException, Servlet
         Exception {
         HttpServletRequest servletRequest = (HttpServletRequest) request;
         String requestURI = servletRequest.getRequestURI();
         if ("/test1".equals(requestURI)) {
             Map<String, String[]> map = servletRequest.getParameterMap();
             for (Map.Entry<String, String[]> entry : map.entrySet()) {
                 System.out.println("请求的参数名字是:" + entry.getKey()
                                    + " ,请求的值是:" + Arrays.toString(entry.getValue()));
                 return;
             }
         }
         //放行,继续后面的业务处理
         chain.doFilter(servletRequest,response);
     }
 }

在UserController.java文件中添加test1方法的代码如下:

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

过滤器使用场景:

  • 执行目标资源之前执行预处理,如设置编码;
  • 通过条件判断是否放行,如校验当前用户是否已经登录,或某些用户的IP是否被禁用;
  • 目标资源执行后,后续的特殊处理工作,如处理目标资源输出的数据。