使用の原則把握@ModelAttributeレベル(記事を使用)では、[まとめ] Spring MVCのを学ぶために

各1

誰もが明確にこの質問を考える必要があります:あなたは先祖の報酬が食べるか、神の報酬で食べています

序文

記事が描く@ModelAttributeこのシナリオのコア原則は、使用上のプレゼンテーション焦点を当てている@ModelAttributeさまざまなシナリオで使用されるが、と考慮事項(もちろん、いくつかの関連する原則が関与することになります)。

デモデモで最初に再び明確なものを取得する@ModelAttribute役割を。

@ModelAttributeの役割

あなたが見ているかもしれないが記事の基本原則を、それでもトップ概念の要約の一部を欠いている可能性があります。ここで私は私の理解でよ、要約@ModelAttribute主に次の三つの側面に分け、この注釈の役割を、:

  1. コマンドオブジェクト(参照オブジェクト)にリクエストパラメータを結合するコントローラをするための基準方法に載置された場合:要求コマンドオブジェクトに複数のパラメータを結合するように、简化プロセスを結合し、自動露出モデルデータの表示ビューページを使用した場合、
  2. 基準オブジェクトモデルデータを形成する露光:プロセッサ上の一般的なアプローチ(非機能的アプローチ、すなわち、全く存在しない@RequestMapping方法注釈付きの)場合には、ある表示可能形式フォーム参照データオブジェクトを:ここで、そのような登録を選択します静的な情報の都市。これは、加工方法(関数を実行する@RequestMapping以前に注釈を付け法)、それが自動的にオブジェクトモデル、ページの表示に使用されるビューに追加します。
  3. 露光@RequestMapping方法は、モデルデータの値を返す:上の機能処理メソッドの戻り値は、この方法は、ビューの表示ページに使用される露光処理関数の戻り値のモデルデータです。

これらの使用のための次のシナリオでは、与えられたDemo実際の使用へのご参考のために、ユースケースを。


@ConstructorPropertiesを説明します

論文原理で話題のオブジェクトだけでなく、空のコンストラクタを使用することができたときに、モデルが自動的に作成されているので、あなたも使用することができjava.beans.ConstructorProperties、この注釈を、そのためには、最初の波を導入する必要があります。

公式の説明:コンストラクタ上の注意、コンストラクタの表示パラメータゲッターが構築されたオブジェクトに対応する方法。

// @since 1.6
@Documented 
@Target(CONSTRUCTOR)  // 只能使用在构造器上
@Retention(RUNTIME)
public @interface ConstructorProperties {
    String[] value();
}

例としては、次のとおりです:

@Getter
@Setter
public class Person {
    private String name;
    private Integer age;

    // 标注注解
    @ConstructorProperties({"name", "age"})
    public Person(String myName, Integer myAge) {
        this.name = myName;
        this.age = myAge;
    }
}

ここでは上の注釈nameageそれはそれは手段に相当するPersonというJavaBeangetName()getAge()方法。
それは言う:コンストラクタの最初の引数を使用することができるgetName()2番目のパラメータはすることができます取得するにはgetAge()、実行時にメソッドのパラメータ名/コンストラクタが満たされていないため、注釈の使用はこの効果を達成することができ、取得しました。

このコメントそれの意味は何ですか?
実際には、今行く、真実を伝えるxmlことはあまり意味がないのフルアノテーション駆動型の年齢を。使用前にシーンとして最も頻繁に使用されているxml。このように豆を設定するには:

<bean id="person" class="com.fsx.bean.Person">
    <constructor-arg name="name" value="fsx"/>
    <constructor-arg name="age" value="18"/>
</bean>

だから、<constructor-arg>あなたは(持っている木で融通の利かないとエラーが発生しやすい)自然の秩序パラメータインデックスに従う必要はありません来る、あなたは、対応する属性の名前、多くの柔軟性に従うことができます。もともとXML設定の基本的な必要性が、ちょうど@ModelAttributeそれと新生児のこのリニューアルを解析し、以下の具体的な例が与えられます〜

