コンピュータクワガタ

かっぱのかっぱによるコンピュータ関連のサイトです

Spring MVC 4.1 No. 034 form:passwordタグ

form:passwordタグは、HTMLの<input type="password">タグを生成します。

指定できる属性はshowPassword以外はform:inputと同じです。

その要素の内、単純にHTMLの属性に置き換えられるものは、以下の属性です。cssClassやcssStyleはそれぞれclass、style属性に置き換えられます。

属性 説明
accesskey HTML標準のaccesskey属性
alt HTML標準のalt属性
autocomplete HTML標準のautocomplete属性
cssClass HTML標準のclass属性
cssStyle HTML標準のsytle属性
dir HTML標準のdir属性
disabled HTML標準のdisabled属性
id HTML標準のid属性
lang HTML標準のlang属性
maxlength HTML標準のmaxlength属性
readonly HTML標準のreadonly属性
size HTML標準のsize属性
tabindex HTML標準のtabindex
title HTML標準のtitle属性

その他、JavaScriptのDOMレベル0イベントとして以下の属性が用意されています。それぞれ同名の属性になります。

属性
onblur
onchange
onclick
ondblclick
onfocus
onkeydown
onkeypress
onkeyup
onmousedown
onmousemove
onmouseout
onmouseover
onmouseup
onselect

残りがSpring用の属性になります。

属性 説明
cssErrorClass Validationのエラー時のclass属性
htmlEscape HTMLのエスケープをするかどうか。デフォルトはtrue
path 関連付けるModelの名前
showPassword パスワードを表示(value属性に出力)するか

コントローラで使う、Modelです。パスワードのみを格納します。

package com.example.spring.controller.c034;

public class C034Model {
    private String password;

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

サンプルのコントローラです。

package com.example.spring.controller.c034;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/c034")
public class C034Controller {
    @RequestMapping("/password")
    public String password(Model model) {
        C034Model c034Model = new C034Model();
        ;
        c034Model.setPassword("password");
        model.addAttribute("c034Model", c034Model);
        return "c034/password";
    }
}

コントローラではformで利用する値をModelに格納しています。

カスタムタグを使用しているJSPです。

<%@page contentType="text/html; charset=utf-8" %><%--
--%><!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>サンプル</title>
 </head>
 <body>
password: <form:password path="c034Model.password" /><br>
showPassword=true: <form:password path="c034Model.password" showPassword="true" /><br>
 </body>
</html>

showPasswordを設定しない場合にはpath属性の値は出力されません。逆にshowPasswordをtrueにするとvalueに値が出力されます。

ソースは https://github.com/kuwalab/spring-mvc41 にあります。タグ034が今回のサンプルです。

まとめ http://kuwalab.hatenablog.jp/entry/spring
最初 http://kuwalab.hatenablog.jp/entry/spring_mvc41/001
前回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/033
次回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/035

Spring MVC 4.1 No. 033 form:inputタグ

form:inputタグは、HTMLの<input type="text">タグを生成します。

その要素の内、単純にHTMLの属性に置き換えられるものは、以下の属性です。cssClassやcssStyleはそれぞれclass、style属性に置き換えられます。

属性 説明
accesskey HTML標準のaccesskey属性
alt HTML標準のalt属性
autocomplete HTML標準のautocomplete属性
cssClass HTML標準のclass属性
cssStyle HTML標準のsytle属性
dir HTML標準のdir属性
disabled HTML標準のdisabled属性
id HTML標準のid属性
lang HTML標準のlang属性
maxlength HTML標準のmaxlength属性
readonly HTML標準のreadonly属性
size HTML標準のsize属性
tabindex HTML標準のtabindex
title HTML標準のtitle属性

その他、JavaScriptのDOMレベル0イベントとして以下の属性が用意されています。それぞれ同名の属性になります。

属性
onblur
onchange
onclick
ondblclick
onfocus
onkeydown
onkeypress
onkeyup
onmousedown
onmousemove
onmouseout
onmouseover
onmouseup
onselect

残りがSpring用の属性になります。

属性 説明
cssErrorClass Validationのエラー時のclass属性
htmlEscape HTMLのエスケープをするかどうか。デフォルトはtrue
path 関連付けるModelの名前

コントローラで使用するモデルです。

package com.example.spring.controller.c033;

public class C033Model {
    private String name;
    private Integer price;
    private Integer listPrice;

