文档章节

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

城邑耕夫
 城邑耕夫
发布于 2017/02/02 12:04
字数 976
阅读 156
收藏 0

在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())处理为实际数据。

© 著作权归作者所有

城邑耕夫
粉丝 92
博文 137
码字总数 104811
作品 0
成都
程序员
私信 提问
struts2笔记——整合JasperReports

JasperReports,Jasper .[dʒæspə]碧玉 16.1 JasperReports简介 JasperReport是一个强大、灵活的报表生成工具,能够展示丰富的页面内容,并将之转换成Excel、PDF、HTML或者XML格式。这个工...

梅_95
2016/08/16
28
0
配置Result

常用配置 /hello/Result.jsp //等于/hello/Result.jsp /hello/Error.jsp /hello/Input.jsp /novel listAction ${id} ${userId} 上述代码的含义为, 名字为Hello的Action有三个返回结果,并且......

长平狐
2013/01/06
945
0
struts2 入门精讲(2)

struts.xml配置 1.constant 对象池 struts.objectFactory这个属性用于说明Struts2的 对象池创建工厂,Struts2也有自己的对象池,就像Spring那样,在配置文件中你可以引用对象池中的对象,你可...

南寒之星
2015/11/28
120
0
Result Type(Struts.xml配置)

<result-type name="chain"class="com.opensymphony.xwork2.ActionChainResult"/><result-type name="dispatcher"class="org.apache.struts2.dispatcher.ServletDispatcherResult"default="t......

MLeo
2012/11/05
89
0
Struts2 返回json格式配置

介绍如何使用Struts2的struts2-json-plugin.jar插件返回JSON数据。 一、其中主要步骤有: 1.将struts2-json-plugin.jar插件拷贝到项目的"/WEB-INF/lib"文件夹下; 2.编写Action类文件; 3.在...

文文1
2018/06/30
32
0

没有更多内容

加载失败,请刷新页面

加载更多

CentOS7.6中安装使用fcitx框架

内容目录 一、为什么要使用fcitx?二、安装fcitx框架三、安装搜狗输入法 一、为什么要使用fcitx? Gnome3桌面自带的输入法框架为ibus,而在使用ibus时会时不时出现卡顿无法输入的现象。 搜狗和...

技术训练营
昨天
5
0
《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
昨天
8
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
昨天
10
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
昨天
6
0
PHP+Ajax微信手机端九宫格抽奖实例

PHP+Ajax结合lottery.js制作的一款微信手机端九宫格抽奖实例,抽奖完成后有收货地址添加表单出现。支持可以设置中奖概率等。 奖品列表 <div class="lottery_list clearfix" id="lottery"> ......

ymkjs1990
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部