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 回應:
張貼留言