> java.beansまた、注釈を提供java.beans.Transient(1.7申し出の後に):属ことを指定したり、フィールドが永続的ではありません。エンティティクラスに注釈を付けるために使用される、またはマップされたスーパークラスのプロパティまたはクラスのフィールドを埋め込むことができます(プロパティに表示されているとメソッドを取得することがあります)

デモショー

非機能方法にマーク

@Getter
@Setter
@ToString
public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String myName, int myAge) {
        this.name = myName;
        this.age = myAge;
    }
}

@RestController
@RequestMapping
public class HelloController {

    @ModelAttribute("myPersonAttr")
    public Person personModelAttr() {
        return new Person("非功能方法", 50);
    }

    @GetMapping("/testModelAttr")
    public void testModelAttr(Person person, ModelMap modelMap) {
        //System.out.println(modelMap.get("person")); // 若上面注解没有指定value值,就是类名首字母小写
        System.out.println(modelMap.get("myPersonAttr"));
    }
}

訪問:/testModelAttr?name=wo&age=10プリントアウト:

Person(name=wo, age=10)
Person(name=非功能方法, age=50)

あなたは、のパラメータを見ることができるPersonとしても、ラベルなしでオブジェクトを@ModelAttributeも正常値にカプセル化すること(そして、さらに内ModelMapの内側)。

空の構築物が作成されます何の注釈もありますのでPerson、その後のオブジェクトを、とは使用しないでServletRequestDataBinder.bind(ServletRequest request)データバインディングを完了するために、(もちろん、あなたも@Validを確認することができます)

:次の詳細があります
1、Person空の構造が存在しない場合でも、手段は@ConstructorProperties自動的にパッケージをも行うことができます

    // Person只有如下一个构造函数
    @ConstructorProperties({"name", "age"})
    public Person(String myName, int myAge) {
        this.name = myName;
        this.age = myAge;
    }

上記フルプリント。

図2は、上記の場合でも、@ConstructorProperties名前で書かれmyName、その結果はまだ正常なパッケージです。限り何もチェックがないのでbindingResult == null実行はまだだろうServletRequestDataBinder.bind(ServletRequest request)一度再パッケージが。追加しない限り@Valid、チェックを、それだけで使用します@ConstructorProperties(二〜を結合しない、一度パッケージを春にはあなたがオーバー@Validたと思うから、その後、港区では行っていません

図3は、トップコンストラクタにマークされていない場合でも@ConstructorPropertiesノート、まだ問題はありません。理由:BeanUtils.instantiateClass(ctor, args)ほとんどの引数はオブジェクト作成されている[null,null]聖歌、またものを与えられていない(そう注:あなたはint型であれば、それは~~基本的なパラメータエラーの友人です)

が4、@ModelAttribute書き込みと同じ効果を書いていません。これが書かれている場合でも@ModelAttribute("myPersonAttr") Person person、それが下に印刷されている値上記と同じ値に指定されています。

Person(name=wo, age=10)
Person(name=wo, age=10)

理由については、彼らは(記事の原則を参照)を説明する必要はありません。

:==も知っておく必要がある@ModelAttribute唯一の本方法では、現在のコントローラ用ラベル。あなたが使用している場合ただし、@ControllerAdviceコンポーネントを、それがグローバルです。(もちろん、指定することができbasePackages、その範囲を限定する- )==

上の標識関数(戻り値)のための方法で

このように、フォーム:

    @GetMapping("/testModelAttr")
    public @ModelAttribute Person testModelAttr(Person person, ModelMap modelMap) {
        ...
    }

この具体的な例を実行するには、それがより簡単です:モデルに値を返すメソッド。これらの値はに置かれていない、nullのリターンをその間隙に注意してください〜)

参照を標識する方法で

使用は複雑の原則が、私たちの最も使用される方法でなければなりませんが、ユーザーは、わずかに、まだ非常に簡単です。

そして、@RequestAttribute/ @SessionAttributeで使用されています

ボーエンを参照:Spring MVCので[学校]のレベルの原則から@ RequestAttribute、@ SessionAttributeの使用を習得タリアの協力はどんなアイデア、一般的に、問題を使用することは非常に滑らかではないではありません

そして、@SessionAttributes一緒に使用

