SpringMVCで@ModelAttributeアノテーションを使用する方法

SpringMVCで@ModelAttributeアノテーションを使用する方法

以下は「SpringMVCでデータ送信(POST)する 」で作成したコントローラです。

@ModelAttributeを使っていませんがmodel.addAttribute~でアクションフォームのインスタンスを格納していました。

package jp.co.confrage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("sample")
public class HomeController {

  private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

  @RequestMapping(value = "home", method = RequestMethod.GET)
  public String home(Model model) {
    logger.info("Welcome Sample Page.");
    model.addAttribute(new HomeForm());
    return "home";
  }
}

homeメソッドの引数にアクションフォームを変更し、model.addAttribute~の行をコメントアウトします。

package jp.co.confrage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("sample")
public class HomeController {

  private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

  @RequestMapping(value = "home", method = RequestMethod.GET)
  public String home(Model model,HomeForm form) {
    logger.info("Welcome Sample Page.");
    //        model.addAttribute(new HomeForm());
    return "home";
  }
}

引数で指定することで、明示的にmodel.addAttributeする必要がなくなります。

裏で、model.addAttribute(new HomeForm());が実行されているようなイメージです。

※model.addAttribute(“homeForm”,new HomeForm());と同じ

JSP側はなにも変更せずに、modelAttribute属性にはhomeFormを指定しています。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Home</title>
</head>
<body>
<h1>
Hello world!
</h1>

<P> Welcome Sample Page. </P>
<spring:url value="/sample/post" var="action" />
<form:form action="${action}" method="post" modelAttribute="homeForm">
<form:label path="keyword">入力›</form:label>
<form:input path="keyword" />
<form:errors path="keyword" cssStyle="color:red" />
<input type="submit" value="送信" />
</form:form>
</body>
</html>

では@ModelAttributeアノテーションを使用してみます。引数の前に記述します。

package jp.co.confrage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("sample")
public class HomeController {

  private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

  @RequestMapping(value = "home", method = RequestMethod.GET)
  public String home(Model model,@ModelAttribute("aForm")HomeForm form) {
    logger.info("Welcome Sample Page.");

    //        model.addAttribute(new HomeForm());

    return "home";
  }
}

このままだと「Neither BindingResult nor plain target object for bean name ‘homeForm’ available as request attribute」とJSP側でエラーが出るので、modelAttribute属性にaFormと記述します。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Home</title>
</head>
<body>
<h1>
Hello world!
</h1>

<P> Welcome Sample Page. </P>
<spring:url value="/sample/post" var="action" />
<form:form action="${action}" method="post" modelAttribute="aForm">
<form:label path="keyword">入力›</form:label>
<form:input path="keyword" />
<form:errors path="keyword" cssStyle="color:red" />
<input type="submit" value="送信" />
</form:form>
</body>
</html>

これで属性名を変更して正常に動作します。

メソッドに対して@ModelAttributeアノテーションを指定できる

@ModelAttributeアノテーションをメソッドの上に指定するとまた意味合いが違ってきます。

package jp.co.confrage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("sample")
public class HomeController {

  private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
  @AutoWired
  HomeForm bean; // フォームの値を入れたいなら@AutoWiredでDIする
  @RequestMapping(value = "home", method = RequestMethod.GET)
  public String home(HomeForm hf) { // 引数に指定してあげることでセッターが呼ばれる
    logger.info("Welcome Sample Page.");
    return "home";
  }
  @ModelAttribute
  public HomeForm setForm(){ // メソッド名は何でもよい
    return this.bean;
  }
}

setFormメソッドが実行されインスタンスが返されます。その次にhomeメソッドが実行されて、これも正常に動作します。

この時、JSP側のmodelAttribute属性にはhomeFormを指定すること(アクションフォーム(ビーン)クラスのキャメルケースにしておく必要がある)

@ModelAttributeアノテーションの役割とは

上記のとおり、@ModelAttributeアノテーションでjspとアクションフォーム(ビーンって言えばわかりやすい?)の指定した別名で連携をするだけのアノテーションです。

SpringMVCで@ModelAttributeアノテーションを使用する

コメント

タイトルとURLをコピーしました