乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 SpringMVC概述与DispatcherServlet

    • 本章导读:Spring MVC概述与DispatcherServlet
    • Spring MVC 是什么
    • MVC 设计模式
    • 前端控制器模式
    • DispatcherServlet
    • 核心组件协作
  • 第2章 控制器与请求映射

    • 本章导读:控制器与请求映射
    • Controller
    • RestController
    • RequestMapping
    • GetMapping
    • PostMapping
    • PutMapping
    • DeleteMapping
    • PathVariable
    • RESTful
    • 请求映射原理
  • 第3章 请求参数获取与转换

    • 本章导读:请求参数获取与转换
    • RequestParam
    • RequestBody
    • RequestHeader
    • CookieValue
    • Model
    • ModelAttribute
    • 数据绑定原理
    • 数据校验
  • 第4章 响应数据与视图解析

    • 本章导读:响应数据与视图解析
    • ResponseBody
    • ResponseEntity
    • ModelAndView
    • ViewResolver
    • HttpMessageConverter
    • forward与redirect
  • 第5章 拦截器过滤器与跨域

    • 本章导读:拦截器、过滤器与跨域
    • HandlerInterceptor
    • WebMvcConfigurer
    • CrossOrigin
    • 登录验证实战
  • 第6章 文件上传与异常处理

    • 本章导读:文件上传与异常处理
    • MultipartFile
    • 文件下载
    • ExceptionHandler
    • ControllerAdvice
    • RestControllerAdvice
    • ResponseStatus
  • 第7章 高级特性与最佳实践

    • 本章导读:高级特性与最佳实践
    • SessionAttributes
    • SessionAttribute
    • RedirectAttributes
    • MockMvc测试
    • 国际化
    • 最佳实践
  • 第8章 扩展与异步机制

    • 本章导读:扩展与异步机制
    • 异步请求处理
    • 自定义参数解析器
    • 内容协商

SessionAttribute

本章聚焦 Spring MVC 从 Session 中读取已存在属性的机制。@SessionAttribute 用于将 HttpSession 中已有的属性绑定到控制器方法的参数上,它是只读的——只能获取,不能写入。理解它与 @SessionAttributes 的区别,是正确使用 Session 数据的关键。


定义与作用

@SessionAttribute 是方法参数级别的注解。它的作用是将当前 HttpSession 中已经存在的指定名称的属性值,自动注入到 Controller 方法的对应参数中。

核心特征:

  • 只读不写:只能读取 Session 中已有的属性,不会在 Session 中创建新属性
  • 前提条件:Session 中必须已经存在该属性,否则抛出 HttpSessionRequiredException
  • 类型转换:Spring MVC 会自动进行类型转换,如果类型不匹配会抛出异常

生活类比:档案室取阅

想象飞翔科技的档案室:

  • @SessionAttribute:你拿着档案编号去档案室取阅已有的档案。如果档案不存在,管理员会告诉你"查无此档"(抛异常)。你只能在阅览区查看,不能把新档案存进去。
  • @SessionAttributes(下一章讲解):这是档案管理员的工作——把新审批通过的档案自动归档到档案室,供后续查阅。

核心原理

Session 属性读取流程

解析时机:@SessionAttribute 的参数解析由 SessionAttributeMethodArgumentResolver 负责。它在参数绑定阶段工作,与 @RequestAttribute 类似,但数据源是 HttpSession 而非 HttpServletRequest。


适用位置与常用属性

属性类型必填说明
value / nameString是(二选一)Session 中属性的名称
requiredboolean否属性是否必须存在,默认 true。设为 false 时,不存在则注入 null

适用位置

  • Controller 方法参数:将 Session 属性绑定到方法形参
@GetMapping("/profile")
public String viewProfile(
        @SessionAttribute("user") User user) {  // 必须存在,否则抛异常
    // ...
}

@GetMapping("/settings")
public String viewSettings(
        @SessionAttribute(name = "user", required = false) User user) {  // 可选
    // user 可能为 null
}

完整示例

场景

飞翔科技员工管理系统中,用户登录成功后,用户信息被存入 Session。后续访问"个人中心""系统设置"等页面时,后端小崔需要从 Session 中读取当前登录用户,而不是每次都从请求参数中传递。

