一、场景分析
我们使用 SpringMVC 在 Controller 层,对身份证号进行数据校验的话,经常采用以下方式:
@RestController
@RequiredArgsConstructor
@RequestMapping("member")
public class MemberController {
// 身份证号码正则表达式
String regex = "^(^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{2}[0-9Xx]$)$";
@PostMapping("/register")
public R<Void> register(@RequestBody @Valid Member member) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(member.getIdNo());
if (!matcher.matches()) {
return R.fail("不是有效的身份证号");
}
System.out.println(member);
return R.success();
}
}
我们当然可以采用上面的方式进行数据校验,但这种方式不是很优雅:
如果项目中还有别的对象需要进行身份证号校验,那么同样的代码就会在项目里散落一地。
Javax Validation 提供给我们另一种优雅的方式,进行逻辑重复的数据校验。
二、代码实现
1、创建自定义校验注解
首先创建一个自定义的校验注解,用于校验字符串是否为有效的身份证号格式
package com.study.annotations;
import com.study.config.IdCheckValidator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {IdCheckValidator.class}
)
public @interface IdCheck {
String message() default "不是有效的身份证号";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
2、创建校验器实现类
创建一个实现 ConstraintValidator 接口的类来实现自定义校验逻辑
package com.study.config;
import com.study.annotations.IdCheck;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class IdCheckValidator implements ConstraintValidator<IdCheck, String> {
// 身份证号码正则表达式
String regex = "^(^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{2}[0-9Xx]$)$";
private Pattern pattern;
@Override
public void initialize(IdCheck constraintAnnotation) {
// 初始化 pattern
this.pattern = Pattern.compile(regex);
}
@Override
public boolean isValid(String idNo, ConstraintValidatorContext constraintValidatorContext) {
Matcher matcher = pattern.matcher(idNo);
return matcher.matches();
}
}
3、在实体类中使用自定义注解
package com.study.member.entity;
import com.study.annotations.IdCheck;
import lombok.Data;
@Data
public class Member {
// 自定义注解
@IdCheck
private String idNo;
}
4、在控制器中进行数据绑定和校验
package com.study.member.controller;
import com.study.memberentity.Member;
import com.study.common.base.R;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
@RequiredArgsConstructor
@RequestMapping("member")
public class MemberController {
@PostMapping("/register")
public R<Void> register(@RequestBody @Valid Member member) {
System.out.println(member);
return R.success();
}
}
5、测试
输入一个格式错误的身份证号:
###
POST http://localhost:8080/member/register
Content-Type: application/json
{"idNo": "811111111111111111"}
输出:
{
"code": -1,
"msg": "不是有效的身份证号"
}
输入一个格式正确的身份证号(该身份证号是我随机生成的):
###
POST http://localhost:8080/member/register
Content-Type: application/json
{"idNo": "12010319881011691X"}
输出:
{
"code": 0,
"msg": "success"
}
三、总结
标签:自定义,study,身份证号,校验,member,import,Validation,public From: https://blog.csdn.net/matrixlzp/article/details/142550398ConstraintValidator 是 javax validation 规范提供给我们的一个实现数据校验的接口。
像 hibernate.validator 就有很多这个接口的实现,像我们常见的
- NotNullValidator
- MaxValidatorForMonetaryAmount
- MinValidatorForMonetaryAmount
等都是它的实现。以上代码,参考 NotNullValidator 的实现。