验证者+方面:自定义验证

美好的一天,哈伯!

一段时间后,我决定在这里再次写信并分享我的经验。 这次,本文将介绍如何自定义标准验证器,并在需要使用Spring方面的任何地方调用它们。 好吧,它鼓励我写-缺乏这类信息,尤其是俄语。

问题


因此,该应用程序的本质大致如下:有一个网关-api,它接受请求,并进一步将其修改并将其重定向到适当的库。 但是每个银行的要求和验证参数都不同。 因此,不可能验证初始请求。 有两种方法-使用来自javax.validation的注释,或编写您自己的单独的验证层。 在第一种情况下,存在一个陷阱-默认情况下,只能在控制器中验证对象。 在第二种情况下,也有缺点-这是一个额外的层,需要大量的代码,并且即使更改了模型,也必须更改验证器。

因此,决定在必要时找到一种方法来拉标准验证器,而不仅仅是在控制器中。

我们拉验证器


在Google搜寻了几个小时之后,发现了一些解决方案,其中最合适的方法是自动装配javax.validation.Validator并在其上调用validate方法,您需要将经过验证的对象作为参数传递给该方法。

似乎已经找到了解决方案,但是要在各处验证验证器似乎不是一个好主意,我想要一个更优雅的解决方案。

添加AOP


无需三思而后行,我决定尝试使最喜欢的方面适应此解决方案。

逻辑大致如下:创建注释,并将其挂在将一个对象转换为另一个对象的方法上。 在该方面的进一步方面,我们拦截所有带有此批注标记的方法,并为它们返回的值调用validate方法。 获利

所以注释:

//      @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Validate {} 


一种转换查询的方法是:

 @Validate public SomeBankRequest requestToBankRequest(Request<T> request) { SomeBankRequest bankRequest = ...; ... //        ... return bankRequest; } 

好吧,实际上是方面本身:

 @Aspect @Component public class ValidationAspect { private final Validator validator; //    public ValidationAspect(Validator validator) { this.validator = validator; } //       // @Validate       @AfterReturning(pointcut = "@annotation(api.annotations.Validate)", returning = "result") public void validate(JoinPoint joinPoint, Object result) { //     Set<ConstraintViolation<Object>> violations = validator.validate(result); //    ,    ,     //        if (!violations.isEmpty()) { StringBuilder builder = new StringBuilder(); //          ,   //  violations.forEach(violation -> builder .append(violation.getPropertyPath()) .append("[" + violation.getMessage() + "],")); throw new IllegalArgumentException("Invalid values for fields: " + builder.toString()); } } } 

简要介绍工作方面:

我们截取由带有Validate批注标记的方法返回的对象,然后将其传递给验证器方法,该方法将返回Set<ConstraintViolation<Object>> -简而言之-一组类,这些类具有有关已验证字段和错误的不同信息。 如果没有错误,则该集合将为空。 然后,我们只需遍历该集合并创建一条错误消息,并验证所有字段,然后抛出执行。

 violation.getPropertyPath() -    violation.getMessage() -  ,       

结论


因此,我们可以在应用程序中的任何位置调用对所需对象的验证,并且,如果需要,我们可以对注释和方面进行补充,以便验证不仅可以返回对象的方法,还可以对方法的字段和参数进行验证。

聚苯乙烯


另外,如果从同一类的另一个方法调用标记为Validate的方法,请记住aop和proxy之间的连接。

Source: https://habr.com/ru/post/zh-CN432040/


All Articles