springboot优雅的参数校验

SpringBoot常见的参数校验

通俗来说:

@NotEmpty 用在集合类上面
@NotBlank  用在String上面
@NotNull 用在基本类型上面

一般我们在开发中 对于一些字段的校验通过if else进行判空,当然这样也不是不可以,但是一旦参数多了的话,那么校验行数代码可就大了,因此采用validator通过注解的方式进行校验参数,也提高了代码的优美性!

什么是Validator

Bean Validation是Java定义的一套基于注解的数据校验规范,目前已经从JSR 303的1.0版本升级到JSR 349的1.1版本,再到JSR 380的2.0版本(2.0完成于2017.08),已经经历了三个版本 。

在SpringBoot中已经集成在 starter-web中,所以无需在添加其他依赖。

内置注解有这些:

空值检查

注解功能
@Null元素必须为空
@NotNull元素不能为空
@NotEmpty元素不能为null或空
@NotBlank校验约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格

Boolean检查

注解功能
@AssertTrue被注释的元素为true
@AssertFalse被注释的元素为false

长度检查

注解功能
@Length(String)长度在范围内
@Size(Array,Colleation,Map,String)长度在范围内
@Range被注释的元素必须在合适的范围内

数值检查

注解功能
@Min(value=“”,message=“”)被注释的元素必须是个数字并且其最小值是这个value值,如果小于的话,会抛出message信息内容
@Max(value=“”,message =“”)被注释的元素必须是个数字并且其最大值是这个value值,如果大于的话,会抛出message信息内容
@DecimalMin被注释的元素必须是个数字并且其值必须大于等于指定的值
@DecimalMax被注释的元素必须是个数字并且其值必须小于等于指定的值
@Digits验证 Number 和 String 的构成是否合法
@Digits (integer, fraction)验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度

时间检查

注解功能
@Past被注释的元素必须是一个过去的日期
@Future被注释的元素必须是一个将来的日期

地址 正则检查

注解功能
@Pattern(value)被注释的元素必须符合指定的正则表达式
@URL被注释的元素必须是个URL地址
@Email指定的元素必须是电子格式

注意:

  • @NotNull 适用于任何类型被注解的元素必须不能与NULL
  • @NotEmpty 适用于String Map或者数组不能为Null且长度必须大于0
  • @NotBlank 只能用于String上面 不能为null,调用trim()后,长度必须大于0

实例:

@Data
@ApiModel("注解参数校验")
public class UserRequestParam implements Serializable {

    @NotNull(message = "用户名字不能notnull")
    @NotBlank(message = "用户名字不能not Blank")
    private String username;

    @Email(message = "email格式错误")
    private String email;

    @NotNull(message = "性别不能为空")
    private Integer sex;
}

接口处需要有@Valid 或者 @Validated注解校验

@ApiOperation("注解测试")
    @PostMapping("test-validate")
    public Result<Boolean> checkUser(@ApiParam @Valid @RequestBody UserRequestParam request){
        return ResultBuilder.success(true);
    }

全局异常处理的地方需要加个参数校验输出

/**
     * 方法参数校验
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error(e.getMessage(), e);
        return ResultBuilder.error(e.getBindingResult().getFieldError().getDefaultMessage());
    }

启动项目 swagger测试接口
测试1: 任何参数都不传,因此username名字报了 @NotBlank的错误
在这里插入图片描述
测试2: email随便填写一个值
在这里插入图片描述
得到的结果就是一个不合法的电子邮件地址! 注意:如果email传空,不会报错的,只有传了值不匹配电子格式会抛出来。

测试3: 性别为Integer不传值
在这里插入图片描述
抛出异常,性别不能为空!

测试4:测试电话号码

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

在这里插入图片描述
电话号码输入不正常抛出异常!

自定义注解

上面都是内置注解,现在可以采用自定义注解的校验
首先添加一个IdCard注解

@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 {};
}

这里重点来介绍一下这几个注解的作用:

@Documented 是元注解,可以修饰其他注解,被其标注的类在生成文档的时候,会显示该类的内容。
@Target Target翻译中文为目标,即该注解可以声明在哪些目标元素之前,也可理解为注释类型的程序元素的种类。
有几种修饰类型:

  • ElementType.PACKAGE:该注解只能声明在一个包名前。
  • ElementType.ANNOTATION_TYPE:该注解只能声明在一个注解类型前。
  • ElementType.TYPE:该注解只能声明在一个类前。
  • ElementType.CONSTRUCTOR:该注解只能声明在一个类的构造方法前。
  • ElementType.LOCAL_VARIABLE:该注解只能声明在一个局部变量前。
  • ElementType.METHOD:该注解只能声明在一个类的方法前。
  • ElementType.PARAMETER:该注解只能声明在一个方法参数前。
  • ElementType.FIELD:该注解只能声明在一个类的字段前。

@Retention :Retention 翻译成中文为保留,可以理解为如何保留,即告诉编译程序如何处理,也可理解为注解类的生命周期。

  • RetentionPolicy.SOURCE : 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;

  • RetentionPolicy.CLASS : 注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;

  • RetentionPolicy.RUNTIME : 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;

    这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码。
    那怎么来选择合适的注解生命周期呢?
    首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。

@Constraint 用来限定自定义注解的地方,找到后面的方法去实现该注解的作用。

创建IdCardValidator类

public class IdCardValidator implements ConstraintValidator<IdCard,Object> {
    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        return IdcardUtil.isValidCard(o.toString());
    }

    @Override
    public void initialize(IdCard constraintAnnotation) {

    }
}

这里直接采用Hutool工具包里IdCardUtil工具类检测身份证号是否正常

测试1:
先添加字段和对应的注解

	@IdCard
    private String idCard;

在这里插入图片描述
随便输入一个身份证号,值异常!
测试2: 输入一个正确的身份证号,未有遗产抛出

group分组

分组校验指的是 一个请求参数可能被多个接口入参所使用,但是每个接口涉及入参的校验信息不完全一致,因为采用分组校验入参信息,只针对该分组的参数信息进行校验!
上代码
创建两个接口分组名称

public interface Create extends Default {
}
public interface Update extends Default {
}

这个入参做了下改动 ,其他的入参忽略掉

@NotNull(message = "用户名字不能notnull",groups = Create.class)
    @NotBlank(message = "用户名字不能not Blank")
    private String username;

    @Email
    @JsonIgnore
    private String email;

    @NotNull(message = "性别不能为空",groups = Update.class)
    private Integer sex;

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

    @JsonIgnore
    private String idCard;

接口处:

public Result<Boolean> checkUser(@Validated(Create.class) @RequestBody UserRequestParam request){
        return ResultBuilder.success(true);
    }

测试1: 名字为空传参 但是性别不为空
在这里插入图片描述
得出结果!
在这里插入图片描述
测试2 : 名字正常传,但是性别不传
在这里插入图片描述
得到以上结果,结果正常!

测试3: 接口处改下校验分组
在这里插入图片描述
得到结果如你所愿
在这里插入图片描述
以上是我个人心得体会!
文档借鉴了该文档部分说明

https://blog.csdn.net/adparking/article/details/112918333

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值