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