{"id":18600597,"url":"https://github.com/houbb/validator","last_synced_at":"2025-04-10T18:31:27.266Z","repository":{"id":239790833,"uuid":"615206462","full_name":"houbb/validator","owner":"houbb","description":"🚥Fluent-validation framework for java extend from hibernate-validator.（java 对象属性流式验证框架，下一代校验框架。兼容实现 jakarta bean validation、jsr 303、hibernate-validator）","archived":false,"fork":false,"pushed_at":"2023-03-22T04:49:32.000Z","size":270,"stargazers_count":48,"open_issues_count":4,"forks_count":10,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-25T02:51:35.003Z","etag":null,"topics":["hibernate-validator","jakartaee","jsr303-bean-validation","parameter","valid","validator"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/houbb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-17T07:20:45.000Z","updated_at":"2025-02-08T03:38:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"a4c5a1f4-3120-477c-aff6-ae70826922a7","html_url":"https://github.com/houbb/validator","commit_stats":null,"previous_names":["houbb/validator"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houbb%2Fvalidator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houbb%2Fvalidator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houbb%2Fvalidator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/houbb%2Fvalidator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/houbb","download_url":"https://codeload.github.com/houbb/validator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248271722,"owners_count":21075800,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hibernate-validator","jakartaee","jsr303-bean-validation","parameter","valid","validator"],"created_at":"2024-11-07T02:04:36.439Z","updated_at":"2025-04-10T18:31:26.392Z","avatar_url":"https://github.com/houbb.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 项目介绍\n\njava 开发中，参数校验是非常常见的需求。但是 hibernate-validator 在使用过程中，依然会存在一些问题。\n\n[validator](https://github.com/houbb/validator) 在 hibernate-validator 等校验工具之上，做了一些改进，使其使用更加便捷优雅，进一步提升工作效率。\n\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.houbb/validator/badge.svg)](http://mvnrepository.com/artifact/com.github.houbb/validator)\n[![](https://img.shields.io/badge/license-Apache2-FF0080.svg)](https://github.com/houbb/validator/blob/master/LICENSE.txt)\n[![Open Source Love](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://github.com/houbb/validator)\n[![Build Status](https://www.travis-ci.org/houbb/validator.svg?branch=master)](https://www.travis-ci.org/houbb/validator?branch=master)\n[![Coverage Status](https://coveralls.io/repos/github/houbb/validator/badge.svg?branch=master)](https://coveralls.io/github/houbb/validator?branch=master)\n\n## 变更日志\n\n\u003e [变更日志](https://github.com/houbb/validator/blob/master/CHANGELOG.md)\n\n## 特性\n\n- 兼容实现 jakarta bean validation（jsr-303）内置注解 \n\n- 兼容实现 hibernate-validation\n\n- 支持 i18n\n\n- 支持用户自定义策略\n\n- 支持用户自定义注解\n\n- 支持针对属性的校验\n\n- 支持过程式编程与注解式编程\n\n- 支持指定校验生效的条件\n\n# 创作目的\n\n## hibernate-validator 无法满足的场景\n\n如今 java 最流行的 hibernate-validator 框架，但是有些场景是无法满足的。\n\n比如：\n\n1. 验证新密码和确认密码是否相同。(同一对象下的不同属性之间关系)\n\n2. 当一个属性值满足某个条件时，才进行其他值的参数校验。\n\n3. 多个属性值，至少有一个不能为 null\n\n其实，在**对于多个字段的关联关系处理时，hibernate-validator 就会比较弱**。\n\n本项目结合原有的优点，进行这一点的功能强化。\n\n## validation-api 过于复杂\n\nvalidation-api 提供了丰富的特性定义，也同时带来了一个问题。\n\n实现起来，特别复杂。\n\n然而我们实际使用中，常常不需要这么复杂的实现。\n\nvalidator-api 提供了一套简化很多的 api，便于用户自行实现。\n\n## 自定义缺乏灵活性\n\nhibernate-validator 在使用中，自定义约束实现是基于注解的，针对单个属性校验不够灵活。\n\n本项目中，**将属性校验约束和注解约束区分开，便于复用和拓展**。\n\n## 过程式编程 vs 注解式编程\n\nhibernate-validator 核心支持的是注解式编程，基于 bean 的校验。\n\n一个问题是针对属性校验不灵活，有时候针对 bean 的校验，还是要自己写判断。\n\n本项目支持 fluent-api 进行过程式编程，同时支持注解式编程。\n\n尽可能兼顾灵活性与便利性。\n\n# 快速开始\n\n## 准备工作\n\nJDK1.7+\n\nMaven 3.X+\n\n## maven 引入\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.houbb\u003c/groupId\u003e\n    \u003cartifactId\u003evalidator-core\u003c/artifactId\u003e\n    \u003cversion\u003e0.7.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## 快速入门\n\n### 定义对象\n\n第一步，我们定义一个常见的 java bean 对象，可以指定内置的注解。\n\n支持 jsr-303 注解和 hibernate-validator 的注解。\n\n```java\npublic class User {\n\n    /**\n     * 名称\n     */\n    @HasNotNull({\"nickName\"})\n    private String name;\n\n    /**\n     * 昵称\n     */\n    private String nickName;\n\n    /**\n     * 原始密码\n     */\n    @AllEquals(\"password2\")\n    private String password;\n\n    /**\n     * 新密码\n     */\n    private String password2;\n\n    /**\n     * 性别\n     */\n    @Ranges({\"boy\", \"girl\"})\n    private String sex;\n\n    /**\n     * 失败类型枚举\n     */\n    @EnumRanges(FailTypeEnum.class)\n    private String failType;\n    \n    //getter \u0026 setter\n\n}\n```\n\n### ValidHelper 工具方法\n\nValidHelper 作为统一封装的工具类，提供了 java bean 校验常见的方法。\n\n方法列表：\n\n| 序号  | 方法                                                              | 返回值     | 说明                                                          |\n|:----|:----------------------------------------------------------------|:--------|:------------------------------------------------------------|\n| 1   | failOver(Object object)                                         | IResult | 全部验证后返回                                                     |\n| 2   | failFast(Object object)                                         | IResult | 快速验证后返回                                                     |\n| 3   | failOverThrow(Object object)                                    | void    | 全部验证后返回-未通过抛出异常                                             |\n| 4   | failFastThrow(Object object)                                    | void    | 快速验证后返回-未通过抛出异常                                             |\n| 5   | failOver(Object object, IConstraint Constraint)                 | IResult | 全部验证后返回，属性校验                                            |\n| 6   | failFast(Object object, IConstraint Constraint)                 | IResult | 快速验证后返回，属性校验                                            |\n| 7   | failOverThrow(Object object, IConstraint Constraint)            | void    | 全部验证后返回-未通过抛出异常，属性校验                                      |\n| 8   | failFastThrow(Object object, IConstraint Constraint)            | void    | 快速验证后返回-未通过抛出异常，属性校验                                    |\n| 9   | failOver(Object object, IConstraint Constraint, String message) | IResult | 全部验证后返回，属性校验，message 为报错信息                              |\n| 10  | failFast(Object object, IConstraint Constraint, String message)                 | IResult | 快速验证后返回，属性校验，message 为报错信息                              |\n| 11  | failOverThrow(Object object, IConstraint Constraint, String message)            | void    | 全部验证后返回-未通过抛出异常，属性校验，message 为报错信息                      |\n| 12  | failFastThrow(Object object, IConstraint Constraint, String message)            | void    | 快速验证后返回-未通过抛出异常，属性校验，message 为报错信息                      |\n\n使用起来很简单，我们以 failFast 为例：\n\n```java\n// 对象定义\nUser user = new User();\nuser.sex(\"what\").password(\"old\").password2(\"new\");\n\n// 调用方法\nIResult result = ValidHelper.failFast(user);\n```\n\n结果：\n\n```\nDefaultResult{pass=false, notPassList=[DefaultConstraintResult{pass=false, message='name: 值 \u003cnull\u003e 不是预期值', value=null, constraint='HasNotNullConstraint', expectValue='', fieldName='name'}], allList=null}\n```\n\n- IResult 方法说明\n\n返回值实现默认为 DefaultResult，接口 IResult 属性如下：\n\n```java\npublic interface IResult {\n\n    /**\n     * 是否全部通过验证\n     * @return 是否\n     * @since 0.1.0\n     */\n    boolean pass();\n\n    /**\n     * 未通过的列表信息\n     * @return 验证结果\n     * @since 0.1.0\n     */\n    List\u003cIConstraintResult\u003e notPassList();\n\n    /**\n     * 所有的验证结果列表\n     * @return 所有的验证结果\n     * @since 0.1.0\n     */\n    List\u003cIConstraintResult\u003e allList();\n\n    /**\n     * 输出信息到控台\n     * （1）主要是为了方便调整\n     * （2）该功能其实可以做增强，比如输出到文件/数据库等等。\n     * @return this\n     * @since 0.0.6\n     */\n    IResult print();\n\n    /**\n     * 对于未通过的信息，\n     * （1）未通过的界定。\n     *  {@link IConstraintResult#pass()} 为 false\n     *\n     * （2）内容信息\n     * 抛出运行时异常 {@link com.github.houbb.validator.api.exception.ValidRuntimeException}，异常信息为 {@link IConstraintResult#message()} 消息\n     * （3）内容限定\n     *  为了避免异常内容过多，只抛出第一条即可。\n     *  （4）改方法的增强空间\n     *  4.1 可以指定什么情况下抛出异常\n     *  4.2 抛出异常的信息和类别\n     *\n     * @return this\n     * @since 0.0.6\n     */\n    IResult throwsEx();\n\n}\n```\n\n# 注解说明\n\njava bean 的校验，基于注解是比较方便的。和 hibernate-validator 使用类似，这里介绍下常见的注解。\n\n## 内置约束注解\n\n内置注解如下：\n\n| 序号  | 注解            | value()                 | 说明                       |\n|:----|:--------------|:------------------------|:-------------------------|\n| 1   | `@AllEquals`  | `String[]`              | 当前字段及其指定的字段 全部相等         |\n| 2   | `@EnumRanges` | `Class\u003c? extends Enum\u003e` | 当前字段必须在枚举值指定的范围内         |\n| 3   | `@HasNotNull` | `String[]`              | 当前字段及其指定的字段 至少有一个不为 null |\n| 4   | `@Ranges`     | `String[]`              | 当前字段必须在指定的范围内            |\n| 4   | `@Ranges`     | `String[]`              | 当前字段必须在指定的范围内            |\n| 5   | `@ChinaPhone` |                         | 中国手机号校验                  |\n| 6   | `@ChinaIdNo`  |                         | 中国身份证校验                  |\n\n## JSR-303 / jakarta bean validation 约束注解支持\n\n\u003e [jakarta-bean-validation-spec-3.0](https://jakarta.ee/specifications/bean-validation/3.0/jakarta-bean-validation-spec-3.0.html#builtinconstraints-futureorpresent)\n\n| 序号  | 注解                 | 说明                 |\n|:----|:-------------------|:-------------------|\n| 1   | `@AssertTrue`      | 为 true 约束条件        |\n| 2   | `@AssertFalse`     | 为 false 约束条件       |\n| 3   | `@Null`            | 为 null 约束条件        |\n| 4   | `@NotNull`         | 不为 null 约束条件       |\n| 5   | `@Past`            | 是否在当前时间之前约束条件      |\n| 6   | `@PastOrPresent`   | 是否在当前时间之前约束条件，包含当前 |\n| 7   | `@Future`          | 是否在当前时间之后约束条件      |\n| 8   | `@FutureOrPresent` | 是否在当前时间之后约束条件，包含当前 |\n| 9   | `@Pattern`         | 正则表达式约束条件          |\n| 10  | `@Size`            | 在指定范围内的约束条件        |\n| 11  | `@Digits`          | 数字位数的约束条件          |\n| 12  | `@DecimalMax`      | 最大数字的约束条件          |\n| 13  | `@DecimalMin`      | 最小数字的约束条件          |\n| 14  | `@Min`             | 最小的约束条件            |\n| 15  | `@Max`             | 最大的约束条件            |\n| 16  | `@NotBlank`        | 不能为空格的约束条件         |\n| 17  | `@NotEmpty`        | 不能为空的约束条件          |\n| 18  | `@Email`           | Email 约束条件         |\n| 19  | `@Negative`        | 指定值必须为负数约束条件       |\n| 20  | `@NegativeOrZero`  | 指定值必须为负数约束条件，包含0       |\n| 21  | `@Positive`        | 指定值必须为正数约束条件       |\n| 22  | `@PositiveOrZero`  | 指定值必须为正数约束条件，包含0   |\n\n## hibernate-validator 约束注解支持\n\n\u003e [hibernate-validator 内置注解](https://docs.jboss.org/hibernate/validator/8.0/reference/en-US/html_single/#section-builtin-constraints)\n\n实现了常见的几个，后续将陆续完善：\n\n| 序号  | 注解                  | 说明                 |\n|:----|:--------------------|:-------------------|\n| 1   | `@NotBlank`         | 不能为空格的约束条件         |\n| 2   | `@NotEmpty`         | 不能为空的约束条件          |\n| 3   | `@Length`           | 长度的约束条件            |\n| 4   | `@URL`              | URL 约束条件           |\n| 5   | `@Email`            | Email 约束条件         |\n| 6   | `@UniqueElements`   | 元素唯一约束条件           |\n| 7   | `@Range`            | 指定范围元素约束条件         |\n\n# 条件注解\n\n## 说明\n\n有时候我们需要根据不同的参数，进行不同的限制条件。\n\n比如新建时用户 id 不需要传入，但是修改时 id 必填。\n\n如果是传统的 hibernate-validator 处理就会比较麻烦，此处引入条件注解。\n\n## 内置注解 \n\n| 序号  | 注解                      | 说明        |\n|:----|:------------------------|:----------|\n| 1   | `@EqualsCondition`      | 等于指定值的条件  |\n| 2   | `@NotEqualsCondition`   | 不等于指定值的条件 |\n| 3   | `@AlwaysTrueCondition`  | 永远生效的条件   |\n| 4   | `@AlwaysFalseCondition` | 永远不生效的条件  |\n\n## 使用\n\n使用起来也不难，下面的效果如下：\n\n1. operType == 'create' 时，name 的校验才会生效。\n2. operType != 'create' 时，id 的校验才会生效。\n\n其他使用方式保持不变。\n\n```java\npublic class ConditionUser {\n\n    /**\n     * 操作类型\n     */\n    @Ranges({\"create\", \"edit\"})\n    private String operType;\n\n    /**\n     * 新建时，name 必填\n     */\n    @EqualsCondition(value = \"create\", fieldName = \"operType\")\n    @Size(min = 3)\n    @NotNull\n    private String name;\n\n    /**\n     * 不是新建时, id 字段必填\n     */\n    @NotEqualsCondition(value = \"create\", fieldName = \"operType\")\n    @Size(min = 16)\n    private String id;\n    \n    //getter \u0026 setter\n}\n```\n\n# 过程式接口\n\n## 说明\n\n日常开发中，我们都很喜欢使用注解对 java bean 进行校验。\n\n但是这回导致我们定义的单个属性校验无法复用。\n\n所以项目中的单个属性校验和注解是一一对应的，为了便于复用。\n\n## ValidHelper 方法\n\nValidHelper 作为统一封装的工具类，提供单个方法校验常见的方法。\n\n和 java bean 类似，方法列表：\n\n| 序号  | 方法                                 | 返回值     | 说明                                     |\n|:----|:-----------------------------------|:--------|:---------------------------------------|\n| 1   | failOver(Object object, IConstraint constraint)    | IResult | 全部验证后返回                                |\n| 2   | failFast(Object object, IConstraint constraint)      | IResult | 快速验证后返回                                |\n| 3   | failOverThrow(Object object, IConstraint constraint) | void    | 全部验证后返回-未通过抛出 ValidRuntimeException 异常 |\n| 4   | failFastThrow(Object object, IConstraint constraint) | void    | 快速验证后返回-未通过抛出 ValidRuntimeException 异常 |\n\n## 使用例子\n\n用法和 bean 的类似，只是入参多了第二个约束条件。\n\n```java\nIResult result = ValidHelper.failFast(\"\", Constraints.notEmpty());\n```\n\n## IConstraint 对应关系\n\n注解和常见的接口方法一一对应，所有的约束方法在 `Constraints` 工具类中。 \n\n### JSR-303 / jakarta bean validation 约束注解支持\n\n| 序号  | 注解                 | 说明                 | 对应方法              |\n|:----|:-------------------|:-------------------|:------------------|\n| 1   | `@AssertTrue`      | 为 true 约束条件        | assertTrue()      |\n| 2   | `@AssertFalse`     | 为 false 约束条件       | assertFalse()     |\n| 3   | `@Null`            | 为 null 约束条件        | nulls()           |\n| 4   | `@NotNull`         | 不为 null 约束条件       | notNulls()        |\n| 5   | `@Past`            | 是否在当前时间之前约束条件      | past()            |\n| 6   | `@PastOrPresent`   | 是否在当前时间之前约束条件，包含当前 | pastOrPresent()   |\n| 7   | `@Future`          | 是否在当前时间之后约束条件      | future()          |\n| 8   | `@FutureOrPresent` | 是否在当前时间之后约束条件，包含当前 | futureOrPresent() |\n| 9   | `@Pattern`         | 正则表达式约束条件          | pattern()         |\n| 10  | `@Size`            | 在指定范围内的约束条件        | size()            |\n| 11  | `@Digits`          | 数字位数的约束条件          | digits()          |\n| 12  | `@DecimalMax`      | 最大数字的约束条件          | decimalMax()      |\n| 13  | `@DecimalMin`      | 最小数字的约束条件          | decimalMin()      |\n| 14  | `@Min`             | 最小的约束条件            | min()             |\n| 15  | `@Max`             | 最大的约束条件            | max()             |\n| 16  | `@NotBlank`        | 不能为空格的约束条件         | notBlank()        |\n| 17  | `@NotEmpty`        | 不能为空的约束条件          | notEmpty()        |\n| 18  | `@Email`           | Email 约束条件         | email()           |\n| 19  | `@Negative`        | 指定值必须为负数约束条件       | negative()        |\n| 20  | `@NegativeOrZero`  | 指定值必须为负数约束条件，包含0       | negativeOrZero()  |\n| 21  | `@Positive`        | 指定值必须为正数约束条件       | positive()        | \n| 22  | `@PositiveOrZero`  | 指定值必须为正数约束条件，包含0   | positiveOrZero()  |\n\n### ## hibernate-validator 约束注解支持\n\n实现了常见的几个，后续将陆续完善：\n\n| 序号  | 注解                  | 说明                 | 对应方法             |\n|:----|:--------------------|:-------------------|:-----------------|\n| 1   | `@NotBlank`         | 不能为空格的约束条件         | notBlank()       |\n| 2   | `@NotEmpty`         | 不能为空的约束条件          | notEmpty()       |\n| 5   | `@Email`            | Email 约束条件         | email()          |\n| 3   | `@Length`           | 长度的约束条件            | length()         |\n| 4   | `@URL`              | URL 约束条件           | url()            |\n| 6   | `@UniqueElements`   | 元素唯一约束条件           | uniqueElements() |\n| 7   | `@Range`            | 指定范围元素约束条件         | range()          |\n\n## 条件注解\n\n注解和常见的接口方法一一对应，所有的约束方法在 `Conditions` 工具类中。\n\n| 序号  | 注解                      | 说明        | 对应方法          |\n|:----|:------------------------|:----------|:--------------|\n| 1   | `@EqualsCondition`      | 等于指定值的条件  | equals()      |\n| 2   | `@NotEqualsCondition`   | 不等于指定值的条件 | notEquals()   |\n| 3   | `@AlwaysTrueCondition`  | 永远生效的条件   | alwaysTrue()  |\n| 4   | `@AlwaysFalseCondition` | 永远不生效的条件  | alwaysFalse() |\n\n# 注解自定义\n\n## 说明\n\n内置的注解，自然无法满足所有的场景。\n\n本项目中，约束和条件注解都是支持自定义的。\n\n## 约束注解 @Constraint\n\n所有系统的内置注解都可以作为学习的例子。\n\n### 定义注解\n\n以 `@AllEquals` 为例，核心的部分在 `@Constraint(AtAllEqualsConstraint.class)`。\n\n我们在 AtAllEqualsConstraint 中实现具体的约束逻辑。\n\n```java\n@Target(ElementType.FIELD)\n@Retention(RetentionPolicy.RUNTIME)\n@Constraint(AtAllEqualsConstraint.class)\npublic @interface AllEquals {\n\n    /**\n     * 当前字段及其指定的字段 全部相等\n     * 1. 字段类型及其他字段相同\n     * @return 指定的字段列表\n     */\n    String[] value();\n\n    /**\n     * 提示消息\n     * @return 错误提示\n     */\n    String message() default \"\";\n\n    /**\n     * 分组信息\n     * @return 分组类\n     * @since 0.1.2\n     */\n    Class[] group() default {};\n\n}\n```\n\n### 实现逻辑\n\n推荐直接继承 `AbstractAnnotationConstraint\u003cA\u003e`，实现对应的逻辑即可。\n\n```java\npublic class AtAllEqualsConstraint extends AbstractAnnotationConstraint\u003cAllEquals\u003e {\n\n    @Override\n    protected IConstraint buildConstraint(AllEquals annotation) {\n        return Constraints.allEquals(annotation.value());\n    }\n\n}\n```\n\n## 条件注解 @Condition\n\n所有系统的内置注解都可以作为学习的例子。\n\n### 定义注解\n\n以 `@AlwaysTrueCondition` 为例，核心的部分在 `@Condition(AtAlwaysTrueCondition.class)`。\n\n我们在 AtAlwaysTrueCondition 中实现具体的约束逻辑。\n\n```java\n@Target(ElementType.FIELD)\n@Retention(RetentionPolicy.RUNTIME)\n@Condition(AtAlwaysTrueCondition.class)\npublic @interface AlwaysTrueCondition {\n}\n```\n\n### 实现逻辑\n\n推荐直接继承 `AbstractAnnotationCondition\u003cA\u003e`，实现对应的逻辑即可。\n\n```java\npublic class AtAlwaysTrueCondition extends AbstractAnnotationCondition\u003cAlwaysTrueCondition\u003e {\n\n    @Override\n    protected ICondition buildCondition(AlwaysTrueCondition annotation) {\n        return Conditions.alwaysTrue();\n    }\n\n}\n```\n\n# 开源地址\n\n为了便于大家学习使用，目前校验框架已开源。\n\n欢迎大家 fork+star，鼓励一下老马~\n\n\u003e [validator](https://github.com/houbb/validator)\n\n# ROAD-MAP\n\n- [ ] 优化提示信息\n\n- [ ] springboot 整合\n\n- [ ] i18N 對應的描述信息\n\n- [ ] 更多约束条件\n\nphone\n\nidNo\n\n银行卡\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoubb%2Fvalidator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoubb%2Fvalidator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoubb%2Fvalidator/lists"}