news 2026/5/21 11:09:56

登录请求的流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
登录请求的流程

目录

一、先给结论

二、完整登录请求全流程 + ThreadLocal 存取销毁时序

整体流程链路

1. 分步拆解 + ThreadLocal 操作时机

① 请求进来:preHandle 前置拦截(存入 ThreadLocal)

② 执行业务逻辑(Controller / Service / Mapper)

③ 请求正常响应 / 抛出异常 → 进入 afterCompletion(执行 remove 清空)

三、关键问题:登录接口执行完返回结果,立刻 remove 了吗?

1. 时间线顺序

2. 那登录过程中会不会被提前清空?

四、异常场景会不会漏掉 remove?

场景 1:接口主动抛异常

场景 2:请求被拦截器直接拦截拒绝

五、为什么一定要放在 afterCompletion 清理,不放在 Controller 最后清理?

六、线程池复用下整个流程演示(最核心)

七、错误用法对比(线上事故来源)

错误 1:只 set 不 remove

错误 2:在 Controller 方法末尾清理

正确唯一写法

八、精简面试口述版


一、先给结论

普通登录接口走完响应返回后,不会立刻执行 remove只有完整一次 HTTP 请求从头到尾走完(正常结束 / 异常结束),才会在afterCompletion里执行ThreadLocal.remove()清空上下文。

二、完整登录请求全流程 + ThreadLocal 存取销毁时序

整体流程链路

前端发起登录请求 → 到达网关 → 进入 SpringMVC 拦截器 → 登录 Controller → 登录 Service → 响应返回 → 后置清理 ThreadLocal


1. 分步拆解 + ThreadLocal 操作时机

