SpringMVCのアーキテクチャを理解しようとしています。ただし、@ SessionAttributesの動作に完全に混乱しています。
以下のSampleControllerをご覧ください。SuperFormクラスによるpostメソッドを処理しています。実際、SuperFormクラスのフィールドだけが、私が期待したとおりにバインドされているだけです。
ただし、@ SessionAttributesをControllerに配置した後、処理メソッドはSubAFormとしてバインドされます。このバインディングで何が起こったのか誰かが私に説明できますか?.
-------------------------------------------------------
@Controller
@SessionAttributes("form")
@RequestMapping(value = "/sample")
public class SampleController {
@RequestMapping(method = RequestMethod.GET)
public String getCreateForm(Model model) {
model.addAttribute("form", new SubAForm());
return "sample/input";
}
@RequestMapping(method = RequestMethod.POST)
public String register(@ModelAttribute("form") SuperForm form, Model model) {
return "sample/input";
}
}
-------------------------------------------------------
public class SuperForm {
private Long superId;
public Long getSuperId() {
return superId;
}
public void setSuperId(Long superId) {
this.superId = superId;
}
}
-------------------------------------------------------
public class SubAForm extends SuperForm {
private Long subAId;
public Long getSubAId() {
return subAId;
}
public void setSubAId(Long subAId) {
this.subAId = subAId;
}
}
-------------------------------------------------------
<form:form modelAttribute="form" method="post">
<fieldset>
<legend>SUPER FIELD</legend>
<p>
SUPER ID:<form:input path="superId" />
</p>
</fieldset>
<fieldset>
<legend>SUB A FIELD</legend>
<p>
SUB A ID:<form:input path="subAId" />
</p>
</fieldset>
<p>
<input type="submit" value="register" />
</p>
</form:form>
POST
リクエストを処理するとき、Springは次のことを行います。
_@SessionAttributes
_なし:SpringはSuperForm
の新しいインスタンスをインスタンス化し(タイプはregister()
の署名から推測されます)、フォームフィールドからの値によってそのプロパティを設定し、それをに渡します。 register()
メソッド。
_@SessionAttributes
_の場合:Springはセッションからモデル属性のインスタンスを取得し(_@SessionAttributes
_が存在するためにGET
を処理するときに配置された場所)、fromフィールドの値によってプロパティを更新します。そしてそれをregister()
メソッドに渡します。
つまり、_@SessionAttributes
_を使用すると、register()
は、getCreateForm()
によってモデルに配置されたモデル属性オブジェクトの同じインスタンスを取得します。
@axtavtの発言に加えて、getCreateForm
にドロップダウン(リストまたはマップ)の値を入力するか、registerメソッドに必要な形式で値を入力するとします。それらをフォームで表示したくない(非表示のフィールドでも表示しない)。ここで、register
メソッドでエラーが発生し、フォームを再度表示する必要があるとします。ドロップダウン値や次の投稿で必要になるその他の値を入力するには、フォームに再入力する必要があります。 @SessionAttribute
は、@ axtavtが上で非常によく説明されているので、ここで役立ちます。
Springリファレンスドキュメントによると、@ModelAttribute
アノテーション付きメソッド引数は次のように解決されます。
@ModelAttribute
アノテーション付きメソッドを介して追加されます)@SessionAttributes
を使用してHTTPセッションから取得します。@ModelAttribute
名と一致するURIパス変数を使用して作成しますModel
に追加します。ハンドラークラスには、引数として名前のリストを使用して@SessionAttributes
で注釈を付けることができます。これは、@SessionAttributes
アノテーションで指定された名前と一致するモデルデータに存在するデータ項目を(セッションで)永続化するようにSpringに指示するためです。
したがって、SampleController
では、postメソッドの@ModelAttribute
引数は、上記の解決方法により、@SessionAttributes
フィールドで解決されます。
@Controller
@SessionAttributes("test")
public class Controller{
Customer customer;
public Controller() {
super();
customer = new Customer();
}
@ModelAttribute("test")
public Customer getCustomer() {
customer.setName("Savac");
return customer;
}
@RequestMapping({"/index"})
public ModelAndView showMainPage (@ModelAttribute("test") Customer customer, ModelMap model, method = RequestMethod.GET) {
//in the view you set the name
return new ModelAndView("index");
}
@RequestMapping(value = "customer/{customerID}", method = RequestMethod.GET)
public ModelAndView viewAdvice(@PathVariable("customerID") int customerID, @ModelAttribute("test") Customer customer, ModelMap model) {
customer.setName("AnotherName");
model.addAttribute("test", customer);
return new ModelAndView("customer");
}
}