2025-02-19 17:25:42 +08:00
|
|
|
|
# 向application域共享数据
|
|
|
|
|
|
|
|
|
|
## 向application域共享数据
|
|
|
|
|
|
2025-02-19 16:15:49 +08:00
|
|
|
|
在 Spring MVC 中,`Application` 域(也称为 **ServletContext**)是一个全局范围,用于在整个应用程序中共享数据。不同于 **Session** 域和 **Request** 域,`Application` 域中的数据对整个 Web 应用的所有用户都是可见的,因此适合存储全局共享的配置信息、常量、初始化数据等。
|
|
|
|
|
|
|
|
|
|
在 Spring MVC 中,我们可以通过 `ServletContext` 来向 **Application** 域共享数据,通常使用 `setAttribute` 和 `getAttribute` 方法来进行操作。
|
|
|
|
|
|
2025-02-19 17:25:42 +08:00
|
|
|
|
### 1. **通过** `ServletContext` **共享数据**
|
|
|
|
|
|
2025-02-19 16:15:49 +08:00
|
|
|
|
`ServletContext` 是与整个 Web 应用程序相关联的对象,它允许你在多个请求和多个会话之间共享数据。在 Spring MVC 中,可以通过以下两种方式来访问 `ServletContext`:
|
|
|
|
|
|
2025-02-19 17:25:42 +08:00
|
|
|
|
- 直接使用 `HttpServletRequest.getSession().getServletContext()` 获取 `ServletContext`。
|
|
|
|
|
- 使用 `@Autowired` 注解注入 `ServletContext` 对象。
|
2025-02-19 16:15:49 +08:00
|
|
|
|
|
|
|
|
|
#### 示例 1:通过 `ServletContext` 共享数据
|
2025-02-19 17:25:42 +08:00
|
|
|
|
|
2025-02-19 16:15:49 +08:00
|
|
|
|
##### 1.1 通过 `HttpServletRequest` 获取 `ServletContext`
|
2025-02-19 17:25:42 +08:00
|
|
|
|
|
2025-02-19 16:15:49 +08:00
|
|
|
|
```java
|
|
|
|
|
@Controller
|
|
|
|
|
public class ApplicationController {
|
|
|
|
|
|
|
|
|
|
@RequestMapping("/setApplicationData")
|
|
|
|
|
public String setApplicationData(HttpServletRequest request) {
|
|
|
|
|
// 获取 ServletContext
|
|
|
|
|
ServletContext servletContext = request.getServletContext();
|
|
|
|
|
// 向 Application 域存储数据
|
|
|
|
|
servletContext.setAttribute("appName", "SpringMVCApp");
|
|
|
|
|
servletContext.setAttribute("version", "1.0.0");
|
|
|
|
|
return "applicationDataSet";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@RequestMapping("/getApplicationData")
|
|
|
|
|
public String getApplicationData(HttpServletRequest request, Model model) {
|
|
|
|
|
// 获取 ServletContext
|
|
|
|
|
ServletContext servletContext = request.getServletContext();
|
|
|
|
|
// 从 Application 域获取数据
|
|
|
|
|
String appName = (String) servletContext.getAttribute("appName");
|
|
|
|
|
String version = (String) servletContext.getAttribute("version");
|
|
|
|
|
|
|
|
|
|
model.addAttribute("appName", appName);
|
|
|
|
|
model.addAttribute("version", version);
|
|
|
|
|
return "applicationData";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**URL 请求:**
|
|
|
|
|
|
2025-02-19 17:25:42 +08:00
|
|
|
|
- `GET /setApplicationData` 会向 `Application` 域中存储 `"appName": "SpringMVCApp"` 和 `"version": "1.0.0"`。
|
|
|
|
|
- `GET /getApplicationData` 会从 `Application` 域中读取数据,并返回给视图。
|
2025-02-19 16:15:49 +08:00
|
|
|
|
|
|
|
|
|
##### 1.2 通过 `@Autowired` 注入 `ServletContext`
|
2025-02-19 17:25:42 +08:00
|
|
|
|
|
2025-02-19 16:15:49 +08:00
|
|
|
|
```java
|
|
|
|
|
@Controller
|
|
|
|
|
public class ApplicationController {
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private ServletContext servletContext;
|
|
|
|
|
|
|
|
|
|
@RequestMapping("/setApplicationData")
|
|
|
|
|
public String setApplicationData() {
|
|
|
|
|
// 向 Application 域存储数据
|
|
|
|
|
servletContext.setAttribute("appName", "SpringMVCApp");
|
|
|
|
|
servletContext.setAttribute("version", "1.0.0");
|
|
|
|
|
return "applicationDataSet";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@RequestMapping("/getApplicationData")
|
|
|
|
|
public String getApplicationData(Model model) {
|
|
|
|
|
// 从 Application 域获取数据
|
|
|
|
|
String appName = (String) servletContext.getAttribute("appName");
|
|
|
|
|
String version = (String) servletContext.getAttribute("version");
|
|
|
|
|
|
|
|
|
|
model.addAttribute("appName", appName);
|
|
|
|
|
model.addAttribute("version", version);
|
|
|
|
|
return "applicationData";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
在这个例子中,`@Autowired` 注解会自动将 `ServletContext` 注入到控制器中。
|
|
|
|
|
|
|
|
|
|
### 2. **应用场景**
|
2025-02-19 17:25:42 +08:00
|
|
|
|
|
2025-02-19 16:15:49 +08:00
|
|
|
|
将数据放到 `Application` 域中通常用于存储以下类型的数据:
|
|
|
|
|
|
2025-02-19 17:25:42 +08:00
|
|
|
|
- **应用级别的数据**:例如应用名称、版本号、初始化配置等,这些数据是全局共享的。
|
|
|
|
|
- **常量和初始化信息**:如果有一些需要在多个请求中共享的常量或初始化信息,可以将它们放到 `Application` 域中。
|
|
|
|
|
- **数据库连接池或常用资源**:对于一些全局共享的资源(如数据库连接池),可以在 `Application` 域中进行配置并在不同的请求中共享。
|
2025-02-19 16:15:49 +08:00
|
|
|
|
|
|
|
|
|
### 3. **注意事项**
|
2025-02-19 17:25:42 +08:00
|
|
|
|
|
|
|
|
|
- **全局共享**:与 `Session` 和 `Request` 域不同,`Application` 域中的数据对所有用户和请求都可见。因此,要特别小心在 `Application` 域中存储敏感数据,避免泄漏用户个人信息等。
|
|
|
|
|
- **生命周期**:`Application` 域中的数据在整个应用程序生命周期内有效,直到应用服务器重新启动。因此,放入 `Application` 域的数据一般是全局的、不会频繁变化的。
|
|
|
|
|
- **线程安全**:`Application` 域的数据是共享的,因此在并发访问时要考虑线程安全问题。如果有多个线程访问同一数据,可能需要进行同步。
|
2025-02-19 16:15:49 +08:00
|
|
|
|
|
|
|
|
|
### 4. **清理 Application 域中的数据**
|
2025-02-19 17:25:42 +08:00
|
|
|
|
|
2025-02-19 16:15:49 +08:00
|
|
|
|
如果不再需要某个共享数据,可以使用 `removeAttribute` 方法从 `Application` 域中移除该数据。
|
|
|
|
|
|
|
|
|
|
#### 示例:删除 `Application` 域中的数据
|
2025-02-19 17:25:42 +08:00
|
|
|
|
|
2025-02-19 16:15:49 +08:00
|
|
|
|
```java
|
|
|
|
|
@Controller
|
|
|
|
|
public class ApplicationController {
|
|
|
|
|
|
|
|
|
|
@RequestMapping("/removeApplicationData")
|
|
|
|
|
public String removeApplicationData(HttpServletRequest request) {
|
|
|
|
|
// 获取 ServletContext
|
|
|
|
|
ServletContext servletContext = request.getServletContext();
|
|
|
|
|
// 从 Application 域移除数据
|
|
|
|
|
servletContext.removeAttribute("appName");
|
|
|
|
|
servletContext.removeAttribute("version");
|
|
|
|
|
return "applicationDataRemoved";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**URL 请求:**
|
|
|
|
|
|
2025-02-19 17:25:42 +08:00
|
|
|
|
- `GET /removeApplicationData` 会从 `Application` 域中移除 `appName` 和 `version` 属性。
|
|
|
|
|
|
|
|
|
|
### 5. **使用** `@ApplicationScope`**(Spring 方式)**
|
2025-02-19 16:15:49 +08:00
|
|
|
|
|
|
|
|
|
如果使用 Spring 框架进行开发,也可以使用 Spring 提供的 `@ApplicationScope` 注解来定义在整个应用范围内共享的 Bean。这种方法通常用于 Spring 组件,而不是直接操作 `ServletContext`。
|
|
|
|
|
|
|
|
|
|
#### 示例:使用 `@ApplicationScope`
|
2025-02-19 17:25:42 +08:00
|
|
|
|
|
2025-02-19 16:15:49 +08:00
|
|
|
|
```java
|
|
|
|
|
@Component
|
|
|
|
|
@Scope("application")
|
|
|
|
|
public class AppConfig {
|
|
|
|
|
private String appName = "SpringMVCApp";
|
|
|
|
|
|
|
|
|
|
public String getAppName() {
|
|
|
|
|
return appName;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
在这种情况下,Spring 管理的 Bean 会在应用级别共享,类似于 `ServletContext` 中存储的数据。
|
|
|
|
|
|
2025-02-19 17:25:42 +08:00
|
|
|
|
- `Application` 域(即 `ServletContext`)用于在整个应用程序范围内共享数据,适合存储全局共享的信息、配置和常量。
|
|
|
|
|
- 通过 `HttpServletRequest.getServletContext()` 或 `@Autowired` 注解可以访问 `ServletContext` 并向 `Application` 域中共享数据。
|
|
|
|
|
- 数据存储在 `Application` 域中可以在整个应用程序生命周期内有效,适用于共享全局性的、无需频繁更新的数据。
|
|
|
|
|
- 应谨慎存储敏感数据,并注意线程安全和数据的生命周期。
|