24

一般的に、Spring MVC は Hibernate Validator および JSR-303 とうまく統合されることは誰もが知っています。しかし、誰かが言ったように、Hibernate Validator は Bean Validation 専用のものです。つまり、より複雑な検証をデータ層にプッシュする必要があります。このような検証の例: ビジネス キーの一意性、レコード内依存性 (通常、これは DB 設計の問題を指摘するものですが、私たちは皆、不完全な世界に住んでいます)。文字列フィールドの長さなどの単純な検証でさえ、DB 値によって駆動される場合があり、Hibernate Validator が使用できなくなります。

私の質問は、Spring、Hibernate、または JSR がそのような複雑な検証を実行するために提供するものはありますか? Spring と Hibernate に基づく標準の Controller-Service-Repository セットアップで、そのような検証を実行するための確立されたパターンまたはテクノロジの一部はありますか?

更新:より具体的にさせてください。たとえば、AJAX 保存要求をコントローラーのsaveメソッドに送信するフォームがあります。何らかの検証エラー (単純または「複雑」) が発生した場合、ブラウザに戻り、問題のあるフィールドと関連するエラーを示す json が返されます。単純なエラーの場合、フィールド (存在する場合) とエラー メッセージを から抽出できますBindingResult。「複雑な」エラーに対してどのインフラストラクチャを提案しますか? 例外ハンドラーを使用することは、私には良い考えではないように思えます。なぜなら、saveメソッドとの間で単一の検証プロセスを分離すると@ExceptionHandler、物事が複雑になるからです。現在、アドホックな例外 (などValidationException)を使用しています。

public @ResponseBody Result save(@Valid Entity entity, BindingResult errors) {
    Result r = new Result();
    if (errors.hasErrors()) {
        r.setStatus(Result.VALIDATION_ERROR);     
        // ...   
    } else {
        try {
            dao.save(entity);
            r.setStatus(Result.SUCCESS);
        } except (ValidationException e) {
            r.setStatus(Result.VALIDATION_ERROR);
            r.setText(e.getMessage());
        }
    }
    return r;
}

より最適なアプローチを提供できますか?

4

1 に答える 1

43

はい、古き良き確立されたException throwingの Java パターンがあります。
Spring MVC はそれをうまく統合しています (コード例については、私の回答の 2 番目の部分に直接スキップできます)。

「複雑な検証」と呼ばれるものは、実際には例外です。ビジネス キーの単一性エラー、低層または DB エラーなどです。


リマインダー: Spring MVC での検証とは?

検証はプレゼンテーション レイヤーで行う必要があります。基本的には、送信されたフォーム フィールドの検証に関するものです。

それらを 2 種類に分類できます。

1) 簡易検証(JSR-303/Hibernate 検証を使用): 送信されたフィールドに指定された@Size/@Lengthがあること、@NotNullまたは@NotEmpty/であること、フォーマット@NotBlankがあることなどを確認します。@Email

2) 重い検証、または複雑な検証は、クロスフィールド検証などのフィールド検証の特定のケースに関するものです。

  • 例 1: フォームにはfieldAfieldBとがありfieldCます。各フィールドは個別に空にすることができますが、少なくとも 1 つのフィールドを空にすることはできません。
  • 例 2 :userAgeフィールドの値が 18 歳未満の場合、responsibleUserフィールドが null であってはならず、responsibleUser年齢が 21 歳以上である必要があります。

これらの検証は、Spring Validator 実装またはカスタム注釈/制約で実装できます。

これらすべての検証機能に加えて、Spring はまったく邪魔にならず、(良くも悪くも) やりたいことは何でもできるという事実があるため、あいまいに関連するものに「検証ハンマー」を使用したくなる可能性があることを理解しました。エラー処理まで。
そしてそれはうまくいくでしょう: バリデーションのみで、バリデーター/アノテーションで起こりうるすべての問題をチェックします (そして、下位層ではほとんど例外をスローしません)。あなたがすべてのケースについて考えたことを祈っているので、それは悪いことです。ロジックを簡素化し、何かにエラーがあることを確認するのを忘れて間違いを犯す可能性を減らすことができる Java 例外を利用しません。

したがって、Spring MVC の世界では、検証 (つまり、UI 検証) を下位層の例外(サービス例外や DB 例外 (キーの単一性など) など) と間違えてはなりません。


Spring MVC で便利な方法で例外を処理するには?

一部の人々は、「なんてこった、私のコントローラでは、すべての可能なチェック例外を1つずつチェックし、それぞれのメッセージエラーについて考えなければならないのですか?そんなことはありません!」と考える人もいます。私はその一人です。:-)

ほとんどの場合、すべての例外が拡張される一般的なチェック済み例外クラスを使用してください。次に、Spring MVC コントローラーで@ExceptionHandlerと一般的なエラー メッセージを使用して処理します。

コード例:

public class MyAppTechnicalException extends Exception { ... }

@Controller
public class MyController {

    ...

    @RequestMapping(...)
    public void createMyObject(...) throws MyAppTechnicalException {
        ...
        someServiceThanCanThrowMyAppTechnicalException.create(...);
        ...
    }

    ...

    @ExceptionHandler(MyAppTechnicalException.class)
    public String handleMyAppTechnicalException(MyAppTechnicalException e, Model model) {

        // Compute your generic error message/code with e.
        // Or just use a generic error/code, in which case you can remove e from the parameters
        String genericErrorMessage = "Some technical exception has occured blah blah blah" ;

        // There are many other ways to pass an error to the view, but you get the idea
        model.addAttribute("myErrors", genericErrorMessage);

        return "myView";
    }

}

シンプル、迅速、簡単、クリーン!

特定の例外のエラー メッセージを表示する必要がある場合や、設計が不十分で変更できないレガシー システムのために一般的なトップレベルの例外を表示できない場合は、他@ExceptionHandlerの を追加するだけです。
別のトリック: コードの乱雑さを軽減するために、複数の例外を次のように処理できます。

@ExceptionHandler({MyException1.class, MyException2.class, ...})
public String yourMethod(Exception e, Model model) {
    ...
}

結論: 検証をいつ使用するか? いつ例外を使用しますか?

  • UI からのエラー = 検証 = 検証機能 (JSR-303 アノテーション、カスタム アノテーション、Spring バリデーター)
  • 下位層からのエラー = 例外

「UI からのエラー」とは、「ユーザーがフォームに何か間違ったことを入力した」という意味です。

参考文献:

于 2012-09-30T12:38:38.183 に答える