① 请求进来:preHandle前置拦截(存入 ThreadLocal

@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 1. 从Header拿Token String token = request.getHeader("token"); // 2. 校验Token、解析出当前登录用户信息 LoginUser user = tokenCheckAndGetUser(token); // 3. 把用户信息存入 ThreadLocal UserContext.setUser(user); return true; // 放行进入控制器 }

此时状态

  • 当前请求线程ThreadLocalMap存入了当前登录用户
  • 全局任意业务层、工具类都能UserContext.getUser()获取

② 执行业务逻辑(Controller / Service / Mapper)

@RestController public class LoginController { @PostMapping("/login") public Result login(@RequestBody LoginDTO dto){ // 业务登录逻辑:账号密码校验、生成新token String newToken = loginService.doLogin(dto); // 业务中随时获取当前登录人 Long userId = UserContext.getUserId(); return Result.ok(newToken); } }

全程ThreadLocal 数据一直存在,随时可取。

③ 请求正常响应 / 抛出异常 → 进入afterCompletion执行 remove 清空

@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 不管接口成功、报错、抛异常,都会走到这里 UserContext.clear(); }
// UserContext.clear() 底层 public static void clear(){ USER_THREAD_LOCAL.remove(); }

这里才是真正删除 ThreadLocal 数据的时机


三、关键问题:登录接口执行完返回结果,立刻 remove 了吗?

1. 时间线顺序

  1. 接口代码执行完毕 → 组装返回值 →给前端返回响应
  2. 响应已经发给前端之后,才会执行afterCompletion
  3. 最后才调用remove()清空 ThreadLocal

顺序总结接口业务结束 → 响应返回前端 → 后置拦截器清空 ThreadLocal

2. 那登录过程中会不会被提前清空?

绝对不会

  • preHandle:请求进来前置存数据
  • afterCompletion整个请求生命周期彻底结束才清
  • 中间 Controller、Service 所有代码执行期间,ThreadLocal 数据全程有效

四、异常场景会不会漏掉 remove?

场景 1:接口主动抛异常

public void biz(){ throw new RuntimeException("业务报错"); }

Spring MVC 异常机制:

  1. 异常往上抛
  2. 全局异常处理器捕获
  3. 封装错误响应返回前端
  4. 依然一定会进入 afterCompletion→ 执行 remove

场景 2:请求被拦截器直接拦截拒绝

preHandle返回 false

  • 不会进入 Controller
  • 依然执行 afterCompletion,依旧清空

结论:只要进了 preHandle,就一定会走 afterCompletion,一定能清空

五、为什么一定要放在 afterCompletion 清理,不放在 Controller 最后清理?

  1. Controller 太多,每个人都容易忘写remove
  2. 一旦中间抛异常,Controller 末尾代码不走,直接内存泄漏
  3. afterCompletion是 SpringMVC请求生命周期最终回调,兜底最强,100% 执行
  4. 统一收口,全局只写一次清理代码,规范统一

六、线程池复用下整个流程演示(最核心)

  1. 线程池拿出线程Thread-1
  2. 处理用户 A请求:preHandle 存入 A 用户信息
  3. 执行业务、返回结果
  4. afterCompletionremove 清空→ ThreadLocal 为空
  5. 线程Thread-1归还线程池
  6. 下次复用处理用户 B请求
  7. 重新存入 B 用户信息,用完再次清空

完美闭环,无残留数据,彻底杜绝内存泄漏

七、错误用法对比(线上事故来源)

错误 1:只 set 不 remove

public void login(){ UserContext.setUser(user); // 业务逻辑 // 没有任何清理 }

线程复用后,上一个用户数据残留到下一个请求→ 串号、权限错乱 + 内存泄漏

错误 2:在 Controller 方法末尾清理

public Result login(){ UserContext.setUser(user); biz(); UserContext.clear(); // 写在这里 }

一旦biz()抛异常,最后一行清理代码不执行,直接泄漏。

正确唯一写法

前置存,后置拦截器统一兜底清

八、精简面试口述版

  1. 用户发起登录请求,先经过 Spring 拦截器preHandle,解析 Token 拿到用户信息存入 ThreadLocal 上下文;
  2. 进入登录接口执行业务逻辑,全程可任意获取当前登录用户;
  3. 接口处理完成向前端返回响应;
  4. 请求生命周期结束后,触发拦截器afterCompletion方法,统一调用 ThreadLocal 的 remove 方法清除数据
  5. 无论接口正常执行还是抛出异常,都会执行清空操作;
  6. 线程池复用场景下,每次请求用完必清空,避免用户数据串访与 ThreadLocal 内存泄漏。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/21 11:09:56

SDR++终极指南:3步快速上手软件定义无线电,轻松收听全球广播

SDR终极指南:3步快速上手软件定义无线电,轻松收听全球广播 【免费下载链接】SDRPlusPlus Cross-Platform SDR Software 项目地址: https://gitcode.com/GitHub_Trending/sd/SDRPlusPlus SDR是一款跨平台的开源软件定义无线电工具,让普…

作者头像 李华
网站建设 2026/5/21 11:05:07

英雄联盟国服免费换肤终极指南:R3nzSkin特供版完全使用教程

英雄联盟国服免费换肤终极指南:R3nzSkin特供版完全使用教程 【免费下载链接】R3nzSkin-For-China-Server Skin changer for League of Legends (LOL) 项目地址: https://gitcode.com/gh_mirrors/r3/R3nzSkin-For-China-Server 想在英雄联盟国服免费体验所有皮…

作者头像 李华
网站建设 2026/5/21 11:05:04

渗透测试专用字典体系:按场景结构化、可嵌入工作流的爆破资源

1. 这不是“字典合集”,而是一套可直接嵌入工作流的密码爆破资源体系你有没有过这样的经历:凌晨两点,刚搭好靶机环境,准备对一个Web登录页做弱口令测试,结果卡在了字典选择上——用rockyou.txt?太老&#x…

作者头像 李华
网站建设 2026/5/21 11:04:21

FlexRay协议栈深度拆解:静态段、动态段、星型拓扑到底怎么玩?(附帧结构解析图)

FlexRay协议栈工程实践指南:从帧结构解析到拓扑设计实战 在电动汽车与智能驾驶技术快速迭代的今天,传统CAN总线已难以满足底盘控制、能量管理等关键系统对实时性和确定性的严苛要求。作为宝马、奔驰等车企主导开发的新一代车载网络标准,FlexR…

作者头像 李华