Spring Boot嵌套Record的@RequestBody参数校验失效求助
解决Spring Boot中嵌套Record的校验失效问题
问题核心
使用@WebMvcTest测试控制器时,嵌套Record类型字段仅在为null时校验生效;当该字段存在但内部字段不符合校验规则时,校验未触发,无MethodArgumentNotValidException抛出。
解决方案
将嵌套字段上的@Validated替换为@Valid,触发Spring Bean Validation对嵌套对象的递归校验。
修改后的代码示例
- UpdateFoodReqBody 调整
public record UpdateFoodReqBody( String dietaryRestrictions, // 替换@Validated为@Valid,触发嵌套对象校验 @Valid @NotNull UpdateProductReqBody product ) { }
- UpdateProductReqBody 调整
移除不必要的@Validated注解,字段级校验注解已满足需求:
public record UpdateProductReqBody( @NotBlank String name, String description, @NotNull @Positive BigDecimal price, @NotNull Date pickupTime ) { }
- 控制器方法(可保持不变)
@PostMapping("/update-food/{foodId}") public GetFoodResponse updateFood( @PathVariable @NotNull Long foodId, @Validated @RequestBody UpdateFoodReqBody updatedFood) { return foodService.updateFood(foodId, updatedFood); }
原理说明
@Valid是JSR-380(Bean Validation)规范注解,用于标记需要递归校验的嵌套对象;@Validated是Spring增强注解,核心作用是分组校验,无法触发嵌套对象的递归校验逻辑;- 仅在嵌套字段上添加
@Valid,才能让校验器深入校验嵌套Record的内部字段。
验证测试
修改后的测试用例会正常触发校验,抛出MethodArgumentNotValidException并返回400状态码:
@Test public void testUpdateFood_invalidProductFields() throws Exception { mockMvc.perform(MockMvcRequestBuilders .post(controllerPath + "/update-food/1") .accept(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString( new UpdateFoodReqBody( "Restrictions", new UpdateProductReqBody(null, "Description", null, new Date())) )) .contentType("application/json")) .andExpect(result -> assertTrue(result.getResolvedException() instanceof MethodArgumentNotValidException)) .andExpect(status().isBadRequest()); }
内容的提问来源于stack exchange,提问作者Siim Karel Koger
相关产品推荐
相关产品推荐

