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