身份证号码,格式校验:@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);
    }

}

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

接口测试

校验结果为 成功


校验结果为 失败

相关推荐
皮皮林55119 小时前
拒绝写重复代码,试试这套开源的 SpringBoot 组件,效率翻倍~
java·spring boot
用户908324602733 天前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
用户8307196840824 天前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解4 天前
Spring Boot 视图层与模板引擎
spring boot·后端
Java水解4 天前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
洋洋技术笔记4 天前
Spring Boot Web MVC配置详解
spring boot·后端
初次攀爬者5 天前
Kafka 基础介绍
spring boot·kafka·消息队列
用户8307196840825 天前
spring ai alibaba + nacos +mcp 实现mcp服务负载均衡调用实战
spring boot·spring·mcp
Java水解5 天前
SpringBoot3全栈开发实战:从入门到精通的完整指南
spring boot·后端
初次攀爬者6 天前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq