概述
在 Spring MVC 开发中,@SessionAttributes 是专门用于将控制器中的模型数据暂存到 HTTP Session 中的注解,解决了「请求之间共享数据」的核心问题,避免重复查询数据库、提升交互体验。
本文从核心原理、注解详解、使用步骤、应用场景、完整示例、注意事项六个维度,带你彻底掌握这个注解。
一、核心概念
1. 是什么?
@SessionAttributes 是Spring MVC 控制器级注解 ,作用是:把指定的模型数据(Model)自动存入 HttpSession,在多个请求之间共享,直到手动清除。
2. 核心作用
- 跨请求共享模型数据(表单多步骤提交、页面数据缓存)
- 避免重复从数据库加载数据
- 配合表单回显、数据校验使用
3. 与原生 Session 的区别
表格
| 方式 | 写法 | 适用场景 | 耦合度 |
|---|---|---|---|
@SessionAttributes |
注解驱动,简洁 | 控制器内共享固定模型 | 低(Spring 管理) |
原生 HttpSession |
手动 setAttribute |
全局任意共享数据 | 高(耦合 Servlet API) |
一句话总结:@SessionAttributes 是 Spring 对 Session 的封装,专用于控制器模型数据的会话共享。
二、@SessionAttributes 注解全解析
1. 注解位置
只能加在 控制器类 上,不能加在方法上:
java
@Controller
@SessionAttributes("user") // 正确:类级别
public class UserController { ... }
2. 核心属性
注解支持两个属性,可单独 / 组合使用:
(1)names / value(最常用)
- 作用:指定要存入 Session 的模型属性名称
- 类型:字符串数组,可存多个值
java
// 单个属性
@SessionAttributes("user")
// 多个属性
@SessionAttributes({"user", "orderInfo"})
(2)types
- 作用:按数据类型存入 Session,只要模型中是该类型的对象,自动存 Session
- 适用场景:不关心属性名,只关心类型
java
// 所有 User 类型的模型数据,自动存入 Session
@SessionAttributes(types = User.class)
3. 配套注解
@SessionAttributes 必须配合两个注解使用:
@ModelAttribute:从 Session 中取出数据,绑定到方法参数SessionStatus.setComplete():手动清除 Session 数据(必须手动清,否则数据会一直存在)
三、标准使用步骤
- 控制器类上添加
@SessionAttributes,指定要共享的模型名 / 类型 - 方法中向
Model添加数据 → Spring 自动存入 Session - 其他方法用
@ModelAttribute从 Session 取值 - 业务完成后,调用
SessionStatus.setComplete()清除数据
四、典型应用场景
场景 1:多步骤表单提交(最常用)
例如:注册分三步(基本信息 → 上传头像 → 完成),数据需要跨请求保存。
场景 2:表单数据回显 & 校验失败复用
提交表单校验不通过时,无需重新填写,直接从 Session 回显数据。
场景 3:临时缓存页面公共数据
缓存用户信息、购物车临时数据,避免每次请求查库。
五、完整实战示例
我们以 **「用户多步骤注册」** 为例,演示完整用法。
1. 准备实体类
java
public class User {
private String username;
private String password;
private String email;
// getter、setter、toString
}
2. 编写控制器(核心代码)
java
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;
@Controller
// 核心:将名为 "user" 的模型数据存入 Session
@SessionAttributes("user")
public class RegisterController {
// 第一步:进入表单页面,初始化空 User 对象
@GetMapping("/step1")
public String step1(Model model) {
model.addAttribute("user", new User());
return "step1"; // 跳转到基本信息页面
}
// 第二步:接收第一步数据,自动存入 Session,跳转到第二步
@PostMapping("/step1")
public String doStep1(@ModelAttribute User user) {
// 数据自动存入 Session,无需手动操作
return "redirect:/step2";
}
// 第三步:从 Session 取出 User,展示第二步表单
@GetMapping("/step2")
public String step2(@ModelAttribute User user) {
// 直接使用 Session 中的 user 对象
return "step2";
}
// 第四步:完成注册,清除 Session 数据
@PostMapping("/complete")
public String complete(
@ModelAttribute User user,
SessionStatus sessionStatus
) {
// 执行业务:保存用户到数据库
System.out.println("注册成功:" + user);
// 关键:清除 @SessionAttributes 存储的数据
sessionStatus.setComplete();
return "redirect:/success";
}
}
3. 前端页面(简化示例)
step1.html(基本信息)
html
<form action="/step1" method="post">
用户名:<input name="username"><br>
密码:<input name="password"><br>
<button type="submit">下一步</button>
</form>
step2.html(补充信息)
html
<form action="/complete" method="post">
邮箱:<input name="email"><br>
<!-- 数据自动从 Session 回显 -->
用户名:${user.username}<br>
<button type="submit">完成注册</button>
</form>
4. 执行流程
- 访问
/step1→ 新建User→ 存入Model→ Spring 自动存入 Session - 提交第一步 →
User携带数据 → 仍保存在 Session - 跳转到
/step2→@ModelAttribute从 Session 取出User - 提交完成 → 保存数据 →
setComplete()清空 Session 中的 user
六、必须注意的坑(高频面试 / 开发问题)
1. 必须手动清除,不会自动过期
@SessionAttributes 存储的数据不会随请求结束自动删除,必须调用:
java
sessionStatus.setComplete();
否则会一直留在 Session 中,导致数据混乱。
2. 仅对当前控制器生效
@SessionAttributes 是控制器局部 的,A 控制器存的数据,B 控制器无法获取。如果需要全局共享,用原生 HttpSession。
3. 不能替代登录 Session
@SessionAttributes 用于临时业务数据共享 ,不能存储用户登录态。用户登录信息必须用:
- Spring Security / Shiro 安全框架
- 原生
HttpSession
4. 配合重定向使用
跨请求一定要用 redirect: 重定向,避免表单重复提交。
七、总结:什么时候用?
✅ 推荐使用
- 多步骤表单(注册、下单、发布文章)
- 表单校验失败数据回显
- 控制器内临时缓存模型数据
❌ 不要使用
- 存储用户登录信息(用安全框架)
- 全局共享数据(用原生 Session)
- 不需要跨请求的数据(直接用 Model)
核心口诀
类上注解标名称,模型数据自动存;跨请求用属性取,用完记得手动清。
掌握以上内容,你就能在实际项目中灵活、规范地使用 @SessionAttributes 啦!