@ModelAttributeそれは本質的に:私たちは、ターゲットメソッドを呼び出す前に、モデルデータを操作することができます@SessionAttributesそれは可能Modelセッションへの転送要求を複数との間の便利な値を同期データ(修飾)。
のは、ユースケースを通じて感じてみましょう:

@RestController
@RequestMapping
@SessionAttributes(names = {"name", "age"}, types = Person.class)
public class HelloController {

    @ModelAttribute
    public Person personModelAttr() {
        return new Person("非功能方法", 50);
    }

    @GetMapping("/testModelAttr")
    public void testModelAttr(HttpSession httpSession, ModelMap modelMap) {
        System.out.println(modelMap.get("person"));
        System.out.println(httpSession.getAttribute("person"));
    }
}

見るために@SessionAttributesの効果を、直接結果を確認するために行(同じセッション)で二度ここに訪問する私のブラウザを使用します。

最初の訪問の印刷:

Person(name=非功能方法, age=50)
null

印刷への第二の訪問:

Person(name=非功能方法, age=50)
Person(name=非功能方法, age=50)

私たちは見ることができます@ModelAttribute組み合わせが@SessionAttributes有効になります。具体的な理由については、ここでは会場の理解を助けることができます。マスターは春のMVCを学ぶために[まとめ]原則のレベルから(コア原則章)を使用@ModelAttribute

(重要)の次の例のバリエーションを見てください:

@RestController
@RequestMapping
@SessionAttributes(names = {"name", "age"}, types = Person.class)
public class HelloController {

    @GetMapping("/testModelAttr")
    public void testModelAttr(@ModelAttribute Person person, HttpSession httpSession, ModelMap modelMap) {
        System.out.println(modelMap.get("person"));
        System.out.println(httpSession.getAttribute("person"));
    }
}

訪問:/testModelAttr?name=wo&age=10誤ったレポート:

 org.springframework.web.HttpSessionRequiredException: Expected session attribute 'person'
    at org.springframework.web.method.annotation.ModelFactory.initModel(ModelFactory.java:117)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:869)

この間違いに注意を払うようにしてください:ときにこれは、誤解の使用に重点を置いて私の前にある@SessionAttributes@ModelAttribute一緒に使用し、間違いを犯す可能性が最も高いです。

以下のようなエラーコードの原因は以下のとおりです。

    public void initModel(NativeWebRequest request, ModelAndViewContainer container, HandlerMethod handlerMethod) throws Exception {
        Map<String, ?> sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request);
        container.mergeAttributes(sessionAttributes);
        invokeModelAttributeMethods(request, container);

        // 合并完sesson的属性,并且执行完成@ModelAttribute的方法后,会继续去检测
        // findSessionAttributeArguments:标注有@ModelAttribute的入参  并且isHandlerSessionAttribute()是SessionAttributts能够处理的类型的话
        // 那就必须给与赋值~~~~  注意是必须
        for (String name : findSessionAttributeArguments(handlerMethod)) {
            // 如果model里不存在这个属性(那就去sessionAttr里面找)
            // 这就是所谓的其实@ModelAttribute它是会深入到session里面去找的哦~~~不仅仅是request里
            if (!container.containsAttribute(name)) {
                Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
                
                // 倘若session里都没有找到,那就报错喽
                // 注意:它并不会自己创建出一个新对象出来,然后自己填值,这就是区别。
                // 至于Spring为什么这么设计 我觉得是值得思考一下子的
                if (value == null) {
                    throw new HttpSessionRequiredException("Expected session attribute '" + name + "'", name);
                }
                container.addAttribute(name, value);
            }
        }
    }

これがあることに注意initModel()しないと、エラーヨーヨーに時間resolveArgument()行います。この設計の春の意図?コントローラに表示されている:私は推測するベンチャー@SessionAttributesノート、あなたも上のパラメータを使用する場合@ModelAttribute、その後、あなたは間違いなく拘束取得したい、、何の手続きのエラーがあなたの問題ではない必要がある場合、あなたは例外をスローディスプレイは、トラブルシューティングに行くことを示しています。

