3

私はSpring MVCの初心者で、サーバー側の検証に関連するチュートリアルプロジェクトをインポートしましたが、それがどのように機能するかについて疑問があります.

したがって、次のログイン フォームを含むlogin.jspという名前のログイン ページがあります。

<form:form action="${pageContext.request.contextPath}/login" commandName="user" method="post">

    <table>

        <tr>
            <td><label>Enter Username : </label></td>
            <td><form:input type="text" path="username" name="username" />
                <br> <form:errors path="username" style="color:red;"></form:errors>
            </td>
        </tr>

        <tr>
            <td><label>Enter Password : </label></td>
            <td><form:input type="password" path="password" name="password" />
                <br> <form:errors path="password" style="color:red;"></form:errors>
            </td>
        </tr>

        <tr>
            <td>&nbsp</td>
            <td align="center"><input type="submit" value="Login" /></td>
        </tr>

    </table>

</form:form>

モデルから取得したcommandName="user"属性によって指定されたオブジェクトを使用して、ユーザーが挿入したユーザー名とパスワードを保存すると思います (間違ったアサーションを行っている場合は訂正してください)。

このcommandName="user"は、このUserクラスのインスタンスです。

import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotBlank;

public class User {

    @NotBlank(message="Username can not be blank")
    private String username;

    @Size(min=6,message="Password must be atleast 6 characters long")
    private String password;

    private String gender;
    private String vehicle;
    private String country;
    private String image;

    ...............................................
    ...............................................
    GETTER AND SETTER METHODS
    ...............................................
    ...............................................
}

ご覧のとおり、ユーザー名パスワードのフィールドで@NotBlank@Sizeの検証アノテーションが宣言されています。

そしてここで最初の疑問: 2 つの使用されたライブラリjavax.validationおよびorg.hibernate.validatorとの違いは正確には何ですか?

チュートリアルで両方を使用するのはなぜですか? 休止状態バリデータ ライブラリのみを使用して同じことを行うことはできますか? (Hibernate バリデーターを使用して文字列の有効な長さを指定できると思いますか?)

したがって、ログイン フォームが送信されると、コントローラー クラスに宣言されたこのメソッドによって処理される/loginリソースに対する HttpRequest が生成されます。

@RequestMapping(value="/login" , method=RequestMethod.POST)
public String do_login(HttpServletRequest req , Model md , HttpSession session , @Valid User user, BindingResult br)
{
    try
    {
        //System.out.println(br.getAllErrors().size());

        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println("Username and pasword are : "+username +"  "+ password);
        if(br.getAllErrors().size() > 0){
            System.out.println("Server side validation takes place....");
        }
        else{
        Login_Model lm = new Login_Model();
        String message = lm.do_login_process(username, password);

        if(message.equals("login success"))
        {
            session.setAttribute("username", username);
            return "redirect:/myprofile";
        }
        else
        {
            md.addAttribute("error_msg", message);
        }
        }
        return "login";
    }
    catch(Exception e)
    {
        return "login";
    }
}

わかりました、そして今、私はこの方法について次の疑問を持っています:

1) このオブジェクトを入力パラメーターとして受け取ります: @Valid User user。誰がそれに合格しますか?フォームでcommandName="user"と指定したことで、Spring が自動でやってくれるのではないかと思います。それが正しいか?

2)私が理解していることから、@Validアノテーションは自動的に検証プロセスを呼び出します。それはどのように起こりますか?Spring が提供するAOP機能に関連するものはありますか? または何?この@Validアノテーションがjavax.validationライブラリのみに関連し、Hibernate バリデーターには関連しないのはなぜですか (したがって、この@Validアノテーションは、Hibernate バリデーターアノテーションでアノテーションが付けられたフィールドも検証するのですか?なぜですか?)

3)ユーザーがログインフォームに間違った値を挿入した場合、私が理解していることから、BindingResult br入力パラメーターによってこのエラーを取得できます。デバッガーを使用すると、このオブジェクトには、 Userモデル オブジェクトに定義された注釈によって定義されたエラー メッセージが含まれていることがわかります。正確にはどのように機能しますか?

TNX

4

3 に答える 3

5

javax.validationそして、ここで最初の疑問: 使用されている 2 つのライブラリとの違いは正確には何org.hibernate.validatorですか?

javax.validationJSR-303 API に由来します。たとえば、この Maven 依存関係の API クラスを確認できます。

Hibernate バリデーター@NotBlankは JSR 303 の実装の 1 つ (実際には参照実装) であるため、すべての API を実装しますが、言及した注釈などの独自の拡張機能を追加しますJSR 303 の他の実装は、たとえばApache BValです。


このオブジェクトを入力パラメータとして受け取ります: @Valid User user. ハンドラー メソッドに渡すのは誰ですか?

Spring MVC のハンドラー メソッドへの値は、 interface の実装によって提供されますHandlerMethodArgumentResolver。あなたの場合、パラメーターを解決するために呼び出される実装UserはおそらくServletModelAttributeMethodProcessor. これらのクラスのソース コードと JavaDoc を表示して、それらが内部でどのように機能するかを確認できます。


