Spring学习笔记_42——@CookieValue
@CookieValue
1. 介绍
@CookieValue
注解是 Spring Framework 中的一个注解,用于从 HTTP 请求中的 Cookie 中提取值并将其绑定到控制器方法的参数上。
这个注解在开发基于 Spring MVC 的 Web 应用时非常有用,因为它允许开发者方便地访问和操作客户端发送到服务器的 Cookie 数据。
2. 场景
@CookieValue
注解通常用于以下场景:
- 身份验证和会话管理:从 Cookie 中获取用户的身份验证令牌或会话 ID。
- 用户偏好设置:读取用户设置的主题、语言等偏好信息。
- 跟踪和分析:读取用于用户跟踪、分析等的 Cookie 数据。
3. 源码
/**
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.0
* @see RequestMapping
* @see RequestParam
* @see RequestHeader
* @see org.springframework.web.bind.annotation.RequestMapping
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CookieValue {
// String类型的属性,用于指定Cookie的名称
@AliasFor("name")
String value() default "";
// Spring4.2版本开始提供的String类型的属性
// 作用与value属性相同
@AliasFor("value")
String name() default "";
// boolean类型的属性,用于指定是否必须有Cookie信息
// true必须有
// false 非必须有
// 如果设置为true, 请求时没有此Cookie信息会强制报错
// 默认为true
boolean required() default true;
// String类型的属性,用于指定Cookie的默认值
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
4. Demo
4.1 用于身份验证
- 用户登录成功后,将验证信息添加到Cookie中进行返回
@PostMapping("/login")
public ResponseEntity<String> login(@RequestParam String username, @RequestParam String password) {
// 假设这里已经完成了用户名和密码的验证
String authToken = generateAuthToken(username); // 生成认证令牌
// 创建Cookie
Cookie cookie = new Cookie("authToken", authToken);
cookie.setHttpOnly(true); // 设置为 HttpOnly 防止 XSS 攻击
cookie.setSecure(true); // 如果使用 HTTPS,设置为 true
cookie.setPath("/"); // 设置路径为根路径
// 将Cookie添加到响应中
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
response.addCookie(cookie);
return ResponseEntity.ok("Login successful");
}
- 使用@CookieValue注解,提取请求中的Cookie信息进行验证
@RestController
@RequestMapping("/secure")
public class SecureController {
@GetMapping("/data")
public ResponseEntity<String> getSecureData(@CookieValue(value = "authToken", required = true) String authToken) {
// 这里可以调用服务层的方法来验证 authToken
if (isValidToken(authToken)) {
// 返回受保护的数据
return ResponseEntity.ok("Secure data for authenticated user");
} else {
// 认证失败,返回未授权状态
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Unauthorized");
}
}
private boolean isValidToken(String token) {
// 实现你的令牌验证逻辑
// 例如,检查令牌是否存在于数据库中,是否过期等
return token.equals("valid-token"); // 示例中的简单验证
}
}
4.2 用于多语言检测
- 定义一个支持语言的枚举
public enum Language {
ENGLISH("en"),
FRENCH("fr"),
GERMAN("de"),
// 添加更多语言...
UNKNOWN("unknown");
private final String code;
Language(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public static Language fromCode(String code) {
for (Language language : values()) {
if (language.getCode().equals(code)) {
return language;
}
}
return UNKNOWN;
}
}
- 创建Controller处理多语言请求
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class LanguageController {
// 默认语言,可以从配置文件中读取
private static final String DEFAULT_LANGUAGE_CODE = "en";
private static final Language DEFAULT_LANGUAGE = Language.ENGLISH;
@GetMapping("/")
public String showHomePage(
@CookieValue(name = "lang", defaultValue = DEFAULT_LANGUAGE_CODE) String langCode,
Model model) {
// 将Cookie中的语言代码转换为Language枚举
Language language = Language.fromCode(langCode);
// 如果Cookie中的语言代码无效,则使用默认语言
if (language == Language.UNKNOWN) {
language = DEFAULT_LANGUAGE;
}
// 将选中的语言添加到模型中,以便在视图(如JSP、Thymeleaf等)中使用
model.addAttribute("language", language);
// 返回视图名称,例如"home"
return "home";
}
// 其他与语言相关的映射和方法...
}