Spring WebMVCをやってみる (8) - @ModelAttribute -
リクエストパラメーターとかからJavaBeanとなるオブジェクトを引数にマッピング出来たりだとか、ModelAndViewで使用するモデルを初期化したりする事も出来る模様
例えば
- /sample/{id}/edit.actionで編集画面を出す
- /sample/{id}/update.actionで編集内容をコミット
っていうようなケースとの場合にidから紐付けられるオブジェクトをデータベース等から取り出して利用するような要件がある場合にはそのリクエストに応じてオブジェクトを取り出すような仕組みとかを利用できるのではと
まぁわけわかになりそうな気もしなくも無いのでやってみる
SampleController.java
package sample;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/sample/{id}")
public class SampleController {
@ModelAttribute("sample")
public Sample bindSample(@PathVariable Integer id) {
// idから特定出来るオブジェクトを返せば良い
Sample sample = new Sample();
sample.setId(id);
sample.setName("hoge");
return sample;
}
@RequestMapping("/edit")
public String edit() {
return "edit";
}
@RequestMapping(value = "/update", method = RequestMethod.POST)
@ResponseBody
public String update(@ModelAttribute Sample sample) {
return sample.toString();
}
}
っていうように@ModelAttributeなアノテーションがついてるのが2箇所
- メソッドについてる@ModelAttributeでModelAndView等?で使用するパラメーターを埋め込む事が可能?
- 引数についてる@ModelAttributeでリクエストパラメーターに応じたオブジェクトをセッターメソッドを介して値を設定したオブジェクトが指定される?
的な感じなのではと。メソッドについてるアノテーションの場合は今回は@PathVariableを利用しているが、@RequestParam等でも利用できる
んじゃテスト書こう
SampleControllerTest.java
package swmvc;
import org.junit.Test;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.ui.ModelMap;
import org.springframework.web.servlet.ModelAndView;
import sample.Sample;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
public class SampleControllerTest extends AbstractTestCase {
@Test
public void test() throws Exception {
MvcResult result = mock.perform(get("/sample/1/edit"))
.andExpect(status().isOk())
.andExpect(model().attributeExists("sample"))
.andExpect(model().attribute("sample", instanceOf(Sample.class)))
.andReturn();
ModelAndView mav = result.getModelAndView();
assertThat(mav, notNullValue());
ModelMap model = mav.getModelMap();
assertThat(model, notNullValue());
assertThat(model, hasKey("sample"));
Sample sample = (Sample)model.get("sample");
assertThat(sample, notNullValue());
assertThat(sample.getId(), is(1));
assertThat(sample.getName(), is("hoge"));
}
@Test
public void say() throws Exception {
mock.perform(post("/sample/2/update").param("name", "hoge"))
.andExpect(status().isOk())
.andExpect(content().string(is("2 -> hoge")))
.andReturn();
}
}
んな感じ。メソッドについてるアノテーションでModelAndViewに指定されたオブジェクトがputされて、updateメソッド時にはリクエストパラメーターに応じて引数に指定されたオブジェクトが注入される的な感じかと。多分パラメーターとかが無い時は引数がnullにはならずインスタンスだけ生成された形になる。そこら辺はフォーム検証的な所でやると思うのでとりあえず今回はパス
っていうような感じで。