springboot后端枚举为什么可以接受前端的字符串?

springboot后端枚举为什么可以接受前端的字符串?

准确来说一个被PostMapping注解修饰的方法,里边的请求体参数被@Valid @RequestBody 修饰的那个Obj,有一个属性值是枚举值,为什么可以接受前端传来的字符串并转换称为枚举?
是因为这个枚举类内部实现了一个of方法,枚举类也有几个属性,of方法的入参是前端的传过来的值,
of方法的逻辑:通过前端传来的值和枚举的某个属性(到底选择哪个属性来比较可以自己定义)进行比较,把等于该属性值的枚举获取出来。

Spring Boot 中,前端通过 URL 参数传递日期字符串(如 `/api/users?birthday=2024-01-01`),后端需要将其自动转换为 `java.time.LocalDate` 类型。默认情况下,Spring 并不会自动识别所有格式的日期字符串,因此需要进行配置或使用注解来实现正确转换。 --- ## ✅ 方法一:使用 `@DateTimeFormat` 注解(推荐用于 URL 参数) 这是最常用且最直接的方式,适用于 `@RequestParam`、`@PathVariable` 等场景。 ### 示例代码 ```java @RestController @RequestMapping("/api/users") public class UserController { // GET /api/users?birthday=2024-01-01 @GetMapping public String getByBirthday(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate birthday) { return "查询生日为:" + birthday; } // 或者指定自定义格式,例如 yyyy/MM/dd @GetMapping("/custom") public String getByBirthdayCustom(@RequestParam @DateTimeFormat(pattern = "yyyy/MM/dd") LocalDate birthday) { return "自定义格式生日:" + birthday; } } ``` ### 请求示例 ```http GET /api/users?birthday=2024-01-01 → 成功解析为 LocalDate.of(2024, 1, 1) GET /api/users/custom?birthday=2024/01/01 → 成功解析 ``` > ⚠️ 如果不加 `@DateTimeFormat`,Spring 默认尝试用 `ConversionService` 转换,但对 URL 查询参数可能失败或依赖全局设置。 --- ## ✅ 方法二:使用 `@ModelAttribute` + DTO 接收多个参数(含 LocalDate) 当有多个字段时,可以封装成一个对象,并在字段上使用 `@DateTimeFormat`。 ```java public class UserQueryRequest { @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) private LocalDate birthday; private String name; // getter 和 setter public LocalDate getBirthday() { return birthday; } public void setBirthday(LocalDate birthday) { this.birthday = birthday; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ``` 控制器: ```java @GetMapping("/search") public String search(@ModelAttribute UserQueryRequest request) { return "姓名:" + request.getName() + ",生日:" + request.getBirthday(); } ``` 请求: ```http GET /api/users/search?name=张三&birthday=2024-03-15 ``` ✅ 自动绑定并转换成功。 --- ## ✅ 方法三:全局配置日期格式(不推荐,影响其他类型) 你可以在配置类中注册全局的 `WebMvcConfigurer` 来统一处理未标注的日期类型转换。 ### 配置类示例 ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(String.class, LocalDate.class, new Converter<String, LocalDate>() { @Override public LocalDate convert(String source) { if (source == null || source.trim().isEmpty()) { return null; } return LocalDate.parse(source.trim(), DateTimeFormatter.ISO_LOCAL_DATE); } }); } } ``` 这样即使没有 `@DateTimeFormat`,也能转换成功。 > ❗ 注意:这种方式会影响所有 `String -> LocalDate` 的转换,容易引发意外问题(比如格式不符)。建议优先使用 `@DateTimeFormat` 显式声明。 --- ## ✅ 方法四:路径变量中的日期转换(@PathVariable) ```java // GET /api/users/2024-01-01 @GetMapping("/{birthday}") public String getByPath(@PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate birthday) { return "路径中的生日:" + birthday; } ``` 请求: ```http GET /api/users/2024-01-01 ``` ✔️ 正确解析。 --- ## 📌 支持的 `@DateTimeFormat.ISO` 枚举值 | 值 | 示例 | |----|------| | `ISO.DATE` | `2024-01-01` | | `ISO.TIME` | `13:45:30` | | `ISO.DATE_TIME` | `2024-01-01T13:45:30` | 对于 `LocalDate`,推荐使用 `@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)`。 --- ## 💡 常见错误与解决方案 | 错误现象 | 原因 | 解决方案 | |--------|------|---------| | `Failed to convert value of type 'java.lang.String' to ... LocalDate` | 缺少格式化器 | 添加 `@DateTimeFormat` | | 400 Bad Request,参数为空 | 格式错误导致解析失败 | 检查传参是否符合 ISO 标准或 pattern | | 中文错误提示乱码 | 字符编码问题 | 设置 UTF-8 编码 | --- ## ✅ 最佳实践建议 1. **始终使用 `@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)`** 显式标注 URL 参数; 2. 使用标准格式 `yyyy-MM-dd` 传输日期字符串; 3. 对可选参数使用 `@RequestParam(required = false)`; ```java public String get(@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) ``` 4. 前端尽量使用 `dateInput.toISOString().split('T')[0]` 输出标准格式。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值