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();
    }
}
相关推荐
一只叫煤球的猫8 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
bobz9658 小时前
tcp/ip 中的多路复用
后端
bobz9658 小时前
tls ingress 简单记录
后端
皮皮林55110 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
你的人类朋友10 小时前
什么是OpenSSL
后端·安全·程序员
bobz96510 小时前
mcp 直接操作浏览器
后端
前端小张同学12 小时前
服务器部署 gitlab 占用空间太大怎么办,优化思路。
后端
databook12 小时前
Manim实现闪光轨迹特效
后端·python·动效
武子康13 小时前
大数据-98 Spark 从 DStream 到 Structured Streaming:Spark 实时计算的演进
大数据·后端·spark
该用户已不存在13 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net