Featured image of post Web开发-Interceptor拦截器

Web开发-Interceptor拦截器

1797字

Spring拦截器(Interceptor)学习笔记

一、拦截器概述

1.1 什么是拦截器?

拦截器是Spring框架提供的一种动态拦截方法调用的机制,类似于Servlet中的过滤器(Filter)。主要特点包括:

  • 动态拦截控制器方法的执行
  • 指定方法调用前后执行预设代码
  • 用于处理通用性的业务逻辑(如登录校验、权限检查、日志记录等)

1.2 拦截器 vs 过滤器

特性 拦截器(Interceptor) 过滤器(Filter)
所属框架 Spring MVC Servlet规范
拦截范围 只拦截Spring环境中的资源 拦截所有资源
依赖 依赖Spring容器 不依赖任何框架
执行时机 Controller方法前后 Servlet处理前后
实现接口 HandlerInterceptor Filter

二、拦截器快速入门

2.1 实现步骤

  1. 定义拦截器:实现HandlerInterceptor接口
  2. 注册配置:通过WebMvcConfigurer配置

2.2 代码实现

1) 自定义拦截器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
@Component
public class DemoInterceptor implements HandlerInterceptor {
    // 目标方法执行前调用
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle执行...");
        return true; // true放行,false拦截
    }
    
    // 目标方法执行后调用(视图渲染前)
    @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执行...");
    }
}

2) 注册拦截器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Autowired
    private DemoInterceptor demoInterceptor;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(demoInterceptor)
                .addPathPatterns("/**"); // 拦截所有路径
    }
}

2.3 执行顺序验证

当访问一个Controller方法时,控制台输出:

1
2
3
4
preHandle执行...
Controller方法执行...
postHandle执行...
afterCompletion执行...

注意:如果preHandle返回false,则后续流程都不会执行!

三、登录校验拦截器实战

3.1 令牌校验实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Slf4j
@Component
public class TokenInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 1. 获取请求URL
        String url = request.getRequestURL().toString();
        
        // 2. 登录请求直接放行
        if(url.contains("login")) {
            log.info("登录请求,放行");
            return true;
        }
        
        // 3. 获取token
        String jwt = request.getHeader("token");
        
        // 4. token不存在返回未登录
        if(!StringUtils.hasLength(jwt)) {
            log.error("令牌为空");
            response.setStatus(HttpStatus.SC_UNAUTHORIZED); // 401
            return false;
        }
        
        // 5. 解析token
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {
            log.error("令牌解析失败");
            response.setStatus(HttpStatus.SC_UNAUTHORIZED);
            return false;
        }
        
        // 6. 放行
        log.info("令牌校验通过");
        return true;
    }
}

3.2 配置拦截器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Autowired
    private TokenInterceptor tokenInterceptor;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login"); // 排除登录接口
    }
}

四、拦截器详解

4.1 拦截路径配置

1) 基本配置方法

  • addPathPatterns():添加拦截路径
  • excludePathPatterns():添加排除路径
1
2
3
registry.addInterceptor(interceptor)
        .addPathPatterns("/**")          // 拦截所有
        .excludePathPatterns("/login");  // 排除登录

2) 常见路径模式

模式 说明
/* 一级路径(如/user
/** 任意级路径(如/user/1
/admin/** 拦截/admin下的所有路径
/secure/*.do 拦截/secure下的所有.do请求

4.2 拦截器执行流程

完整请求生命周期

  1. 过滤器前置处理
  2. DispatcherServlet接收请求
  3. 拦截器preHandle
    • 返回true:继续执行
    • 返回false:终止流程
  4. Controller方法执行
  5. 拦截器postHandle
  6. 视图渲染
  7. 拦截器afterCompletion
  8. 过滤器后置处理

执行流程图

image.png

五、最佳实践建议

  1. 登录校验:推荐使用拦截器而非过滤器

    • 能利用Spring的依赖注入
    • 更精准控制Spring环境中的请求
  2. 路径配置

    1
    2
    3
    4
    
    // 推荐配置方式
    registry.addInterceptor(authInterceptor)
            .addPathPatterns("/api/**")
            .excludePathPatterns("/api/public/**");
    
  3. 性能优化

    • preHandle中进行轻量级检查
    • 避免在拦截器中执行耗时操作
  4. 多拦截器顺序

    • 通过order()方法控制执行顺序
    1
    2
    
    registry.addInterceptor(interceptor1).order(1);
    registry.addInterceptor(interceptor2).order(2);
    

六、常见问题解答

Q1:拦截器和过滤器如何选择?

  • 需要处理Spring相关功能(如自动注入、AOP等)→ 拦截器
  • 需要处理静态资源、非Spring请求 → 过滤器

Q2:拦截器能获取Controller方法信息吗? 可以,通过handler参数:

1
2
3
4
5
if (handler instanceof HandlerMethod) {
    HandlerMethod handlerMethod = (HandlerMethod) handler;
    Method method = handlerMethod.getMethod();
    // 可以获取方法注解等信息
}

Q3:拦截器中如何修改响应数据? 可以在postHandle中操作ModelAndView

1
2
3
4
@Override
public void postHandle(...) {
    modelAndView.addObject("newData", "value");
}
如对内容有异议,请联系关邮箱2285786274@qq.com修改