目标
自定义一个用于校验(作为查询参数的)手机号码格式
的注解@PhoneQuery
,能够和现有的 Validation
兼容,使用方式和其他校验注解
保持一致。
校验逻辑
- 可以为
null
或空字符串
; - 不能包含
空格
; - 必须为
数字序列
(全部为数字); - 长度应小于等于
11
位;
核心代码
需要定义的内容包含两个部分:注解@PhoneQuery
和 校验器PhoneQueryValidator
。
注解:@PhoneQuery
package com.example.core.validation.phone.query;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;/*** 字符串必须是格式正确的手机号码,或手机号码的一部分。正确格式为:小于等于11位的数字。* <p>* {@code null} 或 空字符串,是有效的(能够通过校验)。* <p>* 支持的类型:字符串** @author songguanxun* @since 1.0*/
@Target({FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = PhoneQueryValidator.class)
public @interface PhoneQuery {/*** @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 {};/*** 手机号码的详细描述。* <p>* 用于用户提示中,当页面中存在多个手机号码时,帮助用户更好的区分是哪个手机号码填错了。*/String description() default "手机号码";
}
校验器:PhoneQueryValidator
package com.example.core.validation.phone.query;import org.springframework.util.ObjectUtils;import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Pattern;/*** 手机号码(查询参数)格式校验器*/
public class PhoneQueryValidator implements ConstraintValidator<PhoneQuery, String> {// 手机号码的详细描述。private String description;@Overridepublic void initialize(PhoneQuery constraintAnnotation) {ConstraintValidator.super.initialize(constraintAnnotation);description = constraintAnnotation.description();}@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {if (ObjectUtils.isEmpty(value)) {return true;}if (value.contains(" ")) {String message = String.format("%s,格式错误:不能包含空格", description);resetMessage(context, message);return false;}if (!isNumericSequence(value)) {String message = String.format("%s,格式错误:必须为数字序列", description);resetMessage(context, message);return false;}if (value.length() > 11) {String message = String.format("%s,格式错误:长度应小于等于11位", description);resetMessage(context, message);return false;}return true;}// 格式:数字序列(全部为数字)private static final Pattern PATTERN_NUMERIC_SEQUENCE = Pattern.compile("^\\d*$");/*** 是数字序列*/private boolean isNumericSequence(CharSequence input) {return PATTERN_NUMERIC_SEQUENCE.matcher(input).matches();}/*** 重置提示信息*/private void resetMessage(ConstraintValidatorContext context, String messageTemplate) {context.disableDefaultConstraintViolation();context.buildConstraintViolationWithTemplate(messageTemplate).addConstraintViolation();}}
使用
@PhoneQuery 放在需要校验格式的 用作查询条件的手机号码
字段上。
package com.example.web.exception.query;import com.example.core.validation.phone.query.PhoneQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springdoc.api.annotations.ParameterObject;@Data
@ParameterObject
@Schema(name = "用户Query")
public class UserQuery {@Schema(description = "姓名", example = "张三")private String name;@PhoneQuery@Schema(description = "手机号码", example = "18612345678", pattern = "^\\d*$", maxLength = 11)private String phone;}