    public C033Model(String name, Integer price, Integer listPrice) {
        this.name = name;
        this.price = price;
        this.listPrice = listPrice;
    }

    // setter、getterは省略
}

サンプルのコントローラです。

package com.example.spring.controller.c033;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/c033")
public class C033Controller {
    @RequestMapping("/input")
    public String input(Model model) {
        C033Model c033Model = new C033Model("よく分かるSpring<&>", 2000, 2500);
        model.addAttribute("c033Model", c033Model);
        return "c033/input";
    }
}

コントローラではformで利用する値をModelに格納しています。

カスタムタグを使用しているJSPです。

<%@page contentType="text/html; charset=utf-8" %><%--
--%><!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>サンプル</title>
 </head>
 <body>
書名: <form:input path="c033Model.name" size="20" /><br>
価格: <form:input path="c033Model.price" size="10" maxlength="6" readonly="true" /><br>
定価: <form:input path="c033Model.listPrice" size="10" disabled="true" /><br>
 </body>
</html>

path属性で、モデルの値とタグを関連付けます。Modelに設定されている値がformの初期値となります。

実際に動作させ、出力されるHTMLは以下のようになります。

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>サンプル</title>
 </head>
 <body>
書名: <input id="name" name="name" type="text" value="よく分かるSpring&lt;&amp;&gt;" size="20"/><br>
価格: <input id="price" name="price" readonly="readonly" type="text" value="2000" size="10" maxlength="6"/><br>
定価: <input id="listPrice" name="listPrice" disabled="disabled" type="text" value="2500" size="10"/><br>
 </body>
</html>

ソースは https://github.com/kuwalab/spring-mvc41 にあります。タグ033が今回のサンプルです。

まとめ http://kuwalab.hatenablog.jp/entry/spring
最初 http://kuwalab.hatenablog.jp/entry/spring_mvc41/001
前回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/032
次回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/034

Spring MVC 4.1 No. 032 CSVファイルのダウンロード4

ダウンロードの4つ目の方法はSpringらしい方法です。まず、spring-context.xmlにViewResolverの設定を追加します。処理する順番(order)を1にして最初に参照するようにします。

<bean id="xmlViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
 <property name="order" value="1" />
 <property name="location" value="/WEB-INF/spring/views.xml" />
</bean>

viewResolverで参照する設定ファイルのviews.xmlは次のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
 <bean id="c032Download" class="com.example.spring.controller.c032.C032DownloadView" />
</beans>

この例だと、viewの名前がc032Downloadの場合にC032DownloadView#renderMergedOutputModelが呼び出されます。そのC032DownloadViewクラスは次のとおりです。

package com.example.spring.controller.c032;

import java.io.PrintWriter;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.MimeTypeUtils;
import org.springframework.web.servlet.view.AbstractView;

public class C032DownloadView extends AbstractView {

