从Alita项目中抽取出来的注解验证器, 用于对方法参数做验证,如常用的非空,手机号格式,邮箱格式,数字范围等. 通常用于HTTP项目(包括Restful)中客户端提交的参数的验证
大家可能会问,spring MVC支持验证注解,如常用的hibernate-validator,为什么要自己实现一套呢? 最近做一个APP的服务端接口,项目中有自己的业务返回码.spring MVC支持的注解验证器无法设置验证不通过的时候的返回码,各种不方便,所以思前想后还是自己实现了一套
- 基于Spring Boot 2.x
- 大部分注解在值为null的情况下都是通过: 目前的验证器除了@Required 在值为null的情况下不通过外,其他验证器在值为null的时候都是通过的,所以如果某个参数是必传的话,需要配合@Required 使用
- 验证器可以叠加使用: 例如一个参数是url,并且是必传,可以使用 @Required 和 @HttpUrl
- **关于@NotEmpty验证器: ** 该验证器是在值非null的情况下才工作,验证是否为空.如:String trim后="",数组size=0,集合size=0),Map size=0
- 验证JAVA方法的参数是否符合要求:验证器是基于注解的,可用于验证任何的JAVA方法的参数
- 自定义错误码:使用注解的时候可以自定义验证失败时的错误码
- 自定义错误消息: 使用注解的时候可以自定义验证失败的消息,该消息为一个字符串,如果做国际化,可以在错误消息中放入国际化资源标识,在responseMsgGenerator 处理该资源标识
- 返回类型自定:通过实现错误响应接口,可以实现验证失败被调用的方法返回的内容自定,而不是抛出异常. 例如WEB项目中可以返回一个项目定义的Response格式的对象.
- 各种验证方式:目前提供少量的验证器,如必传,非空,密码(复杂度,长度等),手机号格式等.后面会慢慢增加更多的验证器,当然大家也可以提PR
- 方法参数使用验证器(0.2新增): 现在可以在方法参数上使用验证器,并且如果该参数是个Java Bean, 并且属性中使用了验证器也会进行验证
- 自定义验证器扩展(0.2新增): 通过在配制项"alita.validator.custom.packages" 配制自定义的验证器实现的包路径,可扫描自定义的验证器.多个包路径逗号分隔
- @Trimstring 注解(0.3新增): 用于去除字符串/集合中的字符串中的前后空格(不是验证器),支持处理集合中的字符串
- 日期范围验证(0.3新增): 可以验证日期参数的开始结束返回,或者指定日期之后, 指定日期之前
- @GroupNotEmpty注解(0.3新增): 用于验证一组指定的属性,其中至少几个非空, 配合@GroupItem(用于标注组中的元素), 如果一个类中有多组,需要配合@GroupNotEmptys 使用,具体使用方式参考
- @MultiFieldRequired(0.4新增): 可以在方法参数上指定参数Bean中的属性为必传
- **@HttpUrl(0.4新增):**验证字符串格式是否是url, 如果url中包含非英文部分,需要做url encode
- **@CheckDateFormat(0.4新增):**检查日期字符串是否是指定格式,默认格式为 yyyy-MM-dd HH:mm:ss
- **@IdCard(0.4新增):**校验身份证号
- @StringLength(0.5新增): 用于验证trim 后的string的最大、最小长度
- **支持Bean中的Bean 类型属性中的验证器(0.6新增): **如果参数是个java bean(bean1),并且这个bean中的属性是另一个bean(bean2),可以在bean2的属性中使用验证器,支持无限级. 同时支持集合中的泛型中的验证器(数组 ,Collection,Map),需要使用@ParamBean注解
- 手机号验证器增加199开头支持
- 修复当使用了 @ParamBean 注解,被注解的属性的值为null时抛异常的bug
- 数字相关验证器修改为强制设置错误消息
- top.klw8.alita.validator.ValidatorException 中新增一个验证不通过的方法的返回参数类型,便于在统一响应生成器中处理返回类型
- Bean中的Bean 类型属性中的验证器增加层级限制,最多10层,超过10层将忽略并日志输出警告
- 新增支持Bean中的Bean 类型属性中的验证器,无限级.需要使用@ParamBean注解
- @ParamBean注解同时支持集合中的泛型中的验证器(数组 ,Collection,Map)
- 增加 @StringLength 验证器, 用于验证trim 后的string的最大、最小长度
- 增加 @MultiFieldRequired 验证器,可以在方法参数上指定参数Bean中的属性为必传
- 增加 @HttpUrl 验证器, 验证字符串格式是否是url, 如果url中包含非英文部分,需要做url encode
- 增加 @CheckDateFormat 验证器,用于检查日期字符串是否是指定格式,默认格式为 yyyy-MM-dd HH:mm:ss
- 增加 @IdCard 验证器,用于校验身份证号
- 增加 @Trimstring 注解,用于去除字符串/集合中的字符串中的前后空格(不是验证器),支持处理集合中的字符串
- APO里增加对处理类注解的支持,现在可以定义并处理类级注解,如新增的 @GroupNotEmpty
- 新增验处理器是否实现了验证器接口的校验,扫描验证器时过滤指定包中的非验证器类
- 新增日期范围验证器@DateRange,可以验证日期参数的开始结束返回,或者指定日期之后, 指定日期之前
- 根据自用发现的需求增加功能
maven引入:
<dependency>
<groupId>top.klw8.alita</groupId>
<artifactId>alita-validator</artifactId>
<version>1.0.0</version>
</dependency>
开发一个responseMsgGenerator:
responseMsgGenerator 作为验证错误的响应生成器,用于生成当验证不通过时被调用方法的返回的值,例如WBE项目用于验证客户端提交的参数,可以返回一个统一的响应结构.
实现top.klw8.alita.validator.IResponseMsgGenerator接口,根据传入的自定义错误码和自定义错误消息生成对应的返回值
开启验证器:
在配制类(标注了@Configuration的类)或者spring boot 启动器(标注了@SpringBootApplication的类)的类中加上类注解:
@EnableValidator(responseMsgGenerator = ValidatorResponseGenerator.class)
其中 responseMsgGenerator 为上面开发的 responseMsgGenerator
使用验证器:
在需要验证的方法上加上方法注解 top.klw8.alita.validator.UseValidator:
@UseValidator
public CustomResult xxx(Demo demo)
在Demo类的属性上加上具体验证器:
@Required(validatFailMessage = "姓名不能为空", responseStatusCode="5008")
private String fullName;
验证器注解可以在使用的项目中单独开发,通过配置项"alita.validator.custom.packages" 指定验证器实现所在包就行,多个包路径用逗号分隔,验证器注解在哪个包无所谓.当然也欢迎各种PR~(如果要PR,则验证器注解必须放在 "top.klw8.alita.validator.annotations"包下,实现必须放在"top.klw8.alita.validator.annotations.impl"包下)
定义验证器注解
验证器注解可以放在任意包中
例如开发一个非空验证器(当值不为null的时候判断是否空,为null不处理):
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
@Inherited
@ThisIsValidator
public @interface NotEmpty {
@AliasFor("validatFailMessage")
String value() default "";
/**
* @Title: responseStatusCode
* @Description: 验证失败(不通过)的code
* @return
*/
String responseStatusCode() default "500";
/**
* @Title: validatFailMessage
* @Description: 验证失败(不通过)的文字消息,可为空,默认使用ResponseStatusCodeEnum对应的消息
* @return
*/
@AliasFor("value")
String validatFailMessage() default "";
// 更多参数...
}
上面例子中的value,responseStatusCode和 validatFailMessage 为每个验证器必须有的参数,当然还可以增加更多的参数,在验证器实现解析
开发验证器实现类
验证器实现可以放在任意包中,然后在配制中指定包路径
需要实现 top.klw8.alita.validator.IAnnotationsValidator 接口
@ValidatorImpl(validator = NotEmpty.class) //标注该实现是哪个验证器的实现,如果是多个验证器共有的实现则可以validator = {NotEmpty.class, Xxx.class}
public class NotEmptyImpl implements IAnnotationsValidator {
@Override
public void doValidator(Object object, Annotation annotation) throws Exception {
NotEmpty notEmpty = (NotEmpty) annotation;
String statusCode = notEmpty.responseStatusCode();
String message = notEmpty.validatFailMessage();
if (object != null) {
if (object.getClass().isArray()) {
ValidatorUtil.notEmpty((Object[]) object, statusCode, message);
} else if (object instanceof Collection) {
ValidatorUtil.notEmpty((Collection<?>) object, statusCode, message);
} else if (object instanceof Map) {
ValidatorUtil.notEmpty((Map<?, ?>) object, statusCode, message);
} else if (object instanceof String) {
ValidatorUtil.hasText((String) object, statusCode, message);
}
}
}
}
验证器实现不返回任值,验证不通过时抛出 top.klw8.alita.validator.ValidatorException 异常即可