Spring 拦截器:你的请求休想逃过我的五指山!🚀🚀🚀

拦截器概述

在Spring框架中,拦截器(Interceptor)是一种强大的机制,它允许开发者在请求处理的不同阶段插入自定义逻辑。WebApplicationContext作为Spring Web应用的上下文容器,为拦截器的配置和管理提供了基础支持。

拦截器主要作用于以下场景:

权限验证

日志记录

性能监控

事务管理

通用行为注入等

拦截器与WebApplicationContext的关系

WebApplicationContext是Spring Web应用的IoC容器扩展,它继承自ApplicationContext,并添加了Web应用特有的功能。拦截器通过WebApplicationContext进行注册和管理,成为请求处理管道的一部分。

csharp 复制代码
public interface WebApplicationContext extends ApplicationContext {
    String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
    
    ServletContext getServletContext();
}

拦截器类型

HandlerInterceptor

最常用的拦截器接口,定义了三个关键方法:

java 复制代码
public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) throws Exception {
        return true;
    }
    
    default void postHandle(HttpServletRequest request, 
                          HttpServletResponse response, 
                          Object handler,
                          ModelAndView modelAndView) throws Exception {
    }
    
    default void afterCompletion(HttpServletRequest request, 
                               HttpServletResponse response, 
                               Object handler, 
                               Exception ex) throws Exception {
    }
}

AsyncHandlerInterceptor

HandlerInterceptor的扩展,增加了异步处理的支持。

WebRequestInterceptor

与HandlerInterceptor类似,但提供了更通用的WebRequest抽象,不依赖于Servlet API。

拦截器配置

XML配置方式

markdown 复制代码
    
    
    
    
    
        
        
    

Java配置方式

less 复制代码
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoggingInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/static/**");
        
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/admin/**");
    }
}

注解方式

typescript 复制代码
@Component
public class MyInterceptor implements HandlerInterceptor {
    // 实现方法
}

@Configuration
public class InterceptorConfig {
    
    @Autowired
    private MyInterceptor myInterceptor;
    
    @Bean
    public WebMvcConfigurer adapter() {
        return new WebMvcConfigurer() {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(myInterceptor);
            }
        };
    }
}

拦截器执行流程

拦截器在DispatcherServlet的处理流程中扮演重要角色:

  • preHandle:在处理器执行前调用

返回true继续执行

返回false中断请求处理

  • postHandle:在处理器执行后,视图渲染前调用

可修改ModelAndView

  • afterCompletion:在完整请求完成后调用

适合资源清理

高级拦截器特性

拦截器顺序控制

可以通过order属性控制多个拦截器的执行顺序:

scss 复制代码
registry.addInterceptor(new InterceptorA()).order(1);
registry.addInterceptor(new InterceptorB()).order(2);

路径匹配模式

支持Ant风格的路径模式:

  1. ? 匹配一个字符
    • 匹配零个或多个字符
  2. ** 匹配零个或多个目录

异步请求处理

对于异步请求,afterConcurrentHandlingStarted方法会被调用而不是postHandle和afterCompletion。

拦截器与过滤器的区别

特性 拦截器(Interceptor) 过滤器(Filter)
容器依赖 Spring容器 Servlet容器
作用范围 Spring MVC处理的请求 所有进入容器的请求
访问对象 可以访问Handler和方法信息 只能访问ServletRequest/Response
执行时机 在DispatcherServlet内部执行 在DispatcherServlet外部执行
依赖注入 支持 不支持

实际应用示例

日志拦截器

java 复制代码
public class LoggingInterceptor implements HandlerInterceptor {
    
    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) {
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        logger.info("Request URL: {} : Start Time={}", 
                   request.getRequestURL(), startTime);
        return true;
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, 
                               HttpServletResponse response, 
                               Object handler, 
                               Exception ex) {
        long startTime = (Long) request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        logger.info("Request URL: {} : End Time={} : Time Taken={}ms", 
                   request.getRequestURL(), endTime, (endTime - startTime));
    }
}

认证拦截器

java 复制代码
public class AuthInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler) throws Exception {
        
        HttpSession session = request.getSession();
        if (session.getAttribute("user") == null) {
            response.sendRedirect("/login");
            return false;
        }
        return true;
    }
}

DEMO实测效果

被拦截

未被拦截

相关推荐
老华带你飞35 分钟前
学生信息管理系统|基于Springboot的学生信息管理系统设计与实现(源码+数据库+文档)
java·数据库·spring boot·后端·论文·毕设·学生信息管理系统
Fency咖啡1 小时前
Spring 基础核心 - SpringMVC 入门与请求流程
java·后端·spring·mvc
阑梦清川2 小时前
深入理解文件系统和软硬链接
后端
Cache技术分享2 小时前
204. Java 异常 - Error 类:表示 Java 虚拟机中的严重错误
前端·后端
闲人编程3 小时前
使用Django从零开始构建一个个人博客系统
后端·python·django·接口·restful·web·个人博客
做运维的阿瑞3 小时前
从入门到精通:Django的深度探索之旅
开发语言·后端·python·系统架构·django
Penge6663 小时前
Go语言中的切片展开操作符 ...
后端·go
用户4099322502124 小时前
银行转账不白扣钱、电商下单不超卖,PostgreSQL事务的诀窍是啥?
后端·ai编程·trae
懒惰蜗牛4 小时前
Day27 | Java集合框架之List接口详解
java·后端·java-ee·list
武子康5 小时前
大数据-114 Flink DataStreamAPI 从 SourceFunction 到 RichSourceFunction 源函数的增强与实战
大数据·后端·flink