Java 参数验证 validator

发布于 2024-07-29 20:00:35 字数 5770 浏览 4 评论 0

javax.validation 提供了一系列的注解,帮我们更好的完成参数验证的工作,JSR303 是一套 JavaBean 参数校验的标准,它定义了很多常用的 校验注解 ,可以将注解加在我们 JavaBean 的属性上面进行参数校验。

javax.validation 的 pom 依赖如下:

<!--jsr 303-->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>

没有使用 validation 之前

没有使用 validation 之前我们验证参数会写在 controller 里面

@PostMapping("/save/serial")
public Object save(@RequestBody UserVO userVO) {
    String mobile = userVO.getMobile();

    //手动逐个 参数校验~ 写法
    if (StringUtils.isBlank(mobile)) {
        return RspDTO.paramFail("mobile:手机号码不能为空");
    } else if (!Pattern.matches("^[1][3,4,5,6,7,8,9][0-9]{9}$", mobile)) {
        return RspDTO.paramFail("mobile:手机号码格式不对");
    }

    //抛出自定义异常等~写法
    if (StringUtils.isBlank(userVO.getUsername())) {
        throw new BizException(Constant.PARAM_FAIL_CODE, "用户名不能为空");
    }

    // 比如写一个 map 返回
    if (StringUtils.isBlank(userVO.getSex())) {
        Map<String, Object> result = new HashMap<>(5);
        result.put("code", Constant.PARAM_FAIL_CODE);
        result.put("msg", "性别不能为空");
        return result;
    }
    //.........各种写法 ...
    userService.save(userVO);
    return RspDTO.success();
}

使用 javax.validation 进行参数检验

    // controller
    // 在控制器层进行注解声明 @Validated
    @PostMapping("/save/valid")
    public RspDTO save(@RequestBody @Validated UserDTO userDTO) {
        userService.save(userDTO);
        return RspDTO.success();
    }

// javaBean
// 对参数的字段进行注解标注
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.Date;

@Data
public class UserDTO implements Serializable {
    private static final long serialVersionUID = 1L;

    /*** 用户 ID*/
    @NotNull(message = "用户 id 不能为空")
    private Long userId;

    /** 用户名*/
    @NotBlank(message = "用户名不能为空")
    @Length(max = 20, message = "用户名不能超过 20 个字符")
    @Pattern(regexp = "^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$", message = "用户昵称限制:最多 20 字符,包含文字、字母和数字")
    private String username;

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

    /**性别*/
    private String sex;

    /** 邮箱*/
    @NotBlank(message = "联系邮箱不能为空")
    @Email(message = "邮箱格式不对")
    private String email;

    /** 密码*/
    private String password;

    /*** 创建时间 */
    @Future(message = "时间必须是将来时间")
    private Date createTime;
}

自定义校验规则(以校验身份证号为例)

先定义注解

// 这个注解是作用在 Field 字段上,运行时生效,触发的是 IdentityCardNumber 这个验证类。
// message 定制化的提示信息,主要是从 ValidationMessages.properties 里提取,也可以依据实际情况进行定制
// groups 这里主要进行将 validator 进行分类,不同的类 group 中会执行不同的 validator 操作
// payload 主要是针对 bean 的,使用不多。
@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IdentityCardNumberValidator.class)
public @interface IdentityCardNumber {

    String message() default "身份证号码不合法";

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

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

自定义 Validator

// 这个是真正进行验证的逻辑代码
public class IdentityCardNumberValidator implements ConstraintValidator<IdentityCardNumber, Object> {

    @Override
    public void initialize(IdentityCardNumber identityCardNumber) {
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        return IdCardValidatorUtils.isValidate18Idcard(o.toString());
    }
}

使用自定义注解

    @NotBlank(message = "身份证号不能为空")
    @IdentityCardNumber(message = "身份证信息有误,请核对后提交")
    private String clientCardNo;

使用 groups 区分当前状态是否要进行验证

同一个对象要复用,比如 UserDTO 在更新时候要校验 userId,在保存的时候不需要校验 userId,在两种情况下都要校验 username,groups 就是为了这样的情况使用的

定义 groups 的接口

import javax.validation.groups.Default;

// 在声明分组的时候尽量加上 extend javax.validation.groups.Default 否则没有声明中的 bean 字段就不会去校验,因为默认的校验组是 groups = {Default.class}, 那样下面的 @Email(message = "邮箱格式不对") 因为没有设置 groups 会一直校验
public interface Create extends Default {
}

import javax.validation.groups.Default;

public interface Update extends Default{
}

javaBean 中定义对应的 groups

@Data
public class UserDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    /*** 用户 ID*/
    @NotNull(message = "用户 id 不能为空", groups = Update.class)
    private Long userId;

    /**
     * 用户名
     */
    @NotBlank(message = "用户名不能为空")
    @Length(max = 20, message = "用户名不能超过 20 个字符", groups = {Create.class, Update.class})
    @Pattern(regexp = "^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$", message = "用户昵称限制:最多 20 字符,包含文字、字母和数字")
    private String username;

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

    /**
     * 性别
     */
    private String sex;

    /**
     * 邮箱
     */
    @NotBlank(message = "联系邮箱不能为空")
    @Email(message = "邮箱格式不对")
    private String email;

    /**
     * 密码
     */
    private String password;

    /*** 创建时间 */
    @Future(message = "时间必须是将来时间", groups = {Create.class})
    private Date createTime;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

怀里藏娇

暂无简介

0 文章
0 评论
21 人气
更多

推荐作者

风暴

文章 0 评论 0

乐玩

文章 0 评论 0

英雄似剑

文章 0 评论 0

秋风の叶未落

文章 0 评论 0

luoshaoja

文章 0 评论 0

吴彦文

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文