共存制御の方法で、以下のように変更。

    @ModelAttribute
    public Person personModelAttr() {
        return new Person("非功能方法", 50);
    }

(以下、いくつかの訪問だけでなく、対応する印刷結果を遵守してください)
アクセス:/testModelAttr

Person(name=非功能方法, age=50)
null

次にアクセスしてください。/testModelAttr

Person(name=非功能方法, age=50)
Person(name=非功能方法, age=50)

アクセス:/testModelAttr?name=wo&age=10

Person(name=wo, age=10)
Person(name=wo, age=10)

注:この時点で、modelそしてsession値内部リクエスト・リンクの日のパラメータ値(各リクエストパラメータの値を使用します)に、OH、変更されています。

アクセス:/testModelAttr?age=11111

Person(name=wo, age=11111)
Person(name=wo, age=11111)

私たちは、それが行うことができます見ることができるのプロパティを変更するローカル

再びアクセス:/testModelAttr(要求なしパラメータ、等価のみ行う非機能法に)

Person(name=fsx, age=18)
Person(name=fsx, age=18)

これは見ることができたときmodelsessionどこ値はいない再び非機能的なアプローチになって@ModelAttribute変化し、これは重要な結論です。
ここではその基本原則:

    public void initModel(NativeWebRequest request, ModelAndViewContainer container, HandlerMethod handlerMethod) throws Exception {
        ...
        invokeModelAttributeMethods(request, container);
        ...
    }

    private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer container) throws Exception {
        while (!this.modelMethods.isEmpty()) {
            ...
            // 若model里已经存在此key 直接continue了
            if (container.containsAttribute(ann.name())) {
                ...
                continue;
            }
            // 执行方法
            Object returnValue = modelMethod.invokeForRequest(request, container);
            // 注意:这里只判断了不为void,因此即使你的returnValue=null也是会进来的
            if (!modelMethod.isVoid()){
                ...
                // 也是只有属性不存在 才会生效哦~~~~
                if (!container.containsAttribute(returnValueName)) {
                    container.addAttribute(returnValueName, returnValue);
                }
            }
        }
    }

だから、最終のために@ModelAttribute@SessionAttributes一緒に使用する場合結論づけ注意することが重要である:に追加されているsession使用中の無駄なデータSessionStatusオフクリアする前に、@ModelAttribute非機能的なアプローチは、戻り値をマークし、内部セッションに再び更新されることはありません

だから、@ModelAttributeSIHA〜小さな初期値を標識の非機能方法は、もちろん、あなたが手動でできることを意味SessionStatus明確にした後、それが発効します

概要

任意の技術は、最終的に利用されるように、紙を主に説明落ちる@ModelAttribute様々なユースケースの例を、だけでなく、それがあることを指摘@SessionAttributes一緒に使用するピット。
@ModelAttributeこの注釈は〜、また、最近の合衆国法典をもたらすために、実際の作業の助け小さなパートナーを持って来ることを期待して、最も重要な注意事項、花、したがって、より多くのスペースについて話しました、まだ比較的頻繁に使用すると、強力です

関連読書

【学校】スプリングMVCで使用HandlerMethod、InvocableHandlerMethod、ServletInvocableHandlerMethodを習得する原理レベルで
レベルの原理から@SessionAttributesの使用を習得[一緒に]春MVCを学ぶ
スプリングMVCを学習する[一緒に]使用のマスタ@ModelAttribute原理レベル(物品のコア原則)から

知識交換

==最後に:あなたはあなたにこの記事が参考に思われる場合は、賞賛の聖歌を指すように望むことができます。もちろん、友人のサークルは、より小さなパートナーも見ているので、共有する作者本人许可的~==を

技術内容に興味を持っている場合、グループWX交換に参加することができますJava高工、架构师3群
グループは、2次元コードを失敗した場合、WX番号を追加してください:fsx641385712(または2次元コードがWXの下でスキャンされます)。そして注:"java入群"単語は、手動でグループに招待されます

記事の場合格式混乱または图片裂开「ここをクリック:説明リンク-テキストリンク-テキストリンクを

おすすめ

転載: www.cnblogs.com/fangshixiang/p/11361061.html