# Session共享数据

## 向session共享数据

在 Spring MVC 中，**Session** 是用于存储用户会话期间的数据的一种机制。每个用户访问的应用程序都将拥有一个唯一的会话。通过 `HttpSession`，可以在用户的会话中存储一些数据，直到用户关闭浏览器或会话过期。

Spring MVC 提供了多种方式来与 `HttpSession` 进行交互，下面详细介绍如何通过 `HttpSession` 向 Session 共享数据。

### 1. **通过** `HttpSession` **操作 Session 数据**

在 Spring MVC 控制器中，您可以通过 `HttpSession` 对象来存储和读取会话数据。

#### 示例：将数据添加到 Session

```java
@Controller
public class SessionController {

    @RequestMapping("/setSessionData")
    public String setSessionData(HttpSession session) {
        // 将数据存储到 Session 中
        session.setAttribute("username", "JohnDoe");
        session.setAttribute("age", 30);
        return "sessionSet";  // 返回视图名
    }

    @RequestMapping("/getSessionData")
    public String getSessionData(HttpSession session, Model model) {
        // 从 Session 中获取数据
        String username = (String) session.getAttribute("username");
        Integer age = (Integer) session.getAttribute("age");
        model.addAttribute("username", username);
        model.addAttribute("age", age);
        return "sessionData";  // 返回视图名
    }
}
```

**URL 请求：**

- `GET /setSessionData` 会将数据 `"username": "JohnDoe"` 和 `"age": 30` 存储到 Session 中。
- `GET /getSessionData` 会从 Session 中获取并显示存储的值。

### 2. **使用** `@SessionAttributes` **注解**

`@SessionAttributes` 注解用于将控制器中的某些模型属性放入 Session 中。这种方式比直接操作 `HttpSession` 更为方便和简洁，特别是当需要共享多个模型属性时。

#### 示例：使用 `@SessionAttributes`

```java
@Controller
@SessionAttributes("user")
public class UserController {

    // 在模型中添加用户对象
    @RequestMapping("/setUser")
    public String setUser(Model model) {
        User user = new User("John", 30);
        model.addAttribute("user", user);
        return "userSet";
    }

    // 从 Session 中获取用户对象
    @RequestMapping("/getUser")
    public String getUser(@ModelAttribute("user") User user, Model model) {
        model.addAttribute("user", user);
        return "userDetails";
    }
}
```

**URL 请求：**

- `GET /setUser` 会将 `user` 对象放入 Session 中。
- `GET /getUser` 会从 Session 中获取 `user` 对象。

`@SessionAttributes` 注解不仅可以放入 Session 中，还可以与 `@ModelAttribute` 注解结合使用，确保模型数据保持在 Session 中。

### 3. **使用** `@ModelAttribute` **注解**

`@ModelAttribute` 注解允许将数据放入模型中，并且在方法调用前通过 `Model` 传递给视图。如果和 `@SessionAttributes` 一起使用，它可以将属性直接添加到 `HttpSession`。

#### 示例：使用 `@ModelAttribute` 和 `@SessionAttributes`

```java
@Controller
@SessionAttributes("cart")
public class CartController {

    // 在模型中创建并存储购物车
    @ModelAttribute("cart")
    public Cart createCart() {
        return new Cart();  // 创建一个空的购物车对象
    }

    // 添加商品到购物车
    @RequestMapping("/addToCart")
    public String addToCart(@ModelAttribute("cart") Cart cart, @RequestParam("item") String item) {
        cart.addItem(item);  // 将商品添加到购物车
        return "cartUpdated";
    }

    // 显示购物车内容
    @RequestMapping("/viewCart")
    public String viewCart(@ModelAttribute("cart") Cart cart, Model model) {
        model.addAttribute("cart", cart);
        return "viewCart";
    }
}
```

**URL 请求：**

- `GET /addToCart?item=Apple` 会将 `Apple` 添加到 `cart` 中。
- `GET /viewCart` 会显示购物车中的内容。

### 4. **通过** `@RequestParam` **或** `@PathVariable` **获取 Session 数据**

如果在请求中需要通过路径变量或请求参数传递数据并存储到 Session 中，可以结合 `@RequestParam` 或 `@PathVariable` 来实现。

#### 示例：使用 `@RequestParam` 存储 Session 数据

```java
@Controller
public class SessionController {

    @RequestMapping("/setSession/{username}")
    public String setSessionData(@PathVariable("username") String username, HttpSession session) {
        session.setAttribute("username", username);
        return "sessionSet";
    }

    @RequestMapping("/getSession")
    public String getSessionData(HttpSession session, Model model) {
        String username = (String) session.getAttribute("username");
        model.addAttribute("username", username);
        return "sessionData";
    }
}
```

**URL 请求：**

- `GET /setSession/JohnDoe` 会将 `"username": "JohnDoe"` 存储到 Session 中。
- `GET /getSession` 会从 Session 中获取并显示 `username`。

### 5. **删除 Session 数据**

如果希望在某个操作后清除 Session 中的某些数据，可以使用 `HttpSession` 提供的 `removeAttribute` 方法。

#### 示例：删除 Session 数据

```java
@Controller
public class SessionController {

    @RequestMapping("/removeSessionData")
    public String removeSessionData(HttpSession session) {
        session.removeAttribute("username");  // 删除指定的属性
        return "sessionRemoved";
    }
}
```

**URL 请求：**

- `GET /removeSessionData` 会从 Session 中删除 `"username"` 属性。

### 6. **Session 过期与清理**

默认情况下，Spring MVC 的 `HttpSession` 会话会在用户关闭浏览器后过期，或者会话超时（默认30分钟）。可以在 `web.xml` 或应用的配置类中设置会话超时：

#### 示例：设置 Session 超时

```xml
<session-config>
    <session-timeout>30</session-timeout> <!-- 设置会话超时为30分钟 -->
</session-config>
```

### 7. **通过 Spring 配置 Session**

通过 Spring 配置文件或 Java 配置类，还可以控制 Session 的相关行为（如会话过期时间、session 的持久化等）。

#### 示例：Java 配置类

```java
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SessionInterceptor()).addPathPatterns("/**");
    }
}
```

`SessionInterceptor` 可以用于监控和管理 Session 数据。

在 Spring MVC 中，向 Session 共享数据主要有以下几种方式：

- `HttpSession`：通过 `HttpSession` 对象存储和读取 Session 数据。
- `@SessionAttributes`：通过 `@SessionAttributes` 注解将模型属性添加到 Session 中。
- `@ModelAttribute`：结合 `@SessionAttributes` 使用，将模型数据持久化到 Session 中。
- `@RequestParam` **和** `@PathVariable`：将请求参数或路径变量存储到 Session 中。
- **Session 过期与清理**：可以通过配置控制会话超时，或手动清除 Session 数据。
