在struts2中添加自定义的result的type类型,只需要两步即可在应用中使用了,首先编写自定义类型的类,然后在struts.xml中进行注册即可,若自定义类型带有重定向性质时,就涉及到参数的传递,可参考ServletActionRedirectResult(org.apache.struts2.dispatcher)类,具体可参阅OGNL、ValueStack相关内容。
1、编写自定义类型的处理类package com.csmn.base.action;import java.io.File;import java.io.OutputStream;import java.io.StringWriter;import java.io.UnsupportedEncodingException;import java.util.Arrays;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;import java.util.Map.Entry;import javax.servlet.RequestDispatcher;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.jsp.PageContext;import org.apache.commons.lang.exception.ExceptionUtils;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.struts2.ServletActionContext;import org.apache.struts2.dispatcher.StrutsResultSupport;import org.apache.struts2.views.util.UrlHelper;import org.xhtmlrenderer.pdf.ITextFontResolver;import org.xhtmlrenderer.pdf.ITextRenderer;import com.lowagie.text.pdf.BaseFont;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.config.entities.ResultConfig;import com.opensymphony.xwork2.util.TextParseUtil;/** ** PdfResult類主要用於-导出到PDF. *
** 創建時間 2013-12-7 - 下午08:05:52 *
***歷史修改記錄
**
*- 城邑耕夫 2017-02-02 添加动态参数传递(主要用于处理文件名) *
* copyright cdthgk 2010-2013, all rights reserved. *
* * @author 車水碼農 * @author cdthgk r&d * @since 1.0 * @version 1.0 */public class PdfResult extends StrutsResultSupport { private static final long serialVersionUID = -6588129708854890330L; private static final Log log = LogFactory.getLog(PdfResult.class); public PdfResult() { super(); init(); } public PdfResult(String location) { super(location); init(); } /** * Dispatches to the given location. Does its forward via a * RequestDispatcher. If the dispatch fails a 404 error will be sent back in * the http response. * * @param finalLocation * the location to dispatch to. * @param invocation * the execution state of the action * @throws Exception * if an error occurs. If the dispatch fails the error will go * back via the HTTP request. */ public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception { log.debug("Forwarding to location " + finalLocation); PageContext pageContext = ServletActionContext.getPageContext(); if (pageContext != null) { pageContext.include(finalLocation); } else { HttpServletRequest request = ServletActionContext.getRequest(); HttpServletResponse response = ServletActionContext.getResponse(); RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation); // if the view doesn't exist, let's do a 404 if (dispatcher == null) { response.sendError(404, "result '" + finalLocation + "' not found"); return; } //[ StringWriter sw = new StringWriter(); HttpResponseWrapper rw = new HttpResponseWrapper(response, sw); //] // If we're included, then include the view // Otherwise do forward // This allow the page to, for example, set content type if (!response.isCommitted() && (request.getAttribute("javax.servlet.include.servlet_path") == null)) { request.setAttribute("struts.view_uri", finalLocation); request.setAttribute("struts.request_uri", request.getRequestURI()); // 处理参数 ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(invocation.getResultCode()); if (resultConfig != null ) { MapresultConfigParams = resultConfig.getParams(); for (Iterator > i = resultConfigParams.entrySet().iterator(); i.hasNext();) { Map.Entry e = i.next(); String param = e.getKey().toString(); if (!getProhibitedResultParams().contains(param)) { String potentialValue = (e.getValue() == null ? "" : conditionalParse(e.getValue().toString(), invocation)); requestParameters.put(param, potentialValue); } } } StringBuilder tmpLocation = new StringBuilder(finalLocation); UrlHelper.buildParametersString(requestParameters, tmpLocation, "&"); finalLocation = response.encodeRedirectURL(tmpLocation.toString()); dispatcher.forward(request, rw); } else { dispatcher.include(request, rw); } rw.getWriter().close(); // pdf文件内容// log.debug(sw.toString()); // 通过ValueStack处理后的文件名,再编码 fileName = new String(requestParameters.get("fileName").getBytes(),"ISO8859-1"); ITextRenderer renderer = new ITextRenderer(); renderer.setDocumentFromString(sw.toString()); if (request.getHeader("User-Agent").indexOf("MSIE 5.5") != -1) { response.setHeader("Content-Disposition", "filename=" + fileName); } else { response.setHeader("Content-disposition", "attachment;filename=" + fileName); } response.setHeader("Content-Type", "application/octet-stream;charset=ISO8859-1"); // 解决中文支持问题 ITextFontResolver fontResolver = renderer.getFontResolver(); fontResolver.addFont(new File(this.getClass().getResource("SIMSUN.TTC").getFile()).getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // 解决图片的相对路径问题 //renderer.getSharedContext().setBaseURL("file:/E:/workspace/eclipse_utf-8_workspace/PdfTest/src/flyingsaucer/start/"); renderer.layout(); OutputStream os = response.getOutputStream(); renderer.createPDF(os); os.close(); } } // ******************************************************************** // private & protected // ******************************************************************** private void init(){ try { this.fileName = new String("未命名文件.pdf".getBytes(),"ISO8859-1"); } catch (UnsupportedEncodingException e) { log.debug(ExceptionUtils.getStackTrace(e)); this.fileName = new String("未命名文件.pdf"); } } protected List getProhibitedResultParams() { return Arrays.asList(new String[]{ DEFAULT_PARAM, "namespace", "method", "encode", "parse", "location", "prependServletContext", "supressEmptyParameters"}); } protected String conditionalParse(String param, ActionInvocation invocation) { if (param != null && invocation != null) { String finalValue = TextParseUtil.translateVariables(param, invocation.getStack()); log.debug(param + "通过值栈解析后的参数:" + finalValue); return finalValue; } else { return param; } } // ******************************************************************** // setter and getter // ******************************************************************** private String fileName; protected Map requestParameters = new LinkedHashMap (); public String getFileName() { return fileName; } public void setFileName(String fileName) { try { this.fileName = new String(fileName.getBytes(),"ISO8859-1"); } catch (UnsupportedEncodingException e) { this.fileName = fileName; log.debug(ExceptionUtils.getStackTrace(e)); } } public Map getRequestParameters() { return requestParameters; } public void setRequestParameters(Map requestParameters) { this.requestParameters = requestParameters; }}
2、在struts.xml中注册自定义类型
…… …… ……
3、应用中使用自定义类型
/com/csmn/ext/yy/disposable/use_{1}.jsp /com/csmn/ext/yy/disposable/use_yearMonthGoodsUseList.jsp 医院${goodsUseDto.year}年${goodsUseDto.month}月一次性无菌物品出入库情况一栏表.pdf
上面的type="pdf"即为第二步中result-types下的name="pdf",参数${goodsUseDto.year}、${goodsUseDto.month}则通过第一步中TextParseUtil.translateVariables(param, invocation.getStack())处理为实际数据。