注釈は@Valid、検証プロセスを自動的に呼び出します。これはどのように起こったのですか?AOPを使用していますか?このアノテーションがライブラリ@Validのみに関連し、Hibernate バリデーターには関連しないのはなぜですか (このアノテーションは、Hibernateバリデーターアノテーションでアノテーションが付けられたフィールドも検証するのですか?)javax.validation@Valid

ModelAttributeMethodProcessor検証プロセスは、前述のクラスのServletModelAttributeMethodProcessor継承元であるによって呼び出されます。次のメソッドが含まれています。

protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) {
    Annotation[] annotations = parameter.getParameterAnnotations();
    for (Annotation ann : annotations) {
        if (ann.annotationType().getSimpleName().startsWith("Valid")) {
            Object hints = AnnotationUtils.getValue(ann);
            binder.validate(hints instanceof Object[] ? (Object[]) hints : new Object[] {hints});
            break;
        }
    }
}

よく見ると、次の式の条件がわかります。

ann.annotationType().getSimpleName().startsWith("Valid")

これは、パラメーターにで始まるアノテーションがある場合、Spring が検証を呼び出すことを意味しますValid。検証グループをサポートするのは、JSR 303@Validまたは Springである可能性があります。@Validated名前が で始まる限り、それはカスタム アノテーションである可能性もありますValid


ユーザーがログインフォームに間違った値を挿入した場合に私が理解していることから、BindingResultハンドラーパラメーターからこのエラーを取得できます。デバッガーを使用すると、このオブジェクトには、User モデル オブジェクトに定義された注釈によって定義されたエラー メッセージが含まれていることがわかります。正確にはどのように機能しますか?

ModelAttributeMethodProcessorクラスに戻りましょう。resolveArgumentメソッドには次のコードがあります。

WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);

WebDataBinderこれにより、前述のvalidateIfApplicableメソッドで検証が呼び出されるインスタンスが作成されます。検証自体が にデータを入力し、クラスBindingResultを介してコントローラー ハンドラー メソッドに提供されます。ErrorsMethodArgumentResolverクラスは再び を実装しHandlerMethodArgumentResolverます。


TLDR : この質問であなたが尋ねることの多くは、さまざまな実装にたどることができますHandlerMethodArgumentResolver。これらのクラスを確認し、デバッガーを使用してステップ実行して、理解を深めることをお勧めします。

于 2015-10-10T12:20:46.997 に答える
2
  1. プロパティバインディングと呼ばれる正しい
  2. Spring 3+ は、クラスパスに JSR 303 バリデーター フレームワークがある場合、アノテーションJSR303による Bean 検証をサポートします。@ValidHibernate Validator は、JSR 303 リファレンス実装の 1 つです。

  3. 制約違反は BindingResult オブジェクトのエラーとして公開されるため、コントローラーのメソッドで違反を確認する必要があります。

    if(br.getAllErrors().size() > 0){ System.out.println("サーバー側の検証が行われます...."); }

要約すると、Spring MVC は、 Spring のフォーム タグを使用する JSP フォームからの入力の@Valid後に、アノテーションによって注釈が付けられたモデル オブジェクトを検証します。binding its properties制約違反は、BindingResultオブジェクト のエラーとして公開されます。ここは良い投稿です

于 2015-10-10T12:27:05.750 に答える
2

使用されている 2 つのライブラリ javax.validation と org.hibernate.validator との違いは何ですか?

Bean Validation は、アノテーションを介してオブジェクト モデルの制約を表現し、拡張可能な方法でカスタム制約を記述できるようにするJava仕様です。まったく実装されていない単なる仕様です。Hibernate Validator は、この仕様の実装です。Hibernate Validator は Bean Validation を完全に実装しており、hibernate に固有の機能もいくつか備えています。簡単に言えば、javax.validation仕様部分でorg.hibernate.validatorあり、休止状態固有の機能です。

休止状態バリデータ ライブラリのみを使用して同じことを行うことはできますか? (Hibernate バリデーターを使用して文字列の有効な長さを指定できると思いますか?)

はい、できますが、javax.validation名前空間に固執し、 などのベンダー固有の名前空間による固有の機能のみを使用することをお勧めしますorg.hibernate.validator。このアプローチの利点は、最小限の変更でHibernate Validator から Bean Validation 実装を別のものに切り替えることができることです。

チュートリアルで両方を使用するのはなぜですか?

@NotBlank制約は Bean Validation 仕様では利用できず、Hibernate Validator によってのみ提供されるためです。

このオブジェクトを入力パラメーターとして受け取ります: @Valid User ユーザー。誰がそれに合格しますか?フォームで commandName="user" と指定したことで、Spring が自動でやってくれるのではないかと思います。それが正しいか?

おそらく、空のオブジェクトを返す url のGETコントローラーがあり、それが. ユーザーがフォームに入力して送信すると、Spring はそれらのタグ値を収集し、インスタンスを作成してコントローラーに渡します。loginUser<form:input type="text" path="username" name="username" />User

この @Valid アノテーションが javax.validation ライブラリのみに関連し、Hibernate バリデーターには関連しないのはなぜですか (したがって、この @Valid アノテーションは、Hibernate バリデーターアノテーションでアノテーションが付けられたフィールドも検証するのですか?なぜですか?)

すでに説明済み、Spec/Impl の話!

于 2015-10-10T12:15:30.630 に答える