2015-03-05 10:24

用 Spring 取得 JSP 執行後的字串內容

為了取得執行後的字串內容,我們需要建立 Response 並且替換 PrintWriter,這樣才有辦法取得執行後的內容。

接著可以從 Spring 的 ViewResolver 去取得 View,再透過 View 去處理 render 前的包裝,最後才由 dispatcher 真正去處理 render 的動作。

想到要建立 Request 跟 Response 就感覺讓人頭痛,還好 Spring 有提供 Mock 的類別可以簡單地去建立 Request 跟 Response。


JspRenderer

  1. package com.orion.webmvc.util; 
  2.  
  3. import java.io.IOException; 
  4. import java.io.PrintWriter; 
  5. import java.io.StringWriter; 
  6. import java.io.UnsupportedEncodingException; 
  7. import java.util.Locale; 
  8. import java.util.Map; 
  9.  
  10. import javax.servlet.RequestDispatcher; 
  11. import javax.servlet.ServletContext; 
  12.  
  13. import org.springframework.beans.factory.annotation.Autowired; 
  14. import org.springframework.mock.web.MockHttpServletRequest; 
  15. import org.springframework.mock.web.MockHttpServletResponse; 
  16. import org.springframework.ui.Model; 
  17. import org.springframework.web.servlet.View; 
  18. import org.springframework.web.servlet.ViewResolver; 
  19.  
  20.  
  21. public class JspRenderer { 
  22.  
  23.    @Autowired 
  24.    private ServletContext servletContext; 
  25.  
  26.  
  27.    private ViewResolver viewResolver; 
  28.  
  29.    public void setViewResolver(ViewResolver viewResolver) { 
  30.        this.viewResolver = viewResolver; 
  31.    } 
  32.  
  33.  
  34.    public String render(String viewName, Model model)  
  35.        throws IOException  
  36.    { 
  37.        return render(viewName, model.asMap()); 
  38.    } 
  39.  
  40.    public String render(String viewName, Map<String,Object> modelMap)  
  41.        throws IOException  
  42.    { 
  43.  
  44.        RendererRequest request = new RendererRequest(servletContext); 
  45.        RendererResponse response = new RendererResponse(); 
  46.  
  47.        try { 
  48.            /* 透過 ViewResolver 取得 View 進行 render 的動作 */ 
  49.            View view = viewResolver.resolveViewName( 
  50.                viewName, Locale.getDefault() 
  51.            ); 
  52.            view.render(modelMap, request, response); 
  53.  
  54.            return response.getContentAsString(); 
  55.        } 
  56.        catch(Exception e) { 
  57.            throw new IOException(e); 
  58.        } 
  59.    } 
  60. } 
  61.  
  62.  
  63. class RendererRequest extends MockHttpServletRequest { 
  64.  
  65.    private ServletContext servletContext; 
  66.  
  67.    public RendererRequest(ServletContext servletContext) { 
  68.        this.servletContext = servletContext; 
  69.    } 
  70.  
  71.    @Override 
  72.    public RequestDispatcher getRequestDispatcher(String path) { 
  73.        /* 需要透過真實的 RequestDispatcher 進行 Render */ 
  74.        return servletContext.getRequestDispatcher(path); 
  75.    } 
  76. } 
  77.  
  78.  
  79. class RendererResponse extends MockHttpServletResponse { 
  80.  
  81.    private StringWriter writer = new StringWriter(); 
  82.  
  83.    @Override 
  84.    public PrintWriter getWriter() throws UnsupportedEncodingException { 
  85.        /* 用 StringWriter 作為輸出的容器 */ 
  86.        return new PrintWriter(writer); 
  87.    } 
  88.  
  89.    @Override 
  90.    public boolean isCommitted() { 
  91.        /* true 是為了讓 View 可以採用 include 方式 Render 到 Response */ 
  92.        return true; 
  93.    } 
  94.  
  95.    @Override 
  96.    public String getContentAsString() throws UnsupportedEncodingException { 
  97.        /* 取得 Render 後的內容 */ 
  98.        return writer.getBuffer().toString(); 
  99.    } 
  100. } 


配置 spring.xml

  1. <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
  2.    <property name="prefix" value="/WEB-INF/views/" /> 
  3.    <property name="suffix" value=".jsp" /> 
  4. </bean> 
  5.  
  6. <bean id="jspRenderer" class="com.orion.webmvc.util.JspRenderer"> 
  7.    <property name="viewResolver" ref="viewResolver"/> 
  8. </bean> 


使用範例

  1. //@Autowired 
  2. //private JspRenderer jspRenderer; 
  3.  
  4. Map<String,Object> jspMap = new HashMap<String,Object>(); 
  5. jspMap.put("jspMessage", "中文訊息測試"); 
  6. jspMap.put("costMessage", 4567.89); 
  7.  
  8. String jspOutput = jspRenderer.render("/mailer/test", jspMap); 
  9. System.out.println(jspOutput); 


參考自:Render and capture the output of a JSP as a String | Technological Oddity

0 回應: