Spring 数据休息和业务规则验证

Spring data rest and business rules validation

我想寻求在处理 spring 数据剩余时应用业务规则的最佳实践。

让我们考虑以下场景:

所以我需要确保每当有人 POST 呼叫 /ordersCustomer 进行呼叫 验证

我正在考虑使用 beforeSave Validators 将其他 service/repositories 自动装配到 Validator 并检查任何需要检查的内容。

是否有更好的方法来实现同样的目标?

有几种方法可以解决这个问题。据我所知:

  1. 使用 spring 安全注释,例如 @PreAuthorize。但是,这些注释的预期用途是出于安全目的,您提到的是业务规则。我会将这些用于用户授权规则 Spring data rest security chapter

  2. 您自己提到的验证器的使用。 Spring data rest Validators

  3. 使用spring数据休息事件Spring data rest events. You can create global event handlers, however here you need to determine the entity type. I would go with Annotated event handlers to perform business logic Spring data rest annotated event handler

可用于解决业务规则相关问题的开箱即用解决方案是使用 Spring AOP。您可以做的是定义一个注释(例如@X)并将该注释放在您的 POST 调用之上。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface X{}

接下来你需要做的是,创建一个方面,运行你在这个方面的自定义验证逻辑如下,

@Aspect
@Component
public class CustomAspect {

   //You can autowire beans here

    @Around("@annotation(qualified name of X)")
    public Object customMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        flag = customLogic();
        if (flag){
           return joinPoint.proceed(); //return if logic passes, otherwise
        }else{
           throw new BusinessRuleException("Business rule violated");
        }
    }

    private boolean customLogic(){
     //your custom logic goes here
    }
}

最后在控制器层的任何方法之上应用此注释,例如:

@X
@RequestMapping(method = RequestMethod.POST, value = "do-something")
public void callSomething(HttpServletRequest request) throws Exception {
   // your business logic goes here
}

上面唯一需要注意的是,您需要将 HttpServletRequest 请求 显式传递给您的控制器方法,以便 AOP 方面获得相同的上下文来操作用户会话相关属性,例如session_id等

以上解决方案将帮助您在业务逻辑之上添加业务规则,并帮助您完成要在 Web 应用程序中构建的各种预验证。这是 Spring AOP 的一个非常方便的应用程序。如有任何

,请联系我们

因此,为了世界篇的缘故,我添加了我的解决方案。和#2一起去了。

documentation 非常清楚如何进行,所以只分享一些可能会节省您时间的技巧。

  1. 你需要assign validators manually, auto-discovery doesn't work
  2. 手动拼写事件类型容易出错,一些助手Enum可能会派上用场。

喜欢:

/** 
 * "beforeSave" gets called on PATCH/PUT methods
 * "beforeCreate" on POST
 * "beforeDelete" on DELETE
 */
enum Event {
    ON_CREATE("beforeCreate"), ON_UPDATE("beforeSave"), 
 ON_DELETE("beforeDelete");

    private String name;

    Event(String name) {
        this.name = name;
    }
} 

...

private static void addValidatorForEvents(ValidatingRepositoryEventListener eventListener, Validator validator, Event... events) {
    Arrays.asList(events).forEach(event -> eventListener.addValidator(event.name, validator));
}