Response
並且替換 PrintWriter
,這樣才有辦法取得執行後的內容。接著可以從 Spring 的
ViewResolver
去取得 View
,再透過 View
去處理 render 前的包裝,最後才由 dispatcher 真正去處理 render 的動作。 想到要建立 Request 跟 Response 就感覺讓人頭痛,還好 Spring 有提供 Mock 的類別可以簡單地去建立 Request 跟 Response。
JspRenderer
package com.orion.webmvc.util; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.util.Locale; import java.util.Map; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.ui.Model; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; public class JspRenderer { @Autowired private ServletContext servletContext; private ViewResolver viewResolver; public void setViewResolver(ViewResolver viewResolver) { this.viewResolver = viewResolver; } public String render(String viewName, Model model) throws IOException { return render(viewName, model.asMap()); } public String render(String viewName, Map<String,Object> modelMap) throws IOException { RendererRequest request = new RendererRequest(servletContext); RendererResponse response = new RendererResponse(); try { /* 透過 ViewResolver 取得 View 進行 render 的動作 */ View view = viewResolver.resolveViewName( viewName, Locale.getDefault() ); view.render(modelMap, request, response); return response.getContentAsString(); } catch(Exception e) { throw new IOException(e); } } } class RendererRequest extends MockHttpServletRequest { private ServletContext servletContext; public RendererRequest(ServletContext servletContext) { this.servletContext = servletContext; } @Override public RequestDispatcher getRequestDispatcher(String path) { /* 需要透過真實的 RequestDispatcher 進行 Render */ return servletContext.getRequestDispatcher(path); } } class RendererResponse extends MockHttpServletResponse { private StringWriter writer = new StringWriter(); @Override public PrintWriter getWriter() throws UnsupportedEncodingException { /* 用 StringWriter 作為輸出的容器 */ return new PrintWriter(writer); } @Override public boolean isCommitted() { /* true 是為了讓 View 可以採用 include 方式 Render 到 Response */ return true; } @Override public String getContentAsString() throws UnsupportedEncodingException { /* 取得 Render 後的內容 */ return writer.getBuffer().toString(); } }
配置 spring.xml
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> <bean id="jspRenderer" class="com.orion.webmvc.util.JspRenderer"> <property name="viewResolver" ref="viewResolver"/> </bean>
使用範例
//@Autowired //private JspRenderer jspRenderer; Map<String,Object> jspMap = new HashMap<String,Object>(); jspMap.put("jspMessage", "中文訊息測試"); jspMap.put("costMessage", 4567.89); String jspOutput = jspRenderer.render("/mailer/test", jspMap); System.out.println(jspOutput);
參考自:Render and capture the output of a JSP as a String | Technological Oddity
0 回應:
張貼留言