2013年1月8日 星期二

Struts2 StreamResult 免設定法

我們如果要用Struts2寫下載檔案的功能,不外乎使用StreamResult,在struts.xml中通常會設定類似以下的result:
代碼:
<result name="success" type="stream">
  <param name="contentType">image/jpeg</param>
  <param name="inputName">imageStream</param>
  <param name="contentDisposition">attachment;filename="document.pdf"</param>
  <param name="bufferSize">1024</param>
</result>
如果我們用Struts2 Convention Plugin的話,也會在Action class裡面設定類似的annotation:
代碼:
@Result(name="success", type="stream", params={"contentType", "image/jpeg", "inputName", "imageStream", "contentDisposition", "attachment;filename=\"document.pdf\"", "bufferSize", "1024"})
這樣其實很不方便,如果我們詳細去看org.apache.struts2.dispatcher.StreamResult的話,會發現其實在StreamResult裡面有個protected void resolveParamsFromStack(ValueStack stack, ActionInvocation invocation)方法,它會從ValueStack嘗試取得所有需要的變數,也就是說我們可以利用Action本身回傳StreamResult所需要的值,就可以免除一堆參數設定,也可以獲得動態設定的好處。 依此特性,我們訂一個interface給Action來implement,這樣只要Action execution時回傳值對應到的是StreamResult,那麼StreamResult就會自動再從Action抓到要的參數了。
StreamAction:
import java.io.InputStream;

/**
 * An action interface for org.apache.struts2.dispatcher.StreamResult.
 * 
 * @author linus_chien
 *
 */
public interface StreamAction {

    /**
     * @return content type.
     */
    String getContentType();
    
    /**
     * @return content length.
     */
    String getContentLength();
    
    /**
     * @return content disposition.
     */
    String getContentDisposition();
    
    /**
     * @return input name.
     */
    String getInputName();
    
    /**
     * @return buffer size.
     */
    int getBufferSize();
    
    /**
     * @return allow caching.
     */
    boolean getAllowCaching();
    
    /**
     * @return content char set.
     */
    String getContentCharSet();
    
    /**
     * @return inputstream.
     */
    InputStream getInputStream();
    
}
簡化後設定:
代碼:
<result name="success" type="stream"/>
@Result(name="success", type="stream")