在 Spring Boot 中使用 Filters

原创
2024/09/03 17:56
阅读数 75

Spring Boot过滤器是构建Web应用程序的重要组成部分,本文我们将讨论以下几个问题:

  1. 什么是过滤器?
  2. 为什么我们需要过滤器?
  3. 在Spring Boot应用程序中添加过滤器的不同方法
  4. 如何使用特定的URL模式注册过滤器

它们允许您拦截请求和响应,以便应用自定义逻辑,例如身份验证、日志记录或修改请求/响应对象。

过滤器简介

过滤器是Java Servlet API的一部分,它们允许您预处理和后处理请求和响应。

创建过滤器

要在Spring Boot中创建过滤器,您可以实现javax.servlet.Filter接口或扩展OncePerRequestFilter类。OncePerRequestFilter确保您的过滤器每个请求只执行一次。

@RestController
@RequestMapping("/customer")
public class CustomerController {

    @GetMapping
    public String getMessage(){
        return "welcome to filter session";
    }
}
@Component
@Slf4j
public class MessageFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("[MessageFilter] - Inside doFilter method");
        log.info("Local Port : " + request.getLocalPort());
        log.info("Server Name : " + request.getServerName());

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        log.info("Method Name : " + httpServletRequest.getMethod());
        log.info("Request URI : " + httpServletRequest.getRequestURI());
        log.info("Servlet Path : " + httpServletRequest.getServletPath());
        chain.doFilter(request, response);
    }
}

要测试此过滤器,请访问http://localhost:9898/customer

过滤器的顺序

过滤器的应用顺序可以通过@Order注解

@Component
@Slf4j
@Order(2)
public class MessageFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("[MessageFilter] - Inside doFilter method");
        log.info("Local Port : " + request.getLocalPort());
        log.info("Server Name : " + request.getServerName());

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        log.info("Method Name : " + httpServletRequest.getMethod());
        log.info("Request URI : " + httpServletRequest.getRequestURI());
        log.info("Servlet Path : " + httpServletRequest.getServletPath());
        chain.doFilter(request, response);
    }
}
@Component
@Slf4j
@Order(1)
public class ProductFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("[ProductFilter] - Inside doFilter method");
        log.info("Local Port : " + request.getLocalPort());
        log.info("Server Name : " + request.getServerName());

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        log.info("Method Name : " + httpServletRequest.getMethod());
        log.info("Request URI : " + httpServletRequest.getRequestURI());
        log.info("Servlet Path : " + httpServletRequest.getServletPath());
        chain.doFilter(request, response);
    }
}

如果您只想打印MessageFilter并跳过ProductFilter

要在访问/customer API时仅显示MessageFilter的日志,您需要有条件地绕过ProductFilter/customer端点的过滤。您可以通过修改ProductFilter来跳过特定端点的过滤来实现这一点。

@Component
@Slf4j
@Order(1) // 确保此过滤器在MessageFilter之前执行
public class ProductFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String requestURI = httpServletRequest.getRequestURI();

        if ("/customer".equals(requestURI)) {
            chain.doFilter(request, response);
            return; // 跳过过滤器的其余部分
        }

        log.info("[ProductFilter] - Inside doFilter method");
        log.info("Local Port : " + request.getLocalPort());
        log.info("Server Name : " + request.getServerName());
        log.info("Method Name : " + httpServletRequest.getMethod());
        log.info("Request URI : " + requestURI);
        log.info("Servlet Path : " + httpServletRequest.getServletPath());

        chain.doFilter(request, response);
    }
}

注册过滤器

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<messagefilter> loggingFilter(){
        FilterRegistrationBean<messagefilter> registrationBean = new FilterRegistrationBean&lt;&gt;();

        registrationBean.setFilter(new MessageFilter());
        registrationBean.addUrlPatterns("/customer/*"); // 如果需要,指定URL模式

        return registrationBean;
    }
}

OncePerRequestFilter

public class ProductFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        log.info("[ProductFilter] - Inside doFilter method");
        log.info("Local Port : " + request.getLocalPort());
        log.info("Server Name : " + request.getServerName());

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        log.info("Method Name : " + httpServletRequest.getMethod());
        log.info("Request URI : " + httpServletRequest.getRequestURI());
        log.info("Servlet Path : " + httpServletRequest.getServletPath());
        filterChain.doFilter(request, response);
    }
}

要测试此过滤器,请访问: http://localhost:9898/product

> 欢迎关注我的公众号:程序猿DD。第一时间了解前沿行业消息、分享深度技术干货、获取优质学习资源</messagefilter></messagefilter>

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部