    @SuppressWarnings("unchecked")
    @Override
    protected void renderMergedOutputModel(Map<String, Object> model,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        response.setContentType(MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE
                + ";charset=utf-8");

        response.setHeader("Content-Disposition",
                "attachment; filename=\"test.csv\"");
        try (PrintWriter pw = response.getWriter()) {
            for (C032Model c032Model : (List<C032Model>) model
                    .get("c032ModelList")) {
                pw.print(c032Model.getName());
                pw.print(",");
                pw.print(c032Model.getPrice());
                pw.print("\r\n");
            }
        }
    }
}

AbstractViewを継承し、renderMergedOutputModelメソッドを実装します。実装としてはこれまでどおりのCSVファイルを作成して出力しています。

ContollerとJSPはこれまでと大きく変わりません。

package com.example.spring.controller.c032;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class C032Controller {
    @RequestMapping("/c032/csvInit")
    public String csvInit() {
        return "c032/csvInit";
    }

    @RequestMapping("/c032/csvDown")
    public String csvDown4(Model model) {
        List<C032Model> c032ModelList = new ArrayList<>();

        C032Model c032Model = new C032Model();
        c032Model.setName("よくわかるSpring");
        c032Model.setPrice(3000);
        c032ModelList.add(c032Model);

        c032Model = new C032Model();
        c032Model.setName("よくわかるJava");
        c032Model.setPrice(2980);
        c032ModelList.add(c032Model);

        model.addAttribute("c032ModelList", c032ModelList);
        return "c032Download";
    }
}
package com.example.spring.controller.c032;

public class C032Model {
    private String name;
    private Integer price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }
}
<%@page contentType="text/html; charset=utf-8" %><%--
--%><!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>サンプル</title>
 </head>
 <body>
  <a href="csvDown">csvDown</a>
 </body>
</html>

確認用のテストケースは次のとおりです。

package com.example.spring.controller.c032;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/spring-context.xml" })
public class C032ControllerTest {
    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        mockMvc = webAppContextSetup(wac).build();
    }

    @Test
    public void csvInitのGET() throws Exception {
        mockMvc.perform(get("/c032/csvInit")).andExpect(status().isOk())
                .andExpect(view().name("c032/csvInit"));
    }

    @Test
    public void csvDownのGET() throws Exception {
        StringBuilder sb = new StringBuilder();
        sb.append("よくわかるSpring,3000\r\n");
        sb.append("よくわかるJava,2980\r\n");
        mockMvc.perform(get("/c032/csvDown"))
                .andExpect(status().isOk())
                .andExpect(view().name("c032Download"))
                .andExpect(
                        content().contentType(
                                "application/octet-stream;charset=utf-8"))
                .andExpect(content().string(sb.toString()));
    }
}

ソースは https://github.com/kuwalab/spring-mvc41 にあります。タグ032が今回のサンプルです。

まとめ http://kuwalab.hatenablog.jp/entry/spring
最初 http://kuwalab.hatenablog.jp/entry/spring_mvc41/001
前回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/031
次回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/033

Spring MVC 4.1 No. 031 RedirectAttribute

Springではリダイレクト時にリダイレクト先で参照できるRedirectAttributeを使用できます。

package com.example.spring.controller.c031;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
public class C031Controller {
    @RequestMapping("/c031/flashScope1")
    public String flashScope1(RedirectAttributes attrs, Model model) {
        attrs.addFlashAttribute("flash1", "flash1");
        model.addAttribute("request1", "request1");

        return "redirect:/c031/flashScope2";
    }

    @RequestMapping("/c031/flashScope2")
    public String flashScope2() {
        return "c031/flashScope";
    }
}

コントローラからJSPへ明示的にリダイレクトしています。

表示用のflashScope1.jspは以下のようになります。

<%@page contentType="text/html; charset=utf-8" %><%--
--%><!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>サンプル</title>
 </head>
 <body>
flash1: <c:out value="${flash1}" /><br>
request1: <c:out value="${request1}" />
 </body>
</html>

確認用のテストケースは次のとおりです。

package com.example.spring.controller.c031;

import static org.hamcrest.CoreMatchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/spring-context.xml" })
public class C031ControllerTest {
    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        mockMvc = webAppContextSetup(wac).build();
    }

    @Test
    public void requestScopeのGET() throws Exception {
        mockMvc.perform(get("/c031/flashScope1")).andExpect(status().isFound())
                .andExpect(redirectedUrl("/c031/flashScope2"))
                .andExpect(flash().attribute("flash1", "flash1"))
                .andExpect(request().attribute("request1", is(nullValue())));
    }
}

ソースは https://github.com/kuwalab/spring-mvc41 にあります。タグ031が今回のサンプルです。

まとめ http://kuwalab.hatenablog.jp/entry/spring
最初 http://kuwalab.hatenablog.jp/entry/spring_mvc41/001
前回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/030
次回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/032

