Java参数校验详解:使用@Valid注解和自定义注解进行参数验证

很多时候我们需要使用不少if、else等等逻辑判断及验证,这样在进行一些重复的参数校验会很麻烦,且以后要维护也会吃力。

而这样就可以使用javax.validation 。**验证(Validation)**常见的验证操作包括验证数据的类型、格式、长度、范围、唯一性等

javax.validation 包:Java SE 6+ 中引入了 javax.validation 包,作为 Bean Validation 规范的一部分。这个包提供了一组注解和接口,可以方便地进行数据验证。

XML 复制代码
<!--        validation组件依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

而对于一般写在业务逻辑类中的参数校验语句,可以省略。如将**@Valid**注解填写在登录接口的方法参数中:

java 复制代码
@PostMapping("/login")
public RespBean login(@Valid @RequestBody User user) {
    log.info("{}", user);
    return userService.login(user);
}
  • @Valid 注解对入参进行相应的校验:

注解使用在方法参数上,然后对于参数的校验要求可去参数的实体类进行校验条件的填写。

java 复制代码
/**
 * @author Z
 * @date 2023/9/27 21:25
 */
@Data
public class User {
    @NotNull //账号非空
    //这个@Mobile是自定义判断注解,下面有对其的创建进行详细的讲解
    @Mobile(required = true) 
    private String mobile;
​
    @NotNull //密码非空
    @Length(min = 32)  //长度的限制
    private String password;
}

以及如: @Size(min=1, max=12) 代表:长度在 1 ~ 12 字符之间。其他一些判断的注解可以去该导入的外部库查看。

**也可以自定判断条件注解:**如@Mobile这个自定义的注解:

1.创建软件包:Validation

2.创建需要的注解:Mobile

3.而对于这个注解的写法,直接去拷贝javax.validation 包中已经写好的注解,如:@Notnull注解进行修改:(有报错的地方就删除不用即可)

@Notnull注解如下:
java 复制代码
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(NotNull.List.class)  //爆红了删除
@Documented
@Constraint(validatedBy = {}) //校验规则的定义
public @interface NotNull {
    String message() default "{javax.validation.constraints.NotNull.message}";
    //修改校验的消息
​
    Class<?>[] groups() default {};
​
    Class<? extends Payload>[] payload() default {};
​
}

而在这里在添加一条属性:(代表必填)

java 复制代码
 boolean required() default true;
  • 自定义的@Mobile如下:

java 复制代码
/**
 * @author Z
 * @date 2023/9/28 8:53
 */
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//自己定义校验规则的一个类:MobileValidator.class (手机号码校验规则类)
//将自定义规则类放进@Constraint(validatedBy={}) 中
@Constraint(validatedBy = {MobileValidator.class})
public @interface Mobile {
​
    boolean required() default true;
​
    //信息,抛出的是BindException,前端页面接收的话,我们要进行异常的捕获
    String message() default "手机号码格式错误";
​
    Class<?>[] groups() default {};
​
    Class<? extends Payload>[] payload() default {};
}

而我们需要进行自己定义检验规则,创建一个校验规则类,并将其放进@Constraint(validatedBy={}) 中

  • 自定义校验规则类:

java 复制代码
/**
 * 手机号码校验规则
 *
 * @author Z
 * @date 2023/9/28 8:56
 */
public class MobileValidator implements ConstraintValidator<Mobile, String> {
​
    private boolean required = false;
​
    //初始化:获取是否需要是必填的
    @Override
    public void initialize(Mobile constraintAnnotation) {
        //获取到填的值:true或者false
        required = constraintAnnotation.required();
    }
​
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        //必填:则使用手机号码校验工具类去校验
        if (required){
            return ValidatorUtil.Mobile(value);
        //非必填:
        }else {
            if (StringUtils.isEmpty(value)){ //传的号码为空
                return true;
            }else {
                //传的号码非空,则使用手机号码校验工具类去校验
                return ValidatorUtil.isMobile(value);
            }
        }
    }
}
  • 而对于手机号码的校验工具类:

添加依赖:

XML 复制代码
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
</dependency>

使用正则表达进行手机号码的校验:

java 复制代码
import org.apache.commons.lang3.StringUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
​
/**
 * 手机号码校验类 (使用正则表达式)
 *
 * @author Z
 * @date 2023/9/27 21:45
 */
public class ValidatorUtil {
​
    private static final Pattern mobile_pattern = Pattern.compile("[1]([3-9])[0-9]{9}$");
​
    public static boolean Mobile(String mobile) {
        if (StringUtils.isEmpty(mobile)){
            return false;
        }
        Matcher matcher = mobile_pattern.matcher(mobile);
        return matcher.matches();
    }
}
相关推荐
子洋几秒前
AI Agent 设计模式 - ReAct 模式
前端·人工智能·后端
晨非辰3 分钟前
基于Win32 API控制台的贪吃蛇游戏:从设计到C语言实现详解
c语言·c++·人工智能·后端·python·深度学习·游戏
Victor3564 分钟前
Netty(27)Netty的拦截器和过滤器是什么?如何使用它们?
后端
码界奇点6 分钟前
基于Go语言的Web管理面板系统设计与实现
开发语言·后端·golang·毕业设计·web·go语言·源代码管理
WizLC7 分钟前
【后端】关于Elasticsearch的入门,下载安装+使用
java·大数据·后端·elasticsearch·搜索引擎·全文检索
青云交7 分钟前
Java 大视界 -- 438 台物联网设备时序数据难题破解:Java+Redis+HBase+Kafka 实战全解析(查询延迟 18ms)(438)
java·智能制造·redis 缓存·hbase 存储·时序数据处理·kafka 消息队列·ai 异常检测
小此方7 分钟前
Re: ゼロから学ぶ C++ 入門(六)类和对象·第三篇:运算符重载
开发语言·c++·后端
Slow菜鸟9 分钟前
Java基础 | JSON 处理手册
java·开发语言·json
喵了几个咪9 分钟前
开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:用 JavaScript/Lua 解锁动态业务扩展能力
javascript·后端·微服务·golang·lua·admin