全局异常处理不校验Token,仅捕获已抛异常;Token校验须由拦截器在preHandle中完成,失败时抛TokenInvalidException等自定义异常,再由@RestControllerAdvice统一响应401。

全局异常处理本身不负责校验 Token 是否失效,它只负责捕获和统一响应已抛出的异常。Token 失效的校验必须由拦截器(或过滤器)在请求进入 Controller 之前完成,校验失败时主动抛出特定异常(如 AuthenticationException、NotLoginException 或自定义的 TokenInvalidException),再交由全局异常处理器捕获并格式化返回。
拦截器中完成 Token 校验并抛异常
在 preHandle 方法里解析并验证 token:
- 从请求头(如
Authorization或token)提取 token 字符串 - 调用工具类(如
JwtUtils.verifyToken(token))校验签名、有效期、是否被篡改 - 若校验失败(为空、过期、签名错误、用户不存在等),直接抛出自定义运行时异常,例如:
throw new TokenInvalidException("Token 已过期或无效"); - 不要仅返回
false或设response.setStatus(401)—— 这样异常不会进入全局处理器,而是走 Spring 默认错误页或空响应
全局异常处理器捕获 Token 异常
使用 @RestControllerAdvice 定义处理器,专门响应 Token 相关异常:
- 用
@ExceptionHandler(TokenInvalidException.class)明确捕获 - 返回标准 JSON 结构(如
Result.fail("未登录", 401)),并设置 HTTP 状态码为 401 - 可同时处理其他认证异常,如
NotLoginException、ForbiddenException,保持风格一致
关键注意事项
避免常见失效陷阱:
-
拦截器不能吞掉异常:若在
preHandle中 catch 了校验异常却没 re-throw,全局处理器收不到 -
排除登录等免校验路径:确保
/login、/captcha、/public/**等路径不在拦截范围内,否则会无限重定向 -
Filter 优于 Interceptor(高可靠场景):若用 Sa-Token 或需更早介入(如 Context 初始化前),建议改用
SaServletFilter,它在 Servlet 层执行,能确保异常不被转发机制绕过
配套 ThreadLocal 用户信息透传(可选增强)
校验通过后,可将解析出的 User 对象存入 ThreadLocal,供后续业务层直接获取:
- 在拦截器中调用
UserHolder.set(user) - Controller 或 Service 中通过
UserHolder.getUserId()取值 - 务必在
afterCompletion中调用UserHolder.remove(),防止线程复用导致用户信息错乱


