Spring MVC 4.0 No. 030 コンポーネントをSessionスコープから破棄する

SpringのSessionスコープに格納したコンポーネントのうち、コントローラーに関連したものだけをクリアすることができます。セッションに格納する仕組み自体は前回のものと同様です。

まず、Sessionに置くコンポーネントを用意します。

package com.example.spring.controller.c030;

import java.io.Serializable;

import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;

@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class C030Model implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private Integer price;

    // setter、getterは省略
}

@Scopeアノテーションで、コンポーネントのスコープをSessionにします。また、Sessionスコープを利用する場合には、proxyMode属性を指定します。

次に、コントローラーです。

package com.example.spring.controller.c030;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;

@Controller
@RequestMapping("/c030")
@SessionAttributes("scopedTarget.c030Model")
public class C030Controller {
    @Autowired
    private C030Model c030Model;

    @RequestMapping("/sessionStart")
    public String sessionStart(Model model) {
        c030Model.setName("よくわかるHttpSession");
        c030Model.setPrice(980);
        model.addAttribute("c030Model", c030Model);
        return "c030/sessionScope";
    }

    @RequestMapping("/sessionScope")
    public String sessionScope(Model model) {
        model.addAttribute("c030Model", c030Model);
        return "c030/sessionScope";
    }

    @RequestMapping("/sessionClear")
    public String sesseionClear(Model model, SessionStatus sessionStatus) {
        sessionStatus.setComplete();
        model.addAttribute("c030Model", c030Model);
        return "c030/sessionScope";
    }
}

前回と異なるのは、sessionClearメソッドです。sessionClearメソッドではSessionStatusを引数に取り、setCompleteメソッドでクラスの@SessionAttributeで指定したコンポーネントのデータをクリアしています。@SessionAttributeで指定する名前は、"scopedTarget." + コンポーネント名になります。

表示用のsessionScope.jspは次のとおりです。セッションクリアへのリンクを追加しています。

<%@page contentType="text/html; charset=utf-8" %><%--
--%><!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>サンプル</title>
 </head>
 <body>
書名: <c:out value="${c030Model.name}" /><br>
価格: <c:out value="${c030Model.price}" /><br>
<a href="sessionScope">画面遷移</a><br>
<a href="sessionClear">セッションクリア</a>
 </body>
</html>

確認用のテストケースは次のとおりです。

package com.example.spring.controller.c030;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.ModelAndView;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/spring-context.xml" })
public class C030ControllerTest {
    @Autowired
    private WebApplicationContext wac;
    @Autowired
    private MockHttpSession mockHttpSession;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        mockMvc = webAppContextSetup(wac).build();
    }

    @Test
    public void sessionStartのGET() throws Exception {
        MvcResult mvcResult = mockMvc
                .perform(get("/c030/sessionStart").session(mockHttpSession))
                .andExpect(status().isOk())
                .andExpect(view().name("c030/sessionScope"))
                .andExpect(model().attributeExists("c030Model")).andReturn();
        checkC030Model(mvcResult);

        mvcResult = mockMvc
                .perform(get("/c030/sessionScope").session(mockHttpSession))
                .andExpect(status().isOk())
                .andExpect(view().name("c030/sessionScope"))
                .andExpect(model().attributeExists("c030Model")).andReturn();
        checkC030Model(mvcResult);

        mvcResult = mockMvc
                .perform(get("/c030/sessionClear").session(mockHttpSession))
                .andExpect(status().isOk())
                .andExpect(view().name("c030/sessionScope"))
                .andExpect(model().attributeExists("c030Model")).andReturn();
        ModelAndView mav = mvcResult.getModelAndView();
        Object c030ModelObject = mav.getModel().get("c030Model");
        assertThat(c030ModelObject, is(notNullValue()));
        assertThat(c030ModelObject, is(instanceOf(C030Model.class)));

        C030Model c030Model = (C030Model) c030ModelObject;
        assertThat(c030Model.getName(), is(nullValue()));
        assertThat(c030Model.getPrice(), is(nullValue()));
    }

    private void checkC030Model(MvcResult mvcResult) {
        // モデルデータの確認
        ModelAndView mav = mvcResult.getModelAndView();
        Object c030ModelObject = mav.getModel().get("c030Model");
        assertThat(c030ModelObject, is(notNullValue()));
        assertThat(c030ModelObject, is(instanceOf(C030Model.class)));

        C030Model c030Model = (C030Model) c030ModelObject;
        assertThat(c030Model.getName(), is("よくわかるHttpSession"));
        assertThat(c030Model.getPrice(), is(980));
    }
}


