2013-09-30 19 views
7

我正在用Spring構建一個直接的AJAX/JSON Web服務。常見的數據流是:服務或控制器中的Spring DTO驗證?

some DTO from browser 

      v 

Spring @Controller method 

      v 

    Spring @Service method 

我正在尋找最簡單的方式來處理數據驗證。

  • 我知道@Valid註釋這工作得很好,裏面@Controller方法。
  • 爲什麼@Valid不在@Service方法工作?

我的意思是:任何其他服務和控制器都可以使用服務方法。那麼在@Service級別驗證會更有意義嗎?


讓我們這個簡單的例子:

MyDTO.java:

public class MyDTO { 
    @NotNull 
    public String required 
    @Min(18) 
    public int age; 
} 

MyServiceImpl.java:

public MyDomainObject foo(MyDTO myDTO) { 
    // persist myDTO 
    // and return created domain object 
} 

MyController.java:

@Autowired 
MyService myService; 

@Autowired  // some simple bean mapper like Dozer or Orika 
Mapper mapper; // for converting domain objects to DTO 

@RequestMapping(...) 
public MyDomainObjectDTO doSomething(@RequestBody MyDTO myDTO) { 
    mapper.map(myService.foo(myDTO), MyDomainObjectDTO.class); 
} 

它是常見的做法,該服務方法接收DTO?

  • 如果yes:在服務方法內驗證DTO的最佳實踐是什麼?
  • 如果no:也許應該控制器操縱域對象,只是讓保存該對象的服務? (這對我來說似乎很沒用)

在我看來,服務應該只負責數據的一致性。

你如何解決這個問題?

+0

[檢查控制器或服務層中的先決條件]可能的重複(http://stackoverflow.com/questions/11929781/check-preconditions-in-controller-or-service-layer) –

回答

10

我的回答是?都。

服務必須檢查它自己的有效性合同。

控制器是UI的一部分。它應該驗證和綁定更好的用戶體驗,但服務不應該依賴它。

服務無法知道它是如何被調用。如果你將它作爲REST服務包裝呢?

該服務還知道業務邏輯違規的方式,沒有用戶界面即可。它需要驗證以確保用例得到適當實現。

雙包它;做兩個。

+0

但是,爲什麼服務沒有'允許'@有效'註釋? ...我明白了你的意思,服務和控制器可以在他們的課程中使用(例如)不同的領域。在我的應用程序中,它總是一樣的。正因爲如此,我只是通過DTO進入服務。 –

+0

因爲驗證和防禦性編程/錯誤處理之間存在差異。這就是說我確實使用防禦性編程進行驗證。我會盡快發佈答案。 –

2

看我其他的答案:Check preconditions in Controller or Service layer

如果你真的想這樣做就像對Spring MVC類似你的服務層處理錯誤,你可以使用javax.validation和AspectJ(勸告的方法來驗證)驗證這就是我這樣做是因爲我喜歡使用反射來完成工作和聲明式編程(註釋)。

Spring MVC不需要做AspectJ/AOP來做錯誤處理,因爲這些方法是通過反射(url路由/調度)調用的。

最後爲你MVC代碼,你應該知道,@Valid是非官方不贊成使用。請考慮@Validated,這將利用更多的javax.validation功能。

+0

我現在在服務層使用'@ Validated',這非常棒。只需註冊Spring的'MethodValidationPostProcessor',然後在Service接口上添加一個'@ Validated'註釋,最後在服務接口中定義的方法簽名上放置一些'@ Valid'或'@NotNull'註釋。 ServiceImpl保持清潔。這工作非常好!唯一的「問題」是,拋出的'ConstraintViolationException'中的'propertyPath'前綴爲整個調用層次,即'controllerMethod.serviceMethod.dtoProperty'。我必須以某種方式擺脫這一點。 –

+0

你是什麼意思的'非正式棄用'? – prettyvoid

相關問題