私は単純なAJAX/Springを使用したJSONWebサービスを構築しています。一般的なデータフローは次のとおりです。
some DTO from browser
v
Spring @Controller method
v
Spring @Service method
データ検証を処理する最も簡単な方法を探しています。
@Valid
メソッド内で非常にうまく機能する@Controller
アノテーションを知っています。@Valid
notが@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
の場合:コントローラーがドメインオブジェクトを操作し、サービスにそのオブジェクトを保存させる必要がありますか? (これは私にはかなり役に立たないようです)私の意見では、サービスはデータの整合性のみに責任を持つべきです。
これをどのように解決しますか?
私の答え?両方。
サービスは、自身の契約の有効性を確認する必要があります。
コントローラはUIの一部です。ユーザーエクスペリエンスを向上させるために検証してバインドする必要がありますが、サービスはそれに依存しないでください。
サービスは、それがどのように呼び出されているかを知ることができません。 RESTサービスとしてラップするとどうなりますか?
このサービスは、UIでは不可能な方法でビジネスロジック違反についても認識します。ユースケースが適切に満たされていることを確認するために検証する必要があります。
ダブルバッグ;両方を行います。
私の他の答えを参照してください: コントローラーまたはサービスレイヤーの前提条件を確認してください
Spring MVCと同様に、サービスレイヤーでエラー処理などの検証を本当に実行したい場合は、 javax.validation
とAspectJ(検証方法をアドバイスするため)を使用できます。リフレクションに作業と宣言型プログラミング(注釈)を行わせるようなものです。
メソッドはリフレクション(URLルーティング/ディスパッチ)を介して呼び出されるため、SpringMVCはエラー処理を行うためにAspectJ/AOPを実行する必要はありません。
最後に、MVCコードについては、@Valid
が非公式に非推奨になっていることを知っておく必要があります。代わりに、 @Validated
を検討してください。これにより、javax.validation
機能がさらに活用されます。