参数校验

JCP、JSR简介

  • JCP(Java Community Process,Java社区进程)是一个开放的国际组织,是使Java开发者参与定义Java特征和未来版本的正式过程
  • JSR(Java Specification Requests,Java规范提案),JCP使用JSR作为正式规范文档,收集提议加入到Java体系中的规范和技术,任何人都能提交JSR

Bean Validation与Hibernate Validator

  • 最新的Bean验证提议编号为JSR380,提出了Bean Validation 2.0规范
  • Hibernate Validator 6.0.x.Final就是参考Bean Validation 2.0实现的

集成

  • 注意:Spring Boot 2.3.0版本后spring-boot-starter-webspring-boot-starter-webflux不再内置validation starter,需手动引入spring-boot-starter-validation
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
校验注解
Jakarta Bean Validation/JSR提供的所有校验注解
  • @Null 必须为 null

  • @NotNull 必须不为 null

  • @NotEmpty 必须不为 null 或 空

  • @NotBlank 字符序列必须不为空,以及去空格后的长度必须大于 0。与@NotEmpty的不同之处在于,此约束只能应用于字符。

  • @AssertTrue 必须为 true

  • @AssertFalse 必须为 false

  • @Digits(integer=, fraction=) 必须最多包含 integer 位整数和 fraction 位小数的数字

  • @Email 必须为有效的电子邮件地址。可选参数 regexp 和 flags 允许指定电子邮件必须匹配的附加正则表达式(包括正则表达式标志)

  • @Min(value) 必须是一个数值,其值必须大于等于指定的最小值

  • @Max(value) 必须是一个数值,其值必须小于等于指定的最大值

  • @DecimalMin(value) 必须是一个数字,其值必须大于等于指定的最小值

  • @DecimalMax(value) 必须是一个数字,其值必须小于等于指定的最大值

  • @Size(max=, min=) 长度必须在指定的范围内(包括),数据类型支持字符,Collection,Map和数组

  • @Negative 必须为负数,不包含零

  • @NegativeOrZero 必须为负或零

  • @Positive 必须为正数,不包含零

  • @PositiveOrZero 必须为正或零

  • @Past 必须是一个过去的日期

  • @Future 必须是一个将来的日期

  • @FutureOrPresent 必须是现在或将来的日期

  • @PastOrPresent 必须是过去或现在的日期

  • @Pattern(regex=,flag=) 必须符合指定的正则表达式
    Hibernate Validator提供的常用校验注解

  • @CreditCardNumber(ignoreNonDigitCharacters=) 检查是否通过了Luhn校验和测试。此验证旨在检查用户错误,而不是信用卡有效性!ignoreNonDigitCharacters是否忽略非数字字符,默认值为false

  • @Currency(value=) 检查货币单位javax.money.MonetaryAmount是否为指定货币单位的一部分

  • @DurationMax(days=, hours=, minutes=, seconds=, millis=, nanos=, inclusive=) 检查java.time.Duration元素不大于指定范围。如果将inclusive标识位设置为true,则允许相等

  • @DurationMin(days=, hours=, minutes=, seconds=, millis=, nanos=, inclusive=) 检查java.time.Duration元素不少于指定范围。如果将inclusive标识位设置为true,则允许相等

  • @EAN 检查字符序列是有效的EAN条形码。类型默认值为EAN-13

  • @ISBN 检查字符序列是有效的ISBN国际标准书号。类型默认值为ISBN-13

  • @Length(min=, max=) 验证字符序列长度介于(包括)指定的最小值和最大值之间

  • @Range(min=, max=)检查数字值是否介于(包括)指定的最小值和最大值之间

  • @SafeHtml(whitelistType= , additionalTags=, additionalTagsWithAttributes=, baseURI=) 检查HTML值是否包含潜在的恶意脚本片段,例如

    校验注解使用示例

    public class XBoot {  
    
        @Size(max = 16)  
        @NotNull(message = "不能为空")  
        private String username;  
          
        @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "11位手机号格式不正确")  
        @NotNull(message = "不能为空")  
        private String mobile;  
          
        @Email(message = "邮箱格式不正确")  
        @NotNull(message = "不能为空")  
        private String email;  
    }
    

    验证请求参数

    验证请求体(RequestBody)
    Controller:
    @RestController  
    @RequestMapping("/api")  
    publicclass XBootController {  
      
        @PostMapping("/xboot")  
        public ResponseEntity getPerson(@RequestBody @Valid XBoot xboot,
                                        @Valid User user) {  
            return ResponseEntity.ok().body(xboot);  
        }  
    }
    
    验证请求参数(Path Variables 和 Request Parameters)
    Controller或Service:
    • 一定不要忘记在类上加上Validated注解,这个参数可以告诉 Spring 去校验方法参数,Service中的方法同理
    @RestController
    @RequestMapping("/api")
    // 注意记得加上该注解
    @Validated
    public class XBootController {
    
        @GetMapping("/{id}")    
        public R<Integer> get(@PathVariable("id") @Valid @Max(value = 999, message = "ID超过指定范围") Integer id,
                              @RequestParam @Valid @Email(message = "邮箱格式不正确") String email) {
    
            return ResponseEntity.ok().body(id);
        }
    }
    
    使用组
    • 某些场景下我们需要对不同类有不同的验证规则,例如新增时不需验证ID(系统生成)而修改时需验证,可使用groups指定验证生效的类
    • 第一步创建两个接口
    public interface A {
    }
    
    public interface B {
    }
    
    • 第二步指定验证组并使用
    @Null(groups = A.class)
    @NotNull(groups = B.class)
    private String username;
    
    @Service
    @Validated
    public class XBootService {
    
        @Validated(A.class)    
        public void validateA(@Valid XBoot xboot) {
            ...
        }   
    
        @Validated(B.class)    
        public void validateB(@Valid XBoot xboot) { 
            ...
        }
    }
    
    • 使用验证组的时候一定要小心,这是一种反模式,还会造成代码逻辑性变差

    自定义Validator

    示例:校验自定义时间格式如yyyy-MM-dd HH:mm:ss
    • 第一步创建注解
    @Target({FIELD})  
    @Retention(RUNTIME)  
    @Documented
    @Constraint(validatedBy = {DateValidatorImpl.class})
    public @interface DateValidator {  
      
        /**
         * 必须的属性
         */
        String message() default "日期字符格式不匹配"; 
    
        /**
         * 必须的属性
         * 用于分组校验
         */
        Class[] groups() default {};  
          
        Class[] payload() default {};  
    
        /**
         * 非必须 接收用户校验的时间格式
         */
        String dateFormat() default "yyyy-MM-dd HH:mm:ss";
    }
    
    • 第二步实现ConstraintValidator接口,重写isValid方法
    import cn.hutool.core.date.DateUtil;
    import cn.hutool.core.util.StrUtil;
    
    public class DateValidatorImpl implements ConstraintValidator<DateValidator, String> {
    
        private String dateFormat;
    
        @Override
        public void initialize(DateValidator constraintAnnotation) {
    
            // 获取时间格式
            this.dateFormat = constraintAnnotation.dateFormat();
        }
    
        @Override
        public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
    
            if (StrUtil.isBlank(value)) {
                return true;
            }
            try {
                Date date = DateUtil.parse(value, dateFormat);
                return date != null;
            } catch (Exception e) {
                return false;
            }
        }
    }
    

    @NotNull@Column(nullable = false)

    • 在使用 JPA 操作数据的时候会经常碰到@Column(nullable = false) 这种类型的约束,区别:

    @NotNull是 JSR 303 Bean验证注解,与数据库约束无关
    @Column(nullable = false)是JPA声明列为非空的方法

    • 总的来说就是即前者用于验证,而后者则用于指示数据库创建表的时候对表的约束
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值