ソースは https://github.com/kuwalab/spring-mvc41 にあります。タグ030が今回のサンプルです。

まとめ http://kuwalab.hatenablog.jp/entry/spring
最初 http://kuwalab.hatenablog.jp/entry/spring_mvc41/001
前回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/029
次回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/031

Spring MVC 4.0 No. 029 コンポーネントをSessionスコープにする

SpringのコンポーネントをデフォルトのシングルトンからSessionに変更して、リクエストをまたいでコンポーネントを利用することができます。

まず、Sessionに置くコンポーネントを用意します。

package com.example.spring.controller.c029;

import java.io.Serializable;

import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;

@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class C029Model implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private Integer price;

    // getter、setterは省略
}

@Scopeアノテーションで、コンポーネントのスコープをSessionにします。また、Sessionスコープを利用する場合には、proxyMode属性を指定します。

次に、コントローラーです。

package com.example.spring.controller.c029;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/c029")
public class C029Controller {
    @Autowired
    private C029Model c029Model;

    @RequestMapping("/sessionStart")
    public String sessionStart(Model model) {
        c029Model.setName("よくわかるHttpSession");
        c029Model.setPrice(980);
        model.addAttribute("c029Model", c029Model);
        return "c029/sessionScope";
    }

    @RequestMapping("/sessionScope")
    public String sessionScope(Model model) {
        model.addAttribute("c029Model", c029Model);
        return "c029/sessionScope";
    }
}

コントローラーでは、C029Modelをインジェクションしています。

表示用のsessionScope.jspは次のとおりです。

<%@page contentType="text/html; charset=utf-8" %><%--
--%><!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>サンプル</title>
 </head>
 <body>
書名: <c:out value="${c029Model.name}" /><br>
価格: <c:out value="${c029Model.price}" /><br>
<a href="sessionScope">画面遷移</a>
 </body>
</html>

確認用のテストケースは次のとおりです。

package com.example.spring.controller.c029;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.ModelAndView;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {
 "file:src/main/webapp/WEB-INF/spring/spring-context.xml" })
public class C029ControllerTest {
    @Autowired
    private WebApplicationContext wac;
    @Autowired
    private MockHttpSession mockHttpSession;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        mockMvc = webAppContextSetup(wac).build();
    }

    @Test
    public void sessionStartのGET() throws Exception {
        MvcResult mvcResult = mockMvc
                .perform(get("/c029/sessionStart").session(mockHttpSession))
                .andExpect(status().isOk())
                .andExpect(view().name("c029/sessionScope"))
                .andExpect(model().attributeExists("c029Model")).andReturn();
        checkC029Model(mvcResult);

        mvcResult = mockMvc
                .perform(get("/c029/sessionScope").session(mockHttpSession))
                .andExpect(status().isOk())
                .andExpect(view().name("c029/sessionScope"))
                .andExpect(model().attributeExists("c029Model")).andReturn();
        checkC029Model(mvcResult);
    }

    private void checkC029Model(MvcResult mvcResult) {
        // モデルデータの確認
        ModelAndView mav = mvcResult.getModelAndView();
        Object c029ModelObject = mav.getModel().get("c029Model");
        assertThat(c029ModelObject, is(notNullValue()));
        assertThat(c029ModelObject, is(instanceOf(C029Model.class)));

        C029Model c029Model = (C029Model) c029ModelObject;
        assertThat(c029Model.getName(), is("よくわかるHttpSession"));
        assertThat(c029Model.getPrice(), is(980));
    }
}