登录时写入 Session(前置步骤)

@PostMapping("/login")
public String login(@RequestParam String username,
                    @RequestParam String password,
                    HttpSession session) {
    // 验证用户名密码...
    User user = userService.authenticate(username, password);
    session.setAttribute("user", user);  // 存入 Session
    return "redirect:/dashboard";
}

使用 @SessionAttribute 读取

package com.feixiang.web.controller;

import com.feixiang.web.entity.User;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/profile")
    public Object getProfile(@SessionAttribute("user") User user) {
        return Map.of(
            "username", user.getUsername(),
            "department", user.getDepartment(),
            "role", user.getRole()
        );
    }

    @GetMapping("/settings")
    public Object getSettings(
            @SessionAttribute(name = "user", required = false) User user) {
        if (user == null) {
            return Map.of("error", "未登录,请先登录");
        }
        return Map.of("theme", user.getPreferenceTheme(), "notify", user.isNotifyEnabled());
    }
}

请求示例一:Session 中存在 user 属性

前置条件:用户已登录,session.setAttribute("user", user) 已执行。

curl -X GET http://localhost:8080/user/profile \
  -H "Cookie: JSESSIONID=xxx"

响应:

{
  "username": "xiaocui",
  "department": "研发部",
  "role": "后端工程师"
}

请求示例二:Session 中不存在 user 属性(required = false)

curl -X GET http://localhost:8080/user/settings

响应:

{
  "error": "未登录,请先登录"
}

请求示例三:Session 中不存在 user 属性(required = true,默认)

curl -X GET http://localhost:8080/user/profile

响应(HTTP 500,未配置异常处理器时):

HttpSessionRequiredException: Expected session attribute 'user'

易错场景与面试考点

误区一:用 @SessionAttribute 向 Session 中写入数据

错误认知:"@SessionAttribute("user") 标注在参数上,如果 Session 中没有,Spring 会帮我创建一个放进去。"

纠正:@SessionAttribute 是只读的。如果 Session 中不存在指定属性且 required = true(默认),会直接抛出 HttpSessionRequiredException。它永远不会向 Session 中写入任何数据。

写入 Session 的正确方式:

  • 使用 HttpSession.setAttribute() 手动写入
  • 使用 @SessionAttributes(类级别注解,下一章讲解)自动同步 Model 属性到 Session

误区二:混淆 @SessionAttribute 与 @SessionAttributes

维度@SessionAttribute@SessionAttributes
级别方法参数类
方向只读(从 Session 取)读写(Model → Session 同步)
创建属性❌ 不会创建✅ 会自动创建
清理方式不适用通过 SessionStatus.setComplete()
典型用途读取登录用户信息跨请求保持表单数据(如多步骤向导)

记忆口诀:带 s 的是类级别的复数形式,负责同步(Sync);不带 s 的是参数级别的单数形式,负责读取(Read)。

面试高频:Session 中属性不存在时的处理

问题:如何避免 @SessionAttribute("user") 在 Session 过期时抛异常?

回答:

  1. 设置 required = false,在方法内判断是否为 null
  2. 配合拦截器,在请求到达 Controller 前检查 Session 中是否存在登录信息,不存在则重定向到登录页
  3. 配置全局异常处理器捕获 HttpSessionRequiredException
@ExceptionHandler(HttpSessionRequiredException.class)
public ResponseEntity<?> handleSessionMissing() {
    return ResponseEntity.status(401).body(Map.of("error", "登录已过期,请重新登录"));
}

小结

@SessionAttribute 用于将 HttpSession 中已存在的属性绑定到 Controller 方法参数。它是只读的,不会在 Session 中创建新属性。如果属性不存在且 required = true,会抛出 HttpSessionRequiredException。它适用于读取登录用户信息、权限信息等需要在整个会话期间保持的数据。

本章与全局的关系:本章讲解了从 Session 读取数据的方式。下一章"SessionAttributes"将讲解类级别的 Session 属性同步机制,以及如何在多步骤表单场景中跨请求保持数据。

上一页
SessionAttributes
下一页
RedirectAttributes