Spring WebMVCをやってみる (3) - 返せるレスポンスタイプに関して -
大まかにSpring WebMVCでコントローラーアクション(@RequestMappingで処理されるメソッド)で返せる値の形式は
- String (redirect/forward等のプレフィックスも含む)
- ModelAndView
- Map<String, Object>
- String、又はbyte[]等で@ResponseBodyなアノテーションを付与
- ResponseEntityを使用
- org.springframework.web.servlet.Viewを使用
っていうような感じで値を返す事が出来る。もちろん値を返さないvoidでも引数にHttpServletResponseを利用してレスポンスを出す事も可能
ModelAndViewはSpring WebMVCをやってみる (2) – アノテーションを使わないコントローラー -で既に検証済みなので省略する。又、最後のViewに関しては後日別途で記事を書く予定になっているので今回は省略する。という事でコントローラー書いてテスト書いて検証してみる
SampleController.java
package sample;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/sample")
public class SampleController {
// Mapで返した場合にはそれに含まれているパラメーターがビューとなるJSP等で参照可能(例えば以下だと${data})
@RequestMapping("/test1")
public Map<String, Object> test(HttpServletResponse response) throws Exception{
Map<String, Object> data = new HashMap<String, Object>();
data.put("data", "hoge");
return data;
}
@RequestMapping("/test2")
@ResponseBody
public String test2() {
return "hoge";
}
@RequestMapping("/test3")
public ResponseEntity<String> test3() {
return new ResponseEntity<String>("hoge", HttpStatus.OK);
}
@RequestMapping("/test4")
public String test4() {
return "redirect:/sample/test3";
}
@RequestMapping("/test5")
@ResponseBody
public byte[] test5() {
return "hoge".getBytes();
}
}
んまぁあとはテスト書いて
SampleControllerTest.java
package swmvc;
import java.util.Map;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.web.servlet.ModelAndView;
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 test1_Mapでパラメーターを返す() throws Exception {
MvcResult result = mock.perform(get("/sample/test1"))
.andExpect(request().attribute("data", notNullValue()))
.andExpect(request().attribute("data", is("hoge")))
.andReturn();
MockHttpServletResponse response = result.getResponse();
assertThat(response, notNullValue());
assertThat(response.getStatus(), is(200));
ModelAndView model = result.getModelAndView();
assertThat(model, notNullValue());
Map<String, Object> values = model.getModel();
assertThat(values, notNullValue());
assertThat(values, hasKey("data"));
assertThat(values.get("data").toString(), is("hoge"));
}
@Test
public void test2_ResponseBodyでStringを返す() throws Exception {
MvcResult result = mock.perform(get("/sample/test2"))
.andExpect(content().string("hoge"))
.andReturn();
MockHttpServletResponse response = result.getResponse();
assertThat(response, notNullValue());
assertThat(response.getStatus(), is(200));
assertThat(response.getContentAsString(), is("hoge"));
}
@Test
public void test3_ResponseEntityを返す() throws Exception {
MvcResult result = mock.perform(get("/sample/test3"))
.andExpect(content().string("hoge"))
.andReturn();
MockHttpServletResponse response = result.getResponse();
assertThat(response, notNullValue());
assertThat(response.getStatus(), is(200));
assertThat(response.getContentAsString(), is("hoge"));
}
@Test
public void test4_redirectプレフィックスを使う() throws Exception {
int actualStatus = 302;
MvcResult result = mock.perform(get("/sample/test4"))
.andExpect(status().is(actualStatus))
.andExpect(redirectedUrl("/sample/test3"))
.andReturn();
MockHttpServletResponse response = result.getResponse();
assertThat(response, notNullValue());
assertThat(response.getStatus(), is(actualStatus));
assertThat(response.getRedirectedUrl(), is("/sample/test3"));
}
@Test
public void test5_ResponseBodyでbyteアレイを返す() throws Exception {
MvcResult result = mock.perform(get("/sample/test5"))
.andExpect(content().bytes("hoge".getBytes()))
.andReturn();
MockHttpServletResponse response = result.getResponse();
assertThat(response, notNullValue());
assertThat(response.getStatus(), is(200));
assertThat(response.getContentAsString(), is("hoge"));
assertThat(response.getContentAsByteArray(), is("hoge".getBytes()));
}
}
んまぁまだまだ色々ありそうだけど、とりまぁ現時点でのメモ。追記するかも
追記1: 引数にModelMapを利用する
package sample;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/sample")
public class SampleController {
@RequestMapping("/test/{message}")
public String test(@PathVariable String message, ModelMap model) {
model.addAttribute("data", message.toUpperCase());
return "test";
}
}
っていう感じでも良い。ModelMapに入れられたデータ自体はJSP等でもEL式を用いて参照する事が可能な模様。ちなみにこの場合のテストは
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 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/test/hoge"))
.andExpect(model().attributeExists("data"))
.andExpect(model().attribute("data", is("HOGE")))
.andReturn();
ModelAndView mav = result.getModelAndView();
assertThat(mav, notNullValue());
ModelMap model = mav.getModelMap();
assertThat(model, hasKey("data"));
assertThat(model.get("data").toString(), is("HOGE"));
}
}
っていう感じかと