Struts2自定义Result的返回type类型之导出PDF

在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;

/**
 * <p>
 * PdfResult類主要用於-导出到PDF.
 * </p>
 * <p>
 * 創建時間 2013-12-7 - 下午08:05:52
 * </p>
 * <blockquote>
 * <h4>歷史修改記錄</h4>
 * <ul>
 * <li>城邑耕夫 2017-02-02 添加动态参数传递(主要用于处理文件名)
 * </ul>
 * </blockquote>
 * <p>
 * copyright cdthgk 2010-2013, all rights reserved.
 * </p>
 * 
 * @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 ) {
					Map<String, String> resultConfigParams = resultConfig.getParams();
					for (Iterator<Entry<String, String>> i = resultConfigParams.entrySet().iterator(); i.hasNext();) {
						Map.Entry<String, String> 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<String> 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<String, String> requestParameters = new LinkedHashMap<String, String>();

	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<String, String> getRequestParameters() {
		return requestParameters;
	}
	public void setRequestParameters(Map<String, String> requestParameters) {
		this.requestParameters = requestParameters;
	}
}

2、在struts.xml中注册自定义类型

<package name="csmn.default" extends="struts-default">
   	<result-types>
		<result-type name="pdf" class="com.csmn.base.action.PdfResult"/>
		……
	</result-types>
	<!-- 全局结果 -->
	<global-results>
		……
	</global-results>

	<!-- 全局异常 -->
	<global-exception-mappings>
		……
	</global-exception-mappings>
</package>

3、应用中使用自定义类型

<action name="use_*" method="{1}" class="yy.disposableUseAction">
	<result name="success">/com/csmn/ext/yy/disposable/use_{1}.jsp</result>
	<result name="yearMonthGoodsUseList_pdf" type="pdf">
		<param name="location">/com/csmn/ext/yy/disposable/use_yearMonthGoodsUseList.jsp</param>
		<param name="fileName">医院${goodsUseDto.year}年${goodsUseDto.month}月一次性无菌物品出入库情况一栏表.pdf</param>
	</result>
</action>

上面的type="pdf"即为第二步中result-types下的name="pdf",参数${goodsUseDto.year}、${goodsUseDto.month}则通过第一步中TextParseUtil.translateVariables(param, invocation.getStack())处理为实际数据。

转载于:https://my.oschina.net/chwencong/blog/831041

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值