一、Spring中的校验注解
在Spring的使用过程中,有一些现成的注解可以使用
- @AssertFalse:该值必须为False
- @AssertTrue:该值必须为True
- @DecimalMax(value,inclusive):被注释的元素必须是一个数字,其值必须小于等于指定的最大值 ,inclusive表示是否包含该值
- @DecimalMin(value,inclusive):被注释的元素必须是一个数字,其值必须大于等于指定的最小值 ,inclusive表示是否包含该值
- @Digits:限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
- @Email:该值必须为邮箱格式
- @Future:被注释的元素必须是一个将来的日期
- @FutureOrPresent:被注释的元素必须是一个现在或将来的日期
- @Max(value):被注释的元素必须是一个数字,其值必须小于等于指定的最大值
- @Min(value):被注释的元素必须是一个数字,其值必须大于等于指定的最小值
- @Negative:该值必须小于0
- @NegativeOrZero:该值必须小于等于0
- @NotBlank:该值不为空字符串,例如“ ”
- @NotEmpty:该值不为空字符串,例如”“
- @NotNull:该值不为Null
- @Null:该值必须为Null
- @Past:被注释的元素必须是一个过去的日期
- @PastOrPresent:被注释的元素必须是一个过去或现在的日期
- @Pattern(regexp):匹配正则
- @Positive:该值必须大于0
- @PositiveOrZero:该值必须大于等于0
- @Size(min,max):数组大小必须在[min,max]这个区间
二、自定义注解
2.1 自定义注解类
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {IsMobileValidator.class})
public @interface IsMobile {
boolean required() default true;
String message() default "参数不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
该自定义注解类中用到了四种元注解,最后一个注解@Constraint表示校验此注解的校验器类,可以多个。值得一提的是除了自定义的message、require属性外,下面的groups和payload也是必须添加的。
2.2 注解校验类
import org.apache.commons.lang3.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class IsMobileValidator implements ConstraintValidator<IsMobile,String> {
private boolean require = false;
@Override
public void initialize(IsMobile constraintAnnotation) {
require = constraintAnnotation.required();
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
if(require){
return ValidatorUtil.isMobile(s);
}else {
if (StringUtils.isEmpty(s)) {
return true;
}else {
return ValidatorUtil.isMobile(s);
}
}
}
}
校验类需要实现ConstraintValidator接口。接口使用了泛型,需要指定两个参数,第一个自定义注解类,第二个为需要校验的数据类型。实现接口后要override两个方法,分别为initialize方法和isValid方法。其中initialize为初始化方法,可以在里面做一些初始化操作,isValid方法就是我们最终需要的校验方法了。可以在该方法中实现具体的校验步骤。
2.3 校验工具类
import org.apache.commons.lang3.StringUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ValidatorUtil {
private static final Pattern mobile_pattern = Pattern.compile("1\\d{10}");
public static boolean isMobile(String src) {
if (StringUtils.isEmpty(src)) {
return false;
}
Matcher m = mobile_pattern.matcher(src);
return m.matches();
}
}
2.4 group分组接口实现类
我们可能会将UserVO对象用在不同的接口中接收参数,比如在新增和修改接口中。在新增接口中,需要校验mobile,在修改接口中不需要校验mobile。那注解中的groups字段就派上用场了。groups和@Validated配合能控制哪些注解需不需要开启校验。
我们首先定义2个groups分组接口Update和Create,并且继承Default接口。当然也可以不继承Default接口,因为使用注解时不显示指定groups的值,则默认为groups = {Default.class}。所以继承了Default接口,在用@Validated(Create.class)时,也会校验groups = {Default.class}的注解。
import javax.validation.groups.Default;
public interface Create extends Default {
}
import javax.validation.groups.Default;
public interface Update extends Default {
}
2.5 普通实体类
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
public class UserVO {
@NotNull
@IsMobile(message = "手机号格式不正确",groups = Create.class)
private String mobile;
private String password;
}
2.6 controller接口
import com.qimiao.qm.message.board.temp.Create;
import com.qimiao.qm.message.board.temp.UserVO;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Slf4j
@Api(tags = "自定义校验注解")
@RestController
@RequestMapping("user")
public class UserTestController {
@PostMapping
public String add(@RequestBody @Validated(Create.class) UserVO userVO) {
log.info("add userVO,{}", userVO);
return "SUCCESS";
}
@PutMapping
public String update(@RequestBody @Valid UserVO userVO) {
log.info("update userVO,{}", userVO);
return "SUCCESS";
}
}
三、测试


四、扩展
如果参数校验不通过,会抛出MethodArgumentNotValidException异常,我们全局处理下然后返回给接口。
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import lombok.extern.slf4j.Slf4j;
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
// 处理接口参数数据格式错误异常
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public Object errorHandler(HttpServletRequest request, MethodArgumentNotValidException e) {
return e.getBindingResult().getAllErrors();
}
}
网友评论