身份证号码,格式校验:@IdCard(Validation + Hutool)

目标

自定义一个用于校验 身份证号码 格式的注解@IdCard,能够和现有的 Validation 兼容,使用方式和其他校验注解保持一致(使用 @Valid 注解接口参数)。

校验逻辑

有效格式

符合国家标准。

公民身份号码按照GB11643-1999《公民身份号码》国家标准编制,由18位数字组成:前6位为行政区划代码,第7至14位为出生日期码,第15至17位为顺序码,第18位为校验码。

不校验非空

身份证号码注解,校验的是格式;不校验是否为空(null 或 空字符串)。如果身份证号码为空,此注解校验是可以通过的;

校验非空,使用注解 @NotEmpty;根据业务逻辑来确定,身份证号码是否需要判断非空。

校验格式的工具:Hutool

使用Hutool提供的身份证格式校验方法。

注意,Hutool 校验身份证格式,忽略X的大小写;也就是,大小写的X,都认为表达的是罗马数字十

依赖

  1. Validation
  2. Hutool

Validation:

xml 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

Hutool:

xml 复制代码
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.22</version>
        </dependency>

核心代码

需要自定义的内容,包含两个部分:

  1. 注解@IdCard
  2. 校验器IdCardValidator

注解:@IdCard

java 复制代码
package com.example.core.validation.idcard;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * 身份证号码。字符串必须是格式正确的身份证号码。
 * <p>
 * {@code null} 或 空字符串,是有效的(能够通过校验)。
 * <p>
 * 支持的类型:字符串
 *
 * @author songguanxun
 * @since 1.0
 */
@Target({FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = IdCardValidator.class)
public @interface IdCard {

    /**
     * @return the error message template
     */
    String message() default "身份证号码,格式错误";

    /**
     * @return the groups the constraint belongs to
     */
    Class<?>[] groups() default {};

    /**
     * @return the payload associated to the constraint
     */
    Class<? extends Payload>[] payload() default {};

}

校验器:IdCardValidator

java 复制代码
package com.example.core.validation.idcard;

import cn.hutool.core.util.IdcardUtil;
import com.example.core.validation.ResetMessageUtil;
import org.springframework.util.ObjectUtils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 * 身份证号码,格式校验器
 */
public class IdCardValidator implements ConstraintValidator<IdCard, String> {

    @Override
    public void initialize(IdCard constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
    }


    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (ObjectUtils.isEmpty(value)) {
            return true;
        }

        if (value.contains(" ")) {
            ResetMessageUtil.reset(context, "身份证号码,格式错误:不能包含空格");
            return false;
        }

        return IdcardUtil.isValidCard(value);
    }

}

使用

@IdCard 放在需要校验格式的 身份证号码 字段上。

java 复制代码
package com.example.web.response.model.param;

import com.example.core.validation.idcard.IdCard;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

@Data
@Schema(name = "新增用户Param")
public class UserAddParam {
    
    // 其他字段

    @IdCard
    @Schema(description = "身份证号码", example = "110101202301024130")
    private String idCard;

}

补充代码

ResetMessageUtil:重置提示信息工具类

java 复制代码
package com.example.core.validation;

import javax.validation.ConstraintValidatorContext;

/**
 * 参数校验 - 重置提示信息工具类
 */
public class ResetMessageUtil {

    /**
     * 重置提示信息
     */
    public static void reset(ConstraintValidatorContext context, String message) {
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(message).addConstraintViolation();
    }

}

校验效果

校验工具类(Hutool),测试

对Hutool提供的身份证校验方法,进行测试。

java 复制代码
package com.example;

import cn.hutool.core.util.IdcardUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

/**
 * 身份证号码校验测试(使用Hutool)
 */
@Slf4j
public class IdCardHutoolTest {

    @Test
    void test() {
        test("110101202301024130");
        test("11010120230102857X");
        test("11010120230102857x");
        test("110101202301024130啊啊啊啊");
    }


    private void test(String idCard) {
        boolean validCard = IdcardUtil.isValidCard(idCard);
        log.info("是否为身份证号码格式:{} = {}", idCard, validCard);
    }

}

能够正确校验身份证格式。

接口测试

校验结果为 成功


校验结果为 失败

相关推荐
!chen32 分钟前
【Spring Boot】自定义starter
java·数据库·spring boot
hrrrrb1 小时前
【Spring Boot】Spring Boot 中常见的加密方案
java·spring boot·后端
程序定小飞2 小时前
基于springboot的在线商城系统设计与开发
java·数据库·vue.js·spring boot·后端
小妖怪的夏天3 小时前
react native android设置邮箱,进行邮件发送
android·spring boot·react native
考虑考虑5 小时前
Jpa中的枚举类型
spring boot·后端·spring
用户874034852515 小时前
家政小程序源码实战:快速部署+多端适配,打造高效家政服务生态
spring boot
小杨的全栈之路5 小时前
从 SSLHandshakeException 到成功调用:RestTemplate 攻克自签 HTTPS 全记录
spring boot
还是鼠鼠6 小时前
《黑马商城》Elasticsearch基础-详细介绍【简单易懂注释版】
java·spring boot·spring·elasticsearch·搜索引擎·spring cloud·全文检索
麦兜*7 小时前
Redis 7.2 新特性实战:Client-Side Caching(客户端缓存)如何大幅降低延迟?
数据库·spring boot·redis·spring·spring cloud·缓存·tomcat
熊小猿7 小时前
Spring Boot 的 7 大核心优势
java·spring boot·后端