专业的JAVA编程教程与资源

网站首页 > java教程 正文

Spring Boot 中的拦截器和过滤器到底有什么区别?

temp10 2024-11-04 14:08:40 java教程 15 ℃ 0 评论

拦截器(Interceptor)和过滤器(Filter)都是在Spring Boot中对于HTTP请求进行预处理和后处理的机制,但是它们在实现方式、使用场景和工作层级上有一些关键的区别。下面我们就来介绍一下具体的操作以及具体的实现示例。

过滤器(Filter)

过滤器是属于Servlet规范的一部分,其作用在Servlet容器(如 Tomcat)层面。通常情况下过滤器在Spring MVC的执行之前就会被触发,并且支持对原始的HTTP请求和响应进行处理或修改。一般被用来记录日志记录、进行安全认证、进行跨域请求处理等操作,Filter可以直接对请求和响应的流进行操作。

Spring Boot 中的拦截器和过滤器到底有什么区别?

如下所示,过滤器是通过实现javax.servlet.Filter来对HTTP请求进行处理的,在javax.servlet.Filter中主要提供了如下的三个方法。

void init(FilterConfig filterConfig);
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain);
void destroy();

分别表示初始化、执行、以及销毁。下面我们给出一个过滤器来出日志操作的功能实现,来一起看看过滤器如何实现并且使用。

假设我们需要对每个请求进行日志记录,如下所示。

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.util.logging.Logger;

public class LoggingFilter implements Filter {

    private final Logger logger = Logger.getLogger(LoggingFilter.class.getName());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        logger.info("Request received at " + request.getRemoteAddr());
        chain.doFilter(request, response); // 继续传递请求到下一个过滤器或者目标资源
        logger.info("Response sent");
    }

    @Override
    public void destroy() {
        // 销毁操作
    }
}

在Spring Boot中,可以通过如下的配置来将其添加到容器中生效并且使用。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<LoggingFilter> loggingFilter() {
        FilterRegistrationBean<LoggingFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new LoggingFilter());
        registrationBean.addUrlPatterns("/api/*");  // 只对 /api 路径进行过滤
        return registrationBean;
    }
}

过滤器主要作用在请求进入Spring MVC之前,因此可以在请求和响应进入Spring之前对其进行过滤处理。

拦截器(Interceptor)

拦截器,则是属于Spring MVC框架的一部分,其主要作用在Spring MVC层面。在请求被路由到具体的Controller方法前和返回给客户端之前进行处理。典型使用场景主要有对用户权限校验、执行时间统计、在特定请求中修改数据模型等。

如下所示,拦截器的实现主要是基于HandlerInterceptor接口实现,该接口包括了如下的三个方法。

boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler);
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView);
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);

preHandle方法的返回值是一个布尔值,如果返回false,则表示请求不会被传递到下一个拦截器或者Controller方法,直接终止请求处理。

如下所示我们给出一个基于用户认证的拦截器的示例,如下所示,对每个请求进行用户认证拦截。

import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("Authorization");
        if (token == null || !isValidToken(token)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false; // 拦截请求,直接返回 401 未授权
        }
        return true; // 继续请求,进入 Controller
    }

    private boolean isValidToken(String token) {
        // 简单的 token 验证逻辑
        return "valid-token".equals(token);
    }
}

在SpringBoot中拦截器需要在WebMvcConfigurer中进行配置,如下所示。

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/secure/*"); // 只对 /secure 路径进行拦截
    }
}

总结对比

比较点

过滤器(Filter)

拦截器(Interceptor)

层级

Servlet 容器层面

Spring MVC 层面

执行时机

DispatcherServlet 之前

DispatcherServlet 之后,Controller 方法之前和之后

适用场景

跨域、日志、编码转换、请求/响应的过滤等

用户认证、授权、日志、执行时间分析等

接口

javax.servlet.Filter

HandlerInterceptor

影响返回值

无,必须调用

chain.doFilter()

继续执行

有,

preHandle

返回

false

时会中断请求

通过这两个详细的例子,可以看到过滤器和拦截器的不同作用范围、实现方式和使用场景。在选择使用哪个时,通常是根据需要在 Servlet 层还是 Spring MVC 层对请求进行处理来决定的。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表