Spring Boot基于正则regex实现document-type枚举的PAN卡格式校验
使用场景
项目中存在名为document-type的枚举类型,取值包含passport、PAN CARD。需要在Spring Boot框架下编写基于正则表达式的校验逻辑,对PAN CARD取值的长度、字符规则做合法性校验。
实现方案
首先明确印度PAN卡的官方编码规则,作为正则编写的依据:
- 固定总长度10位
- 前5位为大写英文字母
- 第6到第9位为阿拉伯数字
- 第10位为大写英文字母
- 不允许包含空格、特殊符号
匹配该规则的正则为:^[A-Z]{5}[0-9]{4}[A-Z]$
如果需要兼容用户输入小写字母的场景,可以在匹配前将输入字符串转为全大写,或者直接使用不区分大小写的正则:^(?i)[A-Z]{5}[0-9]{4}[A-Z]$
根据项目复用需求,可以选择以下两种实现方式:
方式1:单业务点快速校验
如果仅需要在单个业务逻辑中做校验,直接使用JDK自带的正则工具类实现即可,注意预编译正则提升性能:
import java.util.regex.Pattern; // 类加载时预编译正则,避免每次调用方法重复编译损耗性能 private static final Pattern PAN_CARD_PATTERN = Pattern.compile("^[A-Z]{5}[0-9]{4}[A-Z]$"); private boolean checkPanCardValid(String cardNo) { // 先做空判断,避免空指针 if (cardNo == null || cardNo.isBlank()) { return false; } // 去掉首尾多余空格后匹配 return PAN_CARD_PATTERN.matcher(cardNo.trim()).matches(); }
业务逻辑中先判断当前document-type枚举值,如果是PAN CARD,调用上述方法校验即可,校验不通过直接返回参数错误提示。
方式2:自定义校验注解(全局复用)
如果项目中有多个接口需要做相同的证件校验,直接基于Spring Boot默认集成的Jakarta Validation组件实现自定义联动校验,一次编写全局可用:
- 先定义类级别校验注解,实现「证件类型不同走不同校验规则」的联动逻辑
import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.*; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = DocumentValidator.class) @Documented public @interface ValidDocument { String message() default "证件信息校验不通过"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
- 编写校验逻辑实现类,在分支中单独处理PAN CARD的正则校验
import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import java.util.regex.Pattern; public class DocumentValidator implements ConstraintValidator<ValidDocument, DocumentInfoDTO> { // 预编译PAN卡校验正则 private static final Pattern PAN_CARD_PATTERN = Pattern.compile("^[A-Z]{5}[0-9]{4}[A-Z]$"); // 护照号最小长度示例,可根据实际业务规则调整 private static final int PASSPORT_MIN_LENGTH = 5; @Override public boolean isValid(DocumentInfoDTO dto, ConstraintValidatorContext context) { // 证件类型为空直接判定不合法 if (dto.getDocumentType() == null) { return false; } String cardNo = dto.getDocumentNo() == null ? "" : dto.getDocumentNo().trim(); switch (dto.getDocumentType()) { case PAN_CARD: // 自定义字段级错误提示 context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate("PAN CARD格式错误,需为10位,规则为前5位大写字母、中间4位数字、最后1位大写字母") .addPropertyNode("documentNo") .addConstraintViolation(); return PAN_CARD_PATTERN.matcher(cardNo).matches(); case PASSPORT: context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate("护照号码格式错误") .addPropertyNode("documentNo") .addConstraintViolation(); return cardNo.length() >= PASSPORT_MIN_LENGTH; default: return false; } } }
- 在接收参数的DTO类上添加
@ValidDocument注解,接口方法参数上添加@Valid注解,请求进入时Spring会自动触发校验,校验不通过会抛出参数校验异常,可结合全局异常处理器统一返回错误提示。
注意事项
- 正则必须提前预编译,不要在每次请求处理时动态编译正则,会额外消耗性能
- 校验前要对输入字符串做空判断、首尾去空格处理,避免空指针、用户误输入空格导致校验失败
- 如果业务允许输入小写PAN卡号,在匹配前调用
cardNo.toUpperCase()转为全大写再做匹配即可,不用修改正则
内容的提问来源于stack exchange,提问作者NAR
相关产品推荐
相关产品推荐

