目标
自定义一个用于校验邮政编码格式
的注解@ZipCode
,能够和现有的 Validation
兼容,使用方式和其他校验注解保持一致(使用 @Valid
注解接口参数)。
校验逻辑
有效格式
- 不能包含空格;
- 应为
6
位数字;
不校验非空
邮政编码,校验的是格式;不校验是否为空(null 或 空字符串)。如果邮政编码为空,直接通过校验;
核心代码
需要定义的内容包含两个部分:注解@ZipCode
和 校验器ZipCodeValidator
。
注解:@ZipCode
package com.example.core.validation.zipcode;
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;
/**
* 邮政编码。字符串必须是格式正确的邮政编码。正确格式为:6位数字。
* <p>
* {@code null} 或 空字符串,是有效的(能够通过校验)。
* <p>
* 支持的类型:字符串
*
* @author songguanxun
* @since 1.0
*/
@Target({FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = ZipCodeValidator.class)
public @interface ZipCode {
/**
* @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 {};
}
校验器:ZipCodeValidator
package com.example.core.validation.zipcode;
import com.example.core.constant.PatternConstant;
import org.springframework.util.ObjectUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Pattern;
/**
* 邮政编码格式校验器
*/
public class ZipCodeValidator implements ConstraintValidator<ZipCode, String> {
@Override
public void initialize(ZipCode constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (ObjectUtils.isEmpty(value)) {
return true;
}
if (value.contains(" ")) {
resetMessage(context, "邮政编码,格式错误:不能包含空格");
return false;
}
if (!isValid(value)) {
resetMessage(context, "邮政编码,格式错误");
return false;
}
return true;
}
// 格式为:6位数字
private static final Pattern PATTERN = Pattern.compile(PatternConstant.ZIP_CODE);
/**
* 是有效的格式
*/
private boolean isValid(CharSequence input) {
return PATTERN.matcher(input).matches();
}
/**
* 重置提示信息
*/
private void resetMessage(ConstraintValidatorContext context, String messageTemplate) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(messageTemplate).addConstraintViolation();
}
}
用到的常量
package com.example.core.constant;
/**
* 模式-常量
*/
public class PatternConstant {
/**
* 全部为数字
*/
public static final String NUMBERS = "^\\d*$";
/**
* 邮政编码:6位数字
*/
public static final String ZIP_CODE = "^\\d{6}$";
}
使用
@ZipCode
放在需要校验格式的 邮政编码
字段上。
新增用户Param
package com.example.web.response.model.param;
import com.example.core.constant.PatternConstant;
import com.example.core.validation.zipcode.ZipCode;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(name = "新增用户Param")
public class UserAddParam {
// 其他字段
@ZipCode
@Schema(description = "邮政编码", example = "201100", pattern = PatternConstant.ZIP_CODE)
private String zipCode;
}
校验效果
包含空格
不是6位数字
数字超过6位
包含非数字的字符