Spring MVC 中拦截器(Interceptor)开发步骤

在 Spring MVC 中,拦截器(Interceptor)用于在请求处理的前后或完成时执行自定义逻辑(如权限验证、日志记录、性能监控等)。以下是拦截器的开发步骤及示例:


一、拦截器开发步骤

在 Spring MVC 中开发拦截器,需要引入 Spring Web MVC 相关依赖。以下是具体依赖配置(以 Maven 和 Gradle 为例):


1. Maven 依赖配置
(1) 传统 Spring MVC 项目

<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-webmvcartifactId>
    <version>5.3.30version> 
dependency>


<dependency>
    <groupId>javax.servletgroupId>
    <artifactId>javax.servlet-apiartifactId>
    <version>4.0.1version>
    <scope>providedscope> 
dependency>
(2) Spring Boot 项目

Spring Boot 已集成 Spring MVC,只需引入 spring-boot-starter-web

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
    <version>2.7.18version> 
dependency>
(3)依赖作用说明
依赖 作用
spring-webmvc 提供 Spring MVC 核心功能(包括拦截器、控制器、视图解析等)。
javax.servlet-api(或 jakarta.servlet-api Servlet 规范接口(如 HttpServletRequest),Spring MVC 基于 Servlet 实现。
spring-boot-starter-web Spring Boot 对 Spring MVC 的自动化配置依赖,包含 spring-webmvc 及其他组件。

(4)注意事项
  1. 版本兼容性
    • Spring MVC 5.x 需要 Java 8+ 和 Servlet 3.1+。
    • Spring Boot 2.x 默认使用 Spring MVC 5.x。
  2. Servlet API 作用域
    • 在非 Spring Boot 项目中,javax.servlet-api 应设置为 provided,避免打包冲突。
  3. Spring Boot 自动配置
    • 使用 Spring Boot 时,拦截器配置需通过 WebMvcConfigurer(Java 配置)或 WebMvcConfigurerAdapter(旧版)完成,无需额外依赖。

2. 创建拦截器类

实现 HandlerInterceptor 接口,并重写其中的方法:

  • preHandle:在请求到达控制器(Controller)前执行,返回 booleantrue 表示放行,false 表示中断请求)。
  • postHandle:在控制器处理完成后、视图渲染前执行。
  • afterCompletion:在请求完成(视图渲染结束)后执行,常用于资源释放。
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class LoginInterceptor implements HandlerInterceptor {

    // 在Controller方法执行前调用
    @Override
    public boolean preHandle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) throws Exception {
        System.out.println("拦截器 preHandle");
        // 示例:检查用户是否登录
        if (request.getSession().getAttribute("user") == null) {
            response.sendRedirect("/login"); // 未登录则跳转到登录页
            return false; // 中断请求
        }
        return true; // 放行请求
    }

    // 在Controller方法执行后、视图渲染前调用
    @Override
    public void postHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler, 
                           ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器 postHandle");
    }

    // 在整个请求完成后调用(视图渲染结束后)
    @Override
    public void afterCompletion(HttpServletRequest request, 
                                HttpServletResponse response, 
                                Object handler, 
                                Exception ex) throws Exception {
        System.out.println("拦截器 afterCompletion");
    }
}

3. 配置拦截器

在 Spring MVC 配置文件中注册拦截器,并指定拦截路径。

基于 XML 配置(applicationContext.xmlspring-mvc.xml
<mvc:interceptors>
    
    <mvc:interceptor>
        
        <mvc:mapping path="/**"/>
        
        <mvc:exclude-mapping path="/resources/**"/>
        
        <mvc:exclude-mapping path="/login"/>
        <mvc:exclude-mapping path="/doLogin"/>
        
        <bean class="com.example.interceptor.LoginInterceptor"/>
    mvc:interceptor>
mvc:interceptors>
基于 Java 配置(WebMvcConfigurer
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**") // 拦截所有路径
                .excludePathPatterns("/login", "/doLogin"); // 排除特定路径
    }
}

二、拦截器示例:权限验证 + 日志记录

1. 拦截器代码
public class AuthInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) throws Exception {
        // 记录请求信息
        logger.info("请求 URL: {}, 请求方法: {}, IP: {}", 
                    request.getRequestURL(), 
                    request.getMethod(), 
                    request.getRemoteAddr());

        // 检查用户权限(示例)
        if (!hasPermission(request)) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "无权访问");
            return false;
        }
        return true;
    }

    private boolean hasPermission(HttpServletRequest request) {
        // 实际业务中从 Session 或 Token 中获取用户权限
        String userRole = (String) request.getSession().getAttribute("role");
        return "ADMIN".equals(userRole); // 仅管理员可访问
    }
}
2. 配置拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/admin/**") // 只拦截管理路径
                .excludePathPatterns("/admin/login");
    }
}

三、拦截器与过滤器的区别

特性 拦截器(Interceptor) 过滤器(Filter)
所属规范 Spring MVC Servlet 规范
作用范围 Controller 层(Handler 整个请求(ServletRequestServletResponse
依赖关系 依赖 Spring 上下文 不依赖 Spring,纯 Servlet API
访问能力 可访问 Handler 对象(如 Controller 方法) 只能操作请求和响应对象
执行时机 DispatcherServlet 之后执行 DispatcherServlet 之前执行

四、注意事项

  1. preHandle 返回值
    • 必须返回 booleantrue 表示放行,false 会中断后续流程(包括 postHandleafterCompletion)。
  2. 路径匹配
    • 使用 addPathPatternsexcludePathPatterns 精确控制拦截范围。
  3. 线程安全
    • 拦截器是单例的,避免在类中使用成员变量存储请求级别数据。
  4. 与过滤器协作
    • 如果需要修改请求参数或响应头,需结合过滤器实现。

五、常见应用场景

  1. 权限验证:检查用户是否登录或具有访问权限。
  2. 日志记录:记录请求信息(如 URL、参数、耗时)。
  3. 性能监控:统计接口响应时间。
  4. 跨域预处理:配合 CORS 配置。
  5. 防重复提交:通过 Token 机制防止表单重复提交。

通过拦截器,可以轻松实现业务无关的横切关注点(Cross-Cutting Concerns),提升代码复用性和可维护性。

你可能感兴趣的:(后端技术,spring,mvc,hive)