ソースは https://github.com/kuwalab/spring-mvc41 にあります。タグ029が今回のサンプルです。

まとめ http://kuwalab.hatenablog.jp/entry/spring
最初 http://kuwalab.hatenablog.jp/entry/spring_mvc41/001
前回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/028
次回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/030

Spring MVC 4.1 No. 028 セッションスコープにデータを格納

セッションにデータを格納する方法もリクエスト同様に複数あります。Servlet APIのHttpSessionを使用する方法、WebRequestを使用する方法などです。

WebRequestはリクエストスコープと同様にデータを格納する際にスコープを指定します。

今回は同一の画面に遷移する3つのメソッドを用意しています。最初のものはセッションにデータを格納するもの、2番目は何もしないもの、3番目はセッションをクリアするものになります。

package com.example.spring.controller.c028;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.WebRequest;

@Controller
@RequestMapping("/c028")
public class C028Controller {
    @RequestMapping("/sessionStart")
    public String sessionScope1(HttpSession session, WebRequest webRequest) {
        session.setAttribute("session1", "httpSession");
        webRequest.setAttribute("session2", "webRequest",
                WebRequest.SCOPE_SESSION);

        return "c028/sessionScope";
    }

    @RequestMapping("/sessionScope")
    public String sessionScope2() {
        return "c028/sessionScope";
    }

    @RequestMapping("/sessionClear")
    public String sessionScope3(HttpSession session) {
        session.invalidate();
        return "c028/sessionScope";
    }
}

表示用のsessionScop.jspです。

<%@page contentType="text/html; charset=utf-8" %><%--
--%><!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>サンプル</title>
 </head>
 <body>
HttpSession: <c:out value="${sessionScope.session1}" /><br>
WebRequest: <c:out value="${sessionScope.session2}" /><br>
<a href="sessionScope">セッションをクリアせず再表示</a><br>
<a href="sessionClear">セッションをクリアして再表示</a>
 </body>
</html>

確認用のテストケースは次のとおりです。

package com.example.spring.controller.c028;

import static org.hamcrest.corematchers.*;
import static org.junit.Assert.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;

import java.util.UUID;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/spring-context.xml" })
public class C028ControllerTest {
    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;
    private MockHttpSession mockHttpSession;

    @Before
    public void setup() {
        mockMvc = webAppContextSetup(wac).build();
        mockHttpSession = new MockHttpSession(wac.getServletContext(), UUID
                .randomUUID().toString());
    }

    @Test
    public void requestScopeのGET() throws Exception {
        assertThat(mockHttpSession.getAttribute("session1"), is(nullValue()));
        assertThat(mockHttpSession.getAttribute("session2"), is(nullValue()));

        mockMvc.perform(get("/c028/sessionStart").session(mockHttpSession))
                .andExpect(status().isOk())
                .andExpect(view().name("c028/sessionScope"));
        assertThat(mockHttpSession.getAttribute("session1"), is("httpSession"));
        assertThat(mockHttpSession.getAttribute("session2"), is("webRequest"));

        // セッションは維持される
        mockMvc.perform(get("/c028/sessionScope").session(mockHttpSession))
                .andExpect(view().name("c028/sessionScope"));

        assertThat(mockHttpSession.getAttribute("session1"), is("httpSession"));
        assertThat(mockHttpSession.getAttribute("session2"), is("webRequest"));

        // セッションは破棄される
        mockMvc.perform(get("/c028/sessionClear").session(mockHttpSession))
                .andExpect(view().name("c028/sessionScope"));

        assertThat(mockHttpSession.isInvalid(), is(true));
    }
}

ソースは https://github.com/kuwalab/spring-mvc41 にあります。タグ028が今回のサンプルです。

まとめ http://kuwalab.hatenablog.jp/entry/spring
最初 http://kuwalab.hatenablog.jp/entry/spring_mvc41/001
前回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/027
次回 http://kuwalab.hatenablog.jp/entry/spring_mvc41/029