Spring WebMVCをやってみる (12) - RedirectAttributes -
んまぁSpring WebMVCでアクションからリダイレクトを利用したい場合等にはredirect:なプレフィックスを利用する事で出来るんだけれども
- リダイレクト先にパラメーターを設置したい (リダイレクト先で@RequestParam)
- フラッシュスコープを利用してリダイレクトしたい
っていう要件を検証してみた
パターン1: リダイレクト先にパラメーターを指定してリダイレクト
package sample;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller
@RequestMapping("/sample")
public class SampleController {
@RequestMapping
public String index(RedirectAttributes attributes) {
attributes.addAttribute("message", "hoge");
return "redirect:/sample/show.action";
}
@RequestMapping("/show")
@ResponseBody
public String show(@RequestParam("message") String message) {
return message;
}
}
はい、終わり。RedirectAttributesを引数に持つメソッドを定義、それはパターン2でも変わらないのですが使うメソッドが違うだけ(リダイレクト先のメソッドの引数も異なる)
package swmvc;
import org.junit.Test;
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_index() throws Exception {
mock.perform(get("/sample"))
.andExpect(status().isFound())
.andExpect(redirectedUrl("/sample/show.action?message=hoge"));
}
}
っていうテストになる
パターン2: フラッシュスコープを利用してリダイレクト
package sample;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller
@RequestMapping("/sample")
public class SampleController {
@RequestMapping
public String index(RedirectAttributes attributes) {
attributes.addFlashAttribute("message", "hoge");
return "redirect:/sample/show.action";
}
@RequestMapping("/show")
@ResponseBody
public String show(ModelMap model) {
String message = (String)model.get("message");
return message;
}
}
addFlashAttributeで突っ込んで、リダイレクト先のModelMapから取る。でリロードするとそのフラッシュスコープは既に存在しないので参照できない
package swmvc;
import org.junit.Test;
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_index() throws Exception {
mock.perform(get("/sample"))
.andExpect(status().isFound())
.andExpect(redirectedUrl("/sample/show.action"))
.andExpect(flash().attributeExists("message"))
.andExpect(flash().attribute("message", is("hoge")));
}
@Test
public void test_show() throws Exception {
mock.perform(get("/sample/show").flashAttr("message", "hoge"))
.andExpect(status().isOk())
.andExpect(content().string(is("hoge")));
}
}
みたいにテスト
んまぁリダイレクトを利用する場合にはRedirectAttributesを使えばパラメーターとかの追加とかわざわざリダイレクト先の文字列を結合したりとかしなくても良いんじゃないかと
余談: redirectHttp10Compatible
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<context:component-scan base-package="sample" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="viewResolvers">
<list>
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
<property name="order" value="1" />
<property name="redirectHttp10Compatible" value="false" />
</bean>
</list>
</property>
</bean>
</beans>
みたいにredirectHttp10Compatibleを設定するとレスポンスステータスコードがHTTP FOUND(302)からHTTP SEE OTHER(303)のようになる模様
ちなみにそのリダイレクトな処理をしている実体なクラスはorg.springframework.web.servlet.view.RedirectViewな模様