Spring boot Validated 参数注解验证

必要注解

@Validated

必须配在方法上,不然不会生效

    @ApiOperation("新增demo")
    @PostMapping("/add")
    public CommonResult<?> add(@Validated @RequestBody DemoAddVo vo) {
        return CommonResult.success();
    }

全局异常捕获 GlobalExceptionHandler

import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Objects;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResult<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        return CommonResult.failed(Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
    }
}

参数注解

@Null 被注释的元素必须为 null

@NotNull 被注释的元素必须不为 null

@AssertTrue 被注释的元素必须为 true

@AssertFalse 被注释的元素必须为 false

@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值

@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值

@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值

@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值

@Size(max, min) 被注释的元素的大小必须在指定的范围内

@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内

@Past 被注释的元素必须是一个过去的日期

@Future 被注释的元素必须是一个将来的日期

@Pattern(value) 被注释的元素必须符合指定的正则表达式

@Email 被注释的元素必须是电子邮箱地址

@Length 被注释的字符串的大小必须在指定的范围内

@NotEmpty 被注释的字符串的必须非空

@Range 被注释的元素必须在合适的范围内

@NotBlank 验证字符串非null,且长度必须大于0

自定义注解(判断是否在枚举值中)

定义 IdCard 注解

  • @IdCard
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IdCardValidator.class)
public @interface IdCard {

    String message() default "";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    Class<? extends Enum<?>> enumClass();

    String enumMethod() default "isValueValid";

}
  • IdCardValidator 注解实现逻辑
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class IdCardValidator implements ConstraintValidator<IdCard, Integer> {

    Logger log = LoggerFactory.getLogger(IdCardValidator.class);

    private Class<? extends Enum<?>> enumClass;
    private String enumMethod;

    @Override
    public void initialize(IdCard constraintAnnotation) {
        enumClass = constraintAnnotation.enumClass();
        enumMethod = constraintAnnotation.enumMethod();
    }

    @Override
    public boolean isValid(Integer o, ConstraintValidatorContext context) {
        if (ObjectUtils.isEmpty(o)) return Boolean.TRUE;
        if (enumClass == null || StringUtils.isEmpty(enumMethod)) return Boolean.TRUE;
        Class<?> vclass = o.getClass();
        try {
            // 反射机制获取具体的校验方法
            Method method = enumClass.getMethod(enumMethod,vclass);
            if (!Boolean.TYPE.equals(method.getReturnType()) &&
                    !Boolean.class.equals(method.getReturnType())) {
                throw new RuntimeException("校验方法不是布尔类型!");
            }
            if (!Modifier.isStatic(method.getModifiers())) {
                throw new RuntimeException("校验方法不是静态方法!");
            }
            method.setAccessible(true);
            // 调用具体的方法
            Boolean res = (Boolean) method.invoke(null,o);
            return res != null ? res : false;
        } catch (NoSuchMethodException e) {
            log.error("NoSuchMethodException:{}" ,e);
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            log.error("IllegalAccessException:{}" ,e);
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            log.error("InvocationTargetException:{}" ,e);
            throw new RuntimeException(e);
        }
    }
}
  • controllrt&入参实体
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

@RestController
@RequestMapping("/demo")
public class DemoController {

    @PostMapping("/add")
    public CommonResult<?> add(@Validated(Create.class) @RequestBody DemoAddVo vo) {
        return CommonResult.success();
    }

    @PostMapping("/update")
    public CommonResult<?> update(@Validated @RequestBody DemoAddVo vo) {
        return CommonResult.success();
    }

    @Data
    @EqualsAndHashCode(callSuper = false)
    private static class DemoAddVo {

        @NotBlank(message = "name 不能为空")
        private String name;

        @NotBlank(message = "邮箱不能为空")
        @Email(message = "邮箱格式错误")
        private String email;

        @NotBlank(message = "手机号不能为空")
        @Pattern(regexp ="^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
        private String mobileNo;

        @NotNull(message = "类型不能为空")
        //group 指定分组 才执行 (@Validated 需要指定)
        @IdCard(message = "类型错误", enumClass = ConstEnum.DEMO_TYPE.class, groups = Create.class)
        private Integer type;
    }
}
  • 指定分组注解生效
import javax.validation.groups.Default;

/**
 * 参数验证: 创建 group
 */
public interface Create extends Default {
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值