Spring Boot Validation
SpringBoot 参数校验
校验框架
Bean 校验框架的事实标准:Hibernate Validator
依赖
从 SpringBoot 2.3 开始,需要显式地引入
spring-boot-starter-validation
依赖
领域模型
@Data @Builder @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "users") // user 是数据库的保留字 public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @NotBlank(message = "Name is mandatory") private String name; @NotBlank(message = "Email is mandatory") private String email; }
使用 @NotBlank
注解表示 name 和 email 的值不能为空。
数据访问层:
public interface UserRepository extends JpaRepository<User, Long> {}
控制器层
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @PostMapping public User addUser(@Valid @RequestBody User user) { return userService.addUser(user); } }
当 SpringBoot 发现一个带有 @Valid
注解的参数,它会自动装配 Hibernate Validation 并校验该参数。
在校验失败时,抛出 MethodArgumentNotValidException
异常。
全局异常处理
/** * 全局校验异常处理 * */ @ControllerAdvice public class ValidExceptionHandler { /** * 以 JSON 格式返回校验异常信息 * */ @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseBody public Map<String, String> handleValidationException(MethodArgumentNotValidException e) { Map<String, String> errors = new HashMap<>(); e.getBindingResult() .getAllErrors() .forEach(error -> { String fieldName = ((FieldError)error).getField(); // 字段名 String errorMessage = error.getDefaultMessage(); // 校验失败信息 errors.put(fieldName, errorMessage); }); return errors; } }
测试
@WebMvcTest class UserControllerTest { @Autowired private MockMvc mockMvc; @MockBean private UserService userService; private ObjectMapper objectMapper = new ObjectMapper(); /** * 参数校验成功测试 * */ @Test public void whenPostRequestToUserAndValidUser_thenCorrectResponse() throws Exception { User user = User.builder() .name("Alex") .email("alex@gamil.com") .build(); String json = objectMapper.writeValueAsString(user); mockMvc.perform(post("/user") .content(json) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); } /** * 参数校验失败测试 * */ @Test public void whenPostRequestToUserAndInvalidUser_thenCorrectResponse() throws Exception { User userWithoutName = User.builder() .email("alex@gmail.com") .build(); String json = objectMapper.writeValueAsString(userWithoutName); mockMvc.perform(post("/user") .content(json) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.name", Is.is("Name is mandatory"))); } }
校验注解
注解 | 适用类型 | 说明 |
---|---|---|
@Null | 任何类型 | |
@NotNull | 任何类型 | |
@NotEmpty | 字符串、集合、Map | 元素不能为 null 且不能为空 |
@NotBlank | 字符串 | 字符串不能为 null 并且不能只包含空白字符 |
@Size(min=, max=) | 字符串、集合、Map | 容器大小,包含边界 |
@Max(value=) | 数值 | 最大值 |
@Min(value=) | 数值 | 最小值 |
@Digits(integer=, fraction=) | 数值或字符串 | 数位 |
@Negative | 数值 | 负数,不能是零 |
@NegativeOrZero | 数值 | 负数或零 |
@Positive | 数值 | 正数,不能是零 |
@PositiveOrZero | 数值 | 正数或零 |
@Pattern(regex=, flags=) | 字符串 | 字符串符合正则表达式 |
字符串 | ||
@DecimalMax(value=, inclusive=) | 数值或字符串 | 最大值 |
@DecimalMin(value=, inclusive=) | 数值或字符串 | 最小值 |
@Future | 日期类型 | 将来日期 |
@FutureOrPresent | 日期类型 | 现在或将来日期 |
@Past | 日期类型 | 过去日期 |
@PastOrPresent | 日期类型 | 过去或现在日期 |
@AssertFalse | 布尔值 | |
@AssertTrue | 布尔值 |
数值包括:BigDecimal, BigInteger, byte, short, int, long
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具