文档站点
Skip to content

Session 与 Cookie ​

Laravel 的 session 驱动默认存文件,靠 Cookie 里的 session id 关联;Spring Boot 默认把 Session 数据存在内存里,靠 JSESSIONID Cookie 关联。概念几乎一样,重点理解「HttpSession」和两个注解。

Session:HttpSession ​

java
@RestController
public class SessionController {

    @GetMapping("/login")
    public String login(HttpSession session) {
        session.setAttribute("user", "张三");   // 相当于 Laravel session(['user' => '张三'])
        return "已登录";
    }

    @GetMapping("/me")
    public Object me(HttpSession session) {
        return session.getAttribute("user");     // 相当于 session('user')
    }

    @PostMapping("/logout")
    public String logout(HttpSession session) {
        session.invalidate();                    // 清空会话
        return "已退出";
    }
}
LaravelSpring Boot
session(['key' => $value])session.setAttribute("key", value)
session('key')session.getAttribute("key")
$request->session()->flush()session.invalidate()
session_id()session.getId()

用注解拿 Session ​

不用 HttpSession 参数也能取,用 @SessionAttribute 读、HttpSession 写:

java
@GetMapping("/me")
public Object me(@SessionAttribute(name = "user", required = false) String user) {
    return user;
}

TIP

@SessionAttribute 读不到且 required=false 时返回 null,不会抛异常。适合「可能未登录」的场景。

java
import jakarta.servlet.http.Cookie;

@PostMapping("/set-cookie")
public String setCookie(HttpServletResponse response) {
    Cookie cookie = new Cookie("theme", "dark");
    cookie.setMaxAge(7 * 24 * 3600);      // 7 天,单位秒(Laravel 用分钟)
    cookie.setPath("/");
    response.addCookie(cookie);
    return "已设置";
}

@GetMapping("/get-cookie")
public String getCookie(@CookieValue(name = "theme", defaultValue = "light") String theme) {
    return theme;
}

TIP

Laravel 的 Cookie 默认是加密的(中间件 EncryptCookies);Spring Boot 的 Cookie 默认不加密。敏感数据要么加密要么只放 session id。

Session 默认存在内存里(重点!) ​

Spring Boot 默认用「内存会话」,数据在 JVM 堆里:

  • 重启应用 → 所有登录态丢失(Laravel 存文件也一样,但文件能持久)
  • 多实例部署 → 负载均衡到另一台机器就丢了登录态

解决办法:

方案场景
spring-boot-starter-data-redis + spring.session.store-type=redis多实例、需持久,最常用
spring.session.store-type=jdbc无 Redis 但有多库
换成 JWT 无状态方案前后端分离的 API 首选(见 认证)

用 Redis 存 Session,配置两步:

yaml
spring:
  data:
    redis:
      host: localhost
      port: 6379
  session:
    store-type: redis

加上依赖:

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

其他代码一行都不用改,Session 自动落到 Redis。这就是 Spring Boot「抽象 + 自动配置」的威力。

类比 Laravel

Laravel 换 session 驱动改 .env 的 SESSION_DRIVER;Spring Boot 换依赖 + spring.session.store-type。都是「接口 + 多实现」,上层代码无感。

超时时间 ​

yaml
server:
  servlet:
    session:
      timeout: 30m      # 30 分钟;默认 30m

与 Laravel 的差异清单 ​

维度LaravelSpring Boot
Cookie 名laravel_sessionJSESSIONID
默认存储文件(storage/framework/sessions)内存
Cookie 加密默认加密不加密
有效期单位分钟秒
多实例需改 Redis需改 Redis(spring.session.store-type)

实践建议 ​

  1. API 接口:优先考虑无状态方案(JWT / Token),别依赖 Session —— 前后端分离下 Session 反而麻烦
  2. 需要服务端会话(传统 MVC 页面):用 Redis 存 Session,避免重启丢登录态
  3. 别在 Session 里放大对象(整个用户实体),只放用户 ID 或轻量 DTO

面向 PHP / Laravel 开发者的 Spring Boot 中文文档