拦截器(Interceptor)在软件开发中应用广泛,常见于 Web 框架(如 Spring、Struts2)、RPC 框架(如 Dubbo)、以及前端请求库(如 Axios、OkHttp)。虽然概念相似,但不同场景下的常见错误略有不同。
以下从通用逻辑错误、Spring MVC 拦截器、前端 Axios 拦截器以及RPC/微服务拦截器四个维度,为你梳理拦截器中最高频的常见错误及避坑指南。
这是最容易犯的错误,通常是因为拦截器内部又触发了同一个拦截器。
// 伪代码:拦截器中重试请求
if (tokenExpired) {
// 重新获取 token
login();
// 重新发起请求 -> 又会进入这个拦截器 -> 死循环
return client.execute(request);
}
拦截器是“守门员”,如果异常处理不好,会导致上游业务完全不知道发生了什么。
catch 块中仅仅打印日志,不抛出异常,也不返回错误响应。getInputStream() 第二次读取时报 IllegalStateException。拦截器通常是一个链(Chain),如果你不调用下一个节点,请求就断了。
chain.proceed() 或 invocation.invoke()。addPathPatterns 时,路径写错或漏写,导致拦截器不生效。@Override
public void addInterceptors(InterceptorRegistry registry) {
// 错误:只拦截 /api/* (一级目录),不会拦截 /api/user/list
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/api/*");
// 正确:拦截 /api 下的所有路径
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/api/**");
}
/* 只匹配一级路径,/** 匹配多级路径。@Order 或实现 Ordered 接口,或者调整 addInterceptors 的调用顺序来控制。preHandle 中读取 Request Body 导致 Controller 无法读取@RequestBody 默认只能读取一次 InputStream。如果在拦截器中通过 request.getInputStream() 读取了 Body(例如为了做签名验证),Controller 里的参数就会是空的。ContentCachingRequestWrapper 或自定义 HttpServletRequestWrapper 包装器,缓存 Body 数据。.css, .js, /swagger-ui/**),导致页面样式丢失或 Swagger 无法访问。registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/css/**", "/js/**", "/swagger-ui/**");
axios.interceptors.response.use(response => {
// 这里只处理了数据,没 return
return response.data; // 如果这里什么都不 return,后续的 then 拿不到数据
});
.then() 拿到的数据是 undefined。RpcContext 或 ThreadLocal 的变量,但在异步线程池(Async)中执行时,发现变量没了。ThreadLocal 是线程绑定的,异步切换线程后就没了。TransmittableThreadLocal (TTL) 或者在提交任务时手动传递上下文。如果你在调试拦截器,请检查以下几点:
/** vs /*)chain.proceed() / invocation.invoke())通过避免这些常见错误,可以大大减少在拦截器上花费的调试时间。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。