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

浙公网安备 33010602011771号