diff --git a/changelog.md b/changelog.md index 0eb502ab..82aef8b8 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,7 @@ ## 2.1.0 - 支持分布式限流(redis实现) +- 可调整JSR-303校验顺序 ## 2.0.0 diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index 370a3a49..b4b85507 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,32 +1,32 @@ -* [首页](/?t=1567770151526) +* [首页](/?t=1567997064207) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1567770151530) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1567770151558) - * [新增接口](files/10020_新增接口.md?t=1567770151558) - * [开发流程](files/10021_开发流程.md?t=1567770151558) - * [业务参数校验](files/10030_业务参数校验.md?t=1567770151558) - * [错误处理](files/10040_错误处理.md?t=1567770151558) - * [编写文档](files/10041_编写文档.md?t=1567770151558) - * [接口交互详解](files/10050_接口交互详解.md?t=1567770151558) - * [easyopen支持](files/10070_easyopen支持.md?t=1567770151559) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1567770151559) - * [ISV管理](files/10085_ISV管理.md?t=1567770151559) - * [自定义返回结果](files/10087_自定义返回结果.md?t=1567770151559) - * [自定义过滤器](files/10088_自定义过滤器.md?t=1567770151559) - * [路由授权](files/10090_路由授权.md?t=1567770151559) - * [接口限流](files/10092_接口限流.md?t=1567770151559) - * [监控日志](files/10093_监控日志.md?t=1567770151559) - * [SDK开发](files/10095_SDK开发.md?t=1567770151559) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1567770151559) - * [应用授权](files/10097_应用授权.md?t=1567770151560) - * [传统web开发](files/10100_传统web开发.md?t=1567770151560) - * [文件上传](files/10104_文件上传.md?t=1567770151560) - * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1567770151560) - * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1567770151560) - * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1567770151560) + * [快速体验](files/10010_快速体验.md?t=1567997064209) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1567997064227) + * [新增接口](files/10020_新增接口.md?t=1567997064227) + * [开发流程](files/10021_开发流程.md?t=1567997064227) + * [业务参数校验](files/10030_业务参数校验.md?t=1567997064227) + * [错误处理](files/10040_错误处理.md?t=1567997064227) + * [编写文档](files/10041_编写文档.md?t=1567997064227) + * [接口交互详解](files/10050_接口交互详解.md?t=1567997064227) + * [easyopen支持](files/10070_easyopen支持.md?t=1567997064227) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1567997064227) + * [ISV管理](files/10085_ISV管理.md?t=1567997064227) + * [自定义返回结果](files/10087_自定义返回结果.md?t=1567997064227) + * [自定义过滤器](files/10088_自定义过滤器.md?t=1567997064228) + * [路由授权](files/10090_路由授权.md?t=1567997064228) + * [接口限流](files/10092_接口限流.md?t=1567997064228) + * [监控日志](files/10093_监控日志.md?t=1567997064228) + * [SDK开发](files/10095_SDK开发.md?t=1567997064228) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1567997064228) + * [应用授权](files/10097_应用授权.md?t=1567997064228) + * [传统web开发](files/10100_传统web开发.md?t=1567997064228) + * [文件上传](files/10104_文件上传.md?t=1567997064228) + * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1567997064228) + * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1567997064228) + * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1567997064228) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1567770151560) - * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1567770151560) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1567770151560) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1567770151560) - * [常见问题](files/90100_常见问题.md?t=1567770151560) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1567997064229) + * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1567997064229) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1567997064229) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1567997064229) + * [常见问题](files/90100_常见问题.md?t=1567997064229) diff --git a/doc/docs/files/10030_业务参数校验.md b/doc/docs/files/10030_业务参数校验.md index 99599216..6ea1bce3 100644 --- a/doc/docs/files/10030_业务参数校验.md +++ b/doc/docs/files/10030_业务参数校验.md @@ -27,6 +27,21 @@ public class GoodsParam { ``` +- 校验顺序 + +如果存在多个注解,可以指定groups来控制校验顺序,如下代码所示: + +```java +@NotBlank(message = "NotBlank", groups = Group1.class) +// 优先校验Group2 +// 可交换下面Group2,Group3,看下校验顺序 +@Length(min = 2, max = 20, message = "length must 10~20", groups = Group2.class) +@Pattern(regexp = "[a-zA-Z]*", message = "name must letters", groups = Group3.class) +private String name; +``` + +优先校验`@Length`,通过后再校验`@Pattern` + ## 参数校验国际化 国际化的配置方式如下: diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml index 9bb50bd3..83627a83 100644 --- a/sop-common/sop-service-common/pom.xml +++ b/sop-common/sop-service-common/pom.xml @@ -58,6 +58,24 @@ spring-boot-autoconfigure true + + junit + junit + 4.12 + test + + + javax.el + javax.el-api + 3.0.0 + test + + + org.glassfish + javax.el + 3.0.0 + test + diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ServiceParamValidator.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ServiceParamValidator.java index 31ca519f..63d58761 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ServiceParamValidator.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ServiceParamValidator.java @@ -4,6 +4,7 @@ import com.gitee.sop.servercommon.bean.ServiceContext; import com.gitee.sop.servercommon.exception.ServiceException; import com.gitee.sop.servercommon.message.ServiceErrorEnum; import com.gitee.sop.servercommon.message.ServiceErrorFactory; +import com.gitee.sop.servercommon.param.validation.ValidationGroupSequence; import org.springframework.util.CollectionUtils; import javax.validation.ConstraintViolation; @@ -18,8 +19,8 @@ import java.util.Set; public class ServiceParamValidator implements ParamValidator { private static final String LEFT_TOKEN = "{"; private static final String RIGHT_TOKEN = "}"; - public static final String EQ = "="; - public static final String COMMA = ","; + private static final String EQ = "="; + private static final String COMMA = ","; private static Object[] EMPTY_OBJ_ARRAY = {}; private static javax.validation.Validator validator; @@ -34,7 +35,7 @@ public class ServiceParamValidator implements ParamValidator { if (obj == null) { return; } - Set> set = validator.validate(obj); + Set> set = validator.validate(obj, ValidationGroupSequence.class); if (!CollectionUtils.isEmpty(set)) { ConstraintViolation oneError = set.iterator().next(); String errorMsg = oneError.getMessage(); diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group1.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group1.java new file mode 100644 index 00000000..45de0ef5 --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group1.java @@ -0,0 +1,7 @@ +package com.gitee.sop.servercommon.param.validation; + +/** + * @author tanghc + */ +public interface Group1 { +} diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group2.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group2.java new file mode 100644 index 00000000..b5d71073 --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group2.java @@ -0,0 +1,7 @@ +package com.gitee.sop.servercommon.param.validation; + +/** + * @author tanghc + */ +public interface Group2 { +} diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group3.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group3.java new file mode 100644 index 00000000..a8a16a78 --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group3.java @@ -0,0 +1,7 @@ +package com.gitee.sop.servercommon.param.validation; + +/** + * @author tanghc + */ +public interface Group3 { +} diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group4.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group4.java new file mode 100644 index 00000000..f0d809c1 --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group4.java @@ -0,0 +1,7 @@ +package com.gitee.sop.servercommon.param.validation; + +/** + * @author tanghc + */ +public interface Group4 { +} diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group5.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group5.java new file mode 100644 index 00000000..70f7c97f --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/Group5.java @@ -0,0 +1,7 @@ +package com.gitee.sop.servercommon.param.validation; + +/** + * @author tanghc + */ +public interface Group5 { +} diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/ValidationGroupSequence.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/ValidationGroupSequence.java new file mode 100644 index 00000000..69a01b5c --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/validation/ValidationGroupSequence.java @@ -0,0 +1,20 @@ +package com.gitee.sop.servercommon.param.validation; + +import javax.validation.GroupSequence; + +/** + * @author tanghc + */ +@GroupSequence({ + // 默认的必须加上,不然没有指定groups的注解不会生效 + javax.validation.groups.Default.class, + Group1.class, + Group2.class, + Group3.class, + Group4.class, + Group5.class, + +}) +public interface ValidationGroupSequence { +} + diff --git a/sop-common/sop-service-common/src/test/java/com/gitee/sop/servercommon/ValidatorTest.java b/sop-common/sop-service-common/src/test/java/com/gitee/sop/servercommon/ValidatorTest.java new file mode 100644 index 00000000..e7e510e9 --- /dev/null +++ b/sop-common/sop-service-common/src/test/java/com/gitee/sop/servercommon/ValidatorTest.java @@ -0,0 +1,48 @@ +package com.gitee.sop.servercommon; + +import com.gitee.sop.servercommon.param.ServiceParamValidator; +import com.gitee.sop.servercommon.param.validation.Group1; +import com.gitee.sop.servercommon.param.validation.Group2; +import com.gitee.sop.servercommon.param.validation.Group3; +import junit.framework.TestCase; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; + +/** + * @author tanghc + */ +public class ValidatorTest extends TestCase { + + private ServiceParamValidator serviceParamValidator = new ServiceParamValidator(); + + /** + * 测试JSR-303注解校验顺序,校验顺序: Group1~GroupN + */ + public void testValidate() { + serviceParamValidator.validateBizParam(new User("1", 1)); + } + + + @Data + @AllArgsConstructor + private static class User { + + // 如果字段为空,无论如何都会命中这个 + @NotBlank(message = "NotBlank", groups = Group1.class) + // 优先校验Group2 + // 可交换下面Group2,Group3,看下校验顺序 + @Length(min = 2, max = 20, message = "length must 10~20", groups = Group2.class) + @Pattern(regexp = "[a-zA-Z]*", message = "name must letters", groups = Group3.class) + private String name; + + @Min(value = 1, message = "min 1") + private int age; + + } + +}