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
沒有留言:
張貼留言
你好!歡迎你在我的 Blog 上留下你寶貴的意見。