Spring WebMVCをやってみる (12) - RedirectAttributes -

2013-12-20T00:00:00+00:00 Java Spring Framework

んまぁ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な模様

Spring WebMVCをやってみる (13) - @ValidとBindingResult - Spring WebMVCをやってみる (11) - @RequestMappingのparams -