1. 自定义校验器实现
package javax.validation.constraints;
下有许多预设的校验器注解比如:
- [x]
AssertFalse
- [x]
AssertTrue
- [x]
DecimalMax
- [x]
DecimalMin
- [x]
Max
- [x]
Min
- [x]
NotNull
- [x]
Null
但是有时候会有校验手机号或邮箱的麻烦事,或者校验全角半角字符长度的校验,这时自定义校验器就派上用场了
2.校验器示例(一个蛋疼的全角半角字符校验)- 来自ios客户端某评论内容需求
2.1 定义注解名,注解类型,校验实现类等,内容如下:
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 描述:校验unicode长度
*
* @author biguodong
* Create time 2018-07-31 上午10:33
**/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UnicodeMaxImpl.class)
public @interface UnicodeMax {
int minLength();
int maxLength();
String message() default "数据长度不合法!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
如上声明的是一个全角半角字符长度判断校验器注解,相关字段参数在使用的时候酌情添加修改即可:
2.2 自定义校验器需要实现的接口类ConstraintValidator<A extends Annotation, T>
需要重写两个方法:
- [x]
void initialize(A constraintAnnotation);
- [x]
boolean isValid(T value, ConstraintValidatorContext context);
接口定义如下:
package javax.validation;
import javax.validation.constraintvalidation.SupportedValidationTarget;
import java.lang.annotation.Annotation;
/**
* 定义校验注解 {@code A}以及需要校验的数据类型 {@code T}
*/
public interface ConstraintValidator<A extends Annotation, T> {
/**
* 实例化校验器
* 使用校验器之前,此方法一定会被调用
*/
void initialize(A constraintAnnotation);
/**
* 实现校验逻辑
* {@code value}不能被改变
* 如果校验不通过,返回false
*/
boolean isValid(T value, ConstraintValidatorContext context);
}
2.3 校验器实现类逻辑
import org.springframework.util.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* 描述:校验unicode长度实现
* 计算半角和全角长度
* @author biguodong
* Create time 2018-07-31 上午10:35
**/
//注解的实现类需要实现ConstraintValidator接口并指定注解类和被校验的数据类型(String)
public class UnicodeMaxImpl implements ConstraintValidator<UnicodeMax, String> {
//定义长度下限
private int minLength;
//定义长度上限
private int maxLength;
/**
*重写实例化方法
*/
@Override
public void initialize(UnicodeMax constraintAnnotation) {
this.maxLength = constraintAnnotation.maxLength();
this.minLength = constraintAnnotation.minLength();
}
/**
*重写校验方法
*/
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
//判空逻辑因人而异
if (StringUtils.isEmpty(value)) {
return true;
}
int length = getCharLength(value);
if (length < minLength || length > maxLength) {
return false;
}
return true;
//return Pattern.matches("^(([\\u4e00-\\u9fa5]|[\\w\\s]|[\\pP|\\pS])*)?$", value);
}
/*
*获取字符串的长度(含半角字符和全角字符)
*/
public static int getCharLength(String value){
int halfCharCount = 0;
int allCharCount = 0;
char[] chars = value.toCharArray();
for (int i = 0; i < chars.length; i++) {
String temp = String.valueOf(chars[i]);
/**
* 判断是全角字符
*/
if (temp.matches("[^\\x00-\\xff]")) {
allCharCount ++;
}
/**
* 判断是半角字符
*/
else {
halfCharCount ++;
}
}
return halfCharCount + 2 * allCharCount;
}
}
2.5 小试牛刀之好鞍上马
我在一个内部类上添加了此注解来约束content的数据长度
/**
* 移动端传递数据接收对象
* @author biguodong
*/
@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class CommentReceiver{
/**
* 视频id
*/
private Long videoId;
/**
* 父级id-回复
*/
private Long parentId;
/**
* 用户id
*/
private Long userId;
/**
* 评论内容
*/
@UnicodeMax(maxLength = 100, minLength = 0, message = "内容过长!")
private String content;
}
2.6 小试牛刀之策马奔腾
配上好兄弟
@Validated
让我们策马奔腾看下效果吧~
import org.springframework.validation.annotation.Validated;
/**
* 添加评论
* @param commentReceiver
* @return
* @throws BizException
*/
@PostMapping
public Object commentAdd(@RequestParam long loginUserId, @RequestBody @Validated CommentVo.CommentReceiver commentReceiver) throws BizException{
commentReceiver.setUserId(loginUserId);
return commentService.save(commentReceiver);
}
提示信息不能乱来奥~