文章目录
- 内置校验器
-
-
- [**一、`javax.validation.constraints` 包下的常用注解**](#一、
javax.validation.constraints包下的常用注解) - [**二、`org.hibernate.validator.constraints` 包下的常用注解(Hibernate Validator扩展)**](#二、
org.hibernate.validator.constraints包下的常用注解(Hibernate Validator扩展)) - **三、注解使用示例**
- [**四、在Spring Boot中使用注解**](#四、在Spring Boot中使用注解)
- [**一、`javax.validation.constraints` 包下的常用注解**](#一、
-
- 自定义校验器
内置校验器
在Java中,javax.validation.constraints包和org.hibernate.validator.constraints包提供了丰富的注解,用于对Java Bean的字段进行验证。以下是这些注解的详细分类和示例:
一、javax.validation.constraints 包下的常用注解
-
空值校验
@Null:验证字段必须为null。@NotNull:验证字段不能为null。@NotEmpty:验证集合、数组或字符串不能为null且长度大于0。@NotBlank:验证字符串不能为null,且去除首尾空格后长度大于0。
-
范围校验
@Size(min, max):验证字符串、集合或数组的长度在指定范围内。@Min(value):验证数值字段的最小值。@Max(value):验证数值字段的最大值。@DecimalMin(value):验证字符串或数值字段的最小值(支持字符串表示的数值)。@DecimalMax(value):验证字符串或数值字段的最大值(支持字符串表示的数值)。@Digits(integer, fraction):验证数值字段的整数部分和小数部分的位数。@Range(min, max):验证数值或字符串字段在指定范围内(Hibernate Validator扩展)。
-
布尔值校验
@AssertTrue:验证布尔字段必须为true。@AssertFalse:验证布尔字段必须为false。
-
日期校验
@Future:验证日期字段必须是将来时间。@FutureOrPresent:验证日期字段必须是将来或现在时间。@Past:验证日期字段必须是过去时间。@PastOrPresent:验证日期字段必须是过去或现在时间。
-
其他校验
@Email:验证字符串字段是否为合法的邮箱地址。@Pattern(regexp):验证字符串字段是否符合指定的正则表达式。@URL:验证字符串字段是否为合法的URL地址(Hibernate Validator扩展)。@SafeHtml:验证字符串字段是否包含安全的HTML(防止XSS攻击,Hibernate Validator扩展)。
二、org.hibernate.validator.constraints 包下的常用注解(Hibernate Validator扩展)
-
长度校验
@Length(min, max):验证字符串字段的长度在指定范围内(与@Size类似,但仅适用于字符串)。
-
其他校验
@CreditCardNumber:验证字符串字段是否为合法的信用卡号。@Currency:验证字符串字段是否为合法的货币值。@EAN:验证字符串字段是否为合法的商品条码(EAN-13或EAN-8)。@LuhnCheck:验证字符串字段是否通过Luhn算法校验(常用于信用卡号、IMEI等)。@ScriptAssert:通过脚本(如JavaScript)进行复杂校验。@UniqueElements:验证集合中的元素是否唯一。
三、注解使用示例
以下是一个完整的Java Bean示例,展示了如何使用上述注解进行字段验证:
java
import javax.validation.constraints.*;
import org.hibernate.validator.constraints.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
public class User {
// 空值校验
@NotNull(message = "用户ID不能为空")
private Long id;
@NotBlank(message = "用户名不能为空")
@Size(min = 3, max = 20, message = "用户名长度必须在3到20个字符之间")
private String username;
// 范围校验
@Min(value = 18, message = "年龄不能小于18岁")
@Max(value = 120, message = "年龄不能大于120岁")
private Integer age;
@DecimalMin(value = "0.01", message = "金额不能小于0.01")
@DecimalMax(value = "1000000.00", message = "金额不能大于1000000.00")
private BigDecimal balance;
// 日期校验
@FutureOrPresent(message = "注册日期不能是将来时间")
private LocalDate registrationDate;
// 其他校验
@Email(message = "邮箱格式不正确")
private String email;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
@URL(message = "URL格式不正确")
private String website;
// Hibernate Validator扩展注解
@Length(min = 6, max = 12, message = "密码长度必须在6到12个字符之间")
private String password;
@CreditCardNumber(message = "信用卡号不合法")
private String creditCardNumber;
@UniqueElements(message = "标签列表中不能有重复元素")
private List<String> tags;
// Getters and Setters
// ...
}
四、在Spring Boot中使用注解
在Spring Boot中,可以通过以下方式启用字段验证:
-
添加依赖:
xml<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> -
在Controller方法中使用
@Valid或@Validated:javaimport org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; @RestController @RequestMapping("/users") public class UserController { @PostMapping public ResponseEntity<String> createUser(@Valid @RequestBody User user) { return ResponseEntity.ok("用户创建成功"); } @PutMapping("/{id}") public ResponseEntity<String> updateUser( @PathVariable Long id, @Validated(UpdateGroup.class) @RequestBody User user) { return ResponseEntity.ok("用户更新成功"); } } -
定义分组(可选):
javapublic interface CreateGroup {} public interface UpdateGroup {} public class User { @NotBlank(groups = CreateGroup.class, message = "创建时用户名不能为空") @NotBlank(groups = UpdateGroup.class, message = "更新时用户名不能为空") private String username; @Null(groups = CreateGroup.class, message = "创建时ID必须为空") @NotNull(groups = UpdateGroup.class, message = "更新时ID不能为空") private Long id; } -
全局异常处理(捕获验证异常):
javaimport org.springframework.http.ResponseEntity; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.util.HashMap; import java.util.Map; @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) { Map<String, String> errors = new HashMap<>(); ex.getBindingResult().getAllErrors().forEach(error -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errors.put(fieldName, errorMessage); }); return ResponseEntity.badRequest().body(errors); } }
自定义校验器
自定义一个校验器,实现必须以xxx 开头。
java
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = PrefixValidator.class) // 关联验证器
public @interface PrefixConstraint {
String message() default "字符串必须以指定前缀开头"; // 默认错误消息
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String prefix() default ""; // 自定义开头前缀属性
}
java
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class PrefixValidator implements ConstraintValidator<PrefixConstraint, String> {
private String prefix; // 动态存储用户设置的开头字符串
@Override
public void initialize(PrefixConstraint constraintAnnotation) {
this.prefix = constraintAnnotation.prefix(); // 初始化时获取注解参数
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// 空值处理(根据业务需求决定是否允许null)
if (value == null) return true;
// 核心验证逻辑:检查字符串是否以指定前缀开头
boolean isValid = value.startsWith(prefix);
if (!isValid) {
// 动态设置错误消息(包含实际前缀值)
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(
"必须以'" + prefix + "'开头,实际值:" + value
).addConstraintViolation();
}
return isValid;
}
}
通常只会提示一个错误,这里修改全局异常处理。
java
@ExceptionHandler(MethodArgumentNotValidException.class)
public R<Object> doException(MethodArgumentNotValidException e) {
List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
ArrayList<FieldError> fieldErrors1 = new ArrayList<>(fieldErrors);
Collections.sort(fieldErrors1,(a,b)->a.getField().compareTo(b.getField()));
FieldError fieldError = fieldErrors1.get(0);
return R.fail(fieldError.getField() + " " + fieldError.getDefaultMessage());
}
使用

运行结果示例
