在控制器和服务之间共享相同的方法前置逻辑?

时间:2015-11-11 11:58:02

标签: java spring spring-mvc design-patterns preconditions

我有ServiceController

服务中的每个方法都有其先决条件,例如:

  public void doSomething(Parameter para1 , Parameter para2 ...) {
    if ( something wrong ) {
      throw new RuntimeException1();
    }
    if ( another thing wrong ) {
      throw new RuntimeException2();
    }
    // continue do something 
  }

在Controller层中,有两种方法,一种是showForm(),它显示用户输入的形式;另一个是doApplyForm(),它接受​​表单并调用底层Service.doSomething()

以下是伪代码(我删除了一些BindingResultattr.addFlashAttribute代码):

  @Injected Service service;

  public String showForm() {
    if ( something wrong ) {
      throw new RuntimeException1();
    }
    if ( another thing wrong ) {
      throw new RuntimeException2();
    }
    return "showForm";
  }

  public String doApplyForm(@Validated Form form) {
    try {
      service.doSomething(para1 , para2 ...);
      return "redirect:/";
    } catch (Exception e) {
      // error handling 
      return "redirect:/error";
    }
  }

效果很好,但我不满意。内有难闻的气味

问题出在showForm(),它与Controller.doSomething()共享相同的先决条件。

如果将来Service.doSomething()添加其他先决条件,则Controller.showForm()必须进行相应的更改。

我想知道是否有任何设计模式或框架可以消除这种难闻的气味

欢迎使用Java8的功能解决方案。

感谢。

2 个答案:

答案 0 :(得分:1)

您可以定义名为Preconditions的util类,并将所有验证逻辑移到那里。它是一种常见模式,有许多框架可以利用它。例如,Guava:Preconditions docs

至少这样,if (condition) throw new exception将被封装并更易于管理。

答案 1 :(得分:1)

Introduce a parameter object for the service request and put the validation logic into the request object. E.g.

public class DoSomethingRequest {

   private Parameter param1;
   private Parameter param2;


   public void validate(){
       if ( something wrong ) {
           throw new RuntimeException1();
       }
       if ( another thing wrong ) {
           throw new RuntimeException2();
       }
   }

}

Your service will be more easy

public void doSomething(DoSomethingRequest request) {
    request.validate();
}

so the controller

public String showForm() {
    DoSomethingRequest request = ... // obtained somehow
    request.validate();
    // ...
    return "showForm";
}

This encapsulates the service method's preconditions in an object.