文件下载中的若干问题之——resultType Stream

本文介绍了一种使用Struts2框架实现从查询数据到Excel文件导出的方法。通过具体的代码示例,展示了如何利用JSP页面和Struts2 Action进行文件下载,并详细解析了在Struts2中导出Excel的具体步骤。
公司项目要实现这样一个功能,将查询出来的数据导出为excel表格的形式给用户。这样的功能类似于文件下载。在
最初的jsp页面中,实现下载是这么实现的:

 

<%@ page contentType="text/html; charset=GB2312"%>
<%@ page import="java.io.*" %>
<html>
  <head></head>
  <body>
    <%
     OutputStream o = response.getOutputStream();
     byte[] b = new byte[500];
     File file = new File("c:/","cgx.jpg");
     //告诉浏览器文件的MIME类型,如application/octet-stream
     response.setContentType("image/jpeg");
     //客户使用保存文件的对话框,去掉这句,浏览器会调用外部程序,直接打开下载的文件
     response.setHeader("Content-Disposition", "attachment;filename=cgx.jpg");
     long fileLength = file.length();
     String length = String.valueOf(fileLength);
     response.setHeader("Content-Length", length);
     FileInputStream in = new FileInputStream(file);
     int n = 0;
     while((n = in.read(b)) != -1) {
      o.write(b,0,n);
     }
     out.clear();
     out = pageContext.pushBody();
     //不加这两句会报错:getOutputStream() has already been called for this response
    %>
  </body>
</html>

 

将JSP页面的最后两行代码的注释去掉,这两行代码的作用如下:

out.clear():清空缓存的内容。

pageContext.pushBody():参考API

public BodyContent pushBody()

Return a new BodyContent object, save the current "out" JspWriter, and update the value of the "out" attribute in the page scope attribute namespace of the PageContext.

返回一个新的BodyContent(代表一个HTML页面的BODY部分内容)
·保存JspWriter实例的对象out
·更新PageContext的out属性的内容。

 

 然而在struts2中,action与配置文件分别为:

public String exportSheetPart(){
		this.showByRole();
		return this.exportSheet();
	}
	
	public String exportSheetTotal() {
		this.execute();
		return this.exportSheet();
	}

public String exportSheet() {
		ValueStack vs = (ValueStack)ServletActionContext.getRequest().getAttribute("struts.valueStack");
		UserUtil userUtil = (UserUtil)vs.findValue("userUtil");
		DeptUtil deptUtil = (DeptUtil)vs.findValue("deptUtil");
		CodeUtil codeUtil = (CodeUtil)vs.findValue("codeUtil");
		
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		String realpath = ServletActionContext.getServletContext().getRealPath("/jsp/common/equipTemplate.xls");
		try {
			docName = new String("设备维修.xls".getBytes("GBK"),"iso-8859-1");
			/*写out Workbook template = null;
			WorkbookSettings setting = new WorkbookSettings();
			java.util.Locale locale = new java.util.Locale("zh","CN");
			setting.setLocale(locale);
			setting.setEncoding("GBK");
			template = Workbook.getWorkbook(new File(realpath),setting);
			WritableWorkbook book = Workbook.createWorkbook(out,template);
			WritableSheet sheet = book.getSheet(0);
			
			WritableCellFormat wcf = new WritableCellFormat();
			wcf.setAlignment(Alignment.CENTRE);
			wcf.setVerticalAlignment(VerticalAlignment.CENTRE);
			wcf.setFont(new WritableFont(WritableFont.ARIAL,10,WritableFont.BOLD,false, UnderlineStyle.NO_UNDERLINE, Colour.RED));
			wcf.setBorder(Border.ALL, BorderLineStyle.THIN);
			
			WritableCellFormat ftText = new WritableCellFormat();
			ftText.setAlignment(Alignment.CENTRE);
			ftText.setVerticalAlignment(VerticalAlignment.CENTRE);
			ftText.setFont(new WritableFont(WritableFont.TIMES, 10, WritableFont.BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK));
			ftText.setBorder(Border.ALL, BorderLineStyle.THIN);
			
			int row = 1;
			int index = 0;
			String tmptMaintainDeptId;
			String tmptMaintainUserId;
			String tmptFixDate;
			String tmptFixMethod;
			for(FaMaintain result : maintainList){
				if(result.getMaintainDeptId() == null) {
					tmptMaintainDeptId = "";
					tmptMaintainUserId = "";
				} else {
					tmptMaintainDeptId = result.getMaintainDeptId().toString();
					tmptMaintainUserId = result.getMaintainUserId().toString();
				}
				if(result.getFixDate() == null) {
					tmptFixDate = "";
				} else {
					tmptFixDate = result.getFixDate().toString();
				}
				if(result.getFixMethod() == null) {
					tmptFixMethod = "";
				} else {
					tmptFixMethod = result.getFixMethod();
				}
				Label indexTitle = new Label(0,row,Integer.toString(index),ftText);
				Label equipNumber = new Label(1,row,result.getFaEquipment().getEquipNumber(),ftText);
				Label status = new Label(2,row,codeUtil.name("FA_MAINTAIN_STATUS", result.getStatus()),ftText);
				Label healthStatus = new Label(3,row,codeUtil.name("FA_EQUIPMENT_HEALTH_STATUS", result.getFaEquipment().getHealthStatus()),ftText);
				Label replace = new Label(4,row,codeUtil.name("FND_YESNO", result.getReplace()),ftText);
				Label createUserId = new Label(5,row,userUtil.name(result.getCreateUserId().toString()),ftText);
				Label createDeptId = new Label(6,row,deptUtil.name(result.getCreateDeptId().toString()),ftText);
				Label createDate = new Label(7,row,result.getCreateDate().toString(),ftText);
				Label priority = new Label(8,row,codeUtil.name("FA_MAINTAIN_PRIORITY", result.getPriority()),ftText);
				Label maintainUserId = new Label(9,row,userUtil.name(tmptMaintainUserId),ftText);
				Label maintainDeptId = new Label(10,row,deptUtil.name(tmptMaintainDeptId),ftText);
				Label fixDate = new Label(11,row,tmptFixDate,ftText);
				Label fixMethod = new Label(12,row,codeUtil.name("FA_MAINTAIN_METHOD", tmptFixMethod),ftText);
				Label memo = new Label(13,row,result.getMemo(),ftText);	
				
				sheet.addCell(indexTitle);
				sheet.addCell(equipNumber);
				sheet.addCell(status);
				sheet.addCell(healthStatus);
				sheet.addCell(replace);
				sheet.addCell(createUserId);
				sheet.addCell(createDeptId);
				sheet.addCell(createDate);
				sheet.addCell(priority);
				sheet.addCell(maintainUserId);
				sheet.addCell(maintainDeptId);
				sheet.addCell(fixDate);
				sheet.addCell(fixMethod);
				sheet.addCell(memo);
				row++;
				index++;
			}
			book.write();
			book.close();*/
			exportStream = new ByteArrayInputStream(out.toByteArray());//将out转化为in的小技巧
		}catch (Exception e) {
			addActionError("导出失败");
			e.printStackTrace();
			return ERROR;
		} finally {// 正常关闭输入输出流.
			try {
				if (out != null) {
					out.flush();
					out.close();
					out = null;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return SUCCESS;
	}

 

		<action name="equip_export" method="exportSheetPart" class="MaintainListAction">
				<result name="success" type="stream"> 
					<param name="contentType">application/octet-stream;charset=ISO8859-1</param>
					<param name="contentDisposition">attachment;fileName="${docName}"</param>
					<param name="inputName">exportStream</param>
					<param name="bufferSize">4096</param>
				</result>
		</action>
		<action name="equip_export2" method="exportSheetTotal" class="MaintainListAction">
				<result name="success" type="stream"> 
					<param name="contentType">application/octet-stream;charset=ISO8859-1</param>
					<param name="contentDisposition">attachment;fileName="${docName}"</param>
					<param name="inputName">exportStream</param>
					<param name="bufferSize">4096</param>
				</result>
		</action>

 

在jsp页面中,有这样一段js

function exp(){
		var tgt = document.queryForm.target;
		var act = document.queryForm.action;
		document.queryForm.target = 'sframe';
		document.queryForm.action = 'equip_export.do';
		document.queryForm.submit();
		document.queryForm.action = act;
		document.queryForm.target = tgt;
	}

 

 和这样一些html

<td width="40">
			<table border="0" cellpadding="0" cellspacing="0" class="ButCmd-border" onMouseOver="this.className='ButCmd2-border'" onMouseOut="this.className='ButCmd-border'" > 
			<tr> 
				<td><input name="expBtn" onclick="exp();" value="导出表格" title="导出表格" type="button"  class="btn3_mouseout" onMouseOver="this.className='btn3_mouseover'" onMouseOut="this.className='btn3_mouseout'" onMouseDown="this.className='btn3_mousedown'" onMouseUp="this.className='btn3_mouseup'" style="width:66px; height:22px;"/></td> 
			</tr> 
            </table>
			</td>
<iframe src="" name="sframe" width="100%" marginwidth="0" height="0" marginheight="0" scrolling="no" frameborder="0" id="sframe"></iframe>

 

 

 

 

 

 

 

 

 

 

Return a new BodyContent object, save the current "out" JspWriter, and update the value of the "out" attribute in the page scope attribute namespace of the PageContext.

 

Returns:
the new BodyContent

·返回一个新的BodyContent(代表一个HTML页面的BODY部分内容)
·保存JspWriter实例的对象out
·更新PageContext的out属性的内容

 

Returns:
the new BodyContent
### MyBatis 中 `resultType` 属性配置 BigDecimal 的方式 在 MyBatis 的 XML 文件中,当查询的结果是一个单一的数值类型(如 `BigDecimal`),可以通过设置 `<select>` 标签中的 `resultType` 属性来定义返回的数据类型。对于 `BigDecimal` 类型,可以直接将其全限定名作为 `resultType` 的值。 以下是具体的配置方法: #### 配置示例 ```xml <select id="getReturnAmount" resultType="java.math.BigDecimal"> SELECT IFNULL(SUM(mymoney), 0.00) AS total_amount FROM test_table WHERE status = #{status} </select> ``` 在此示例中,`resultType="java.math.BigDecimal"` 明确指定了查询结果应映射为 Java 的 `BigDecimal` 数据类型[^1]。如果 SQL 查询返回的是单列数据,则 MyBatis 将自动将该列转换为指定的 `BigDecimal` 对象并返回给调用者。 #### 注意事项 - 如果查询结果可能为空,建议在 SQL 中使用函数(如 MySQL 的 `IFNULL` 或其他数据库对应的函数)提供默认值,以避免潜在的空指针异常。 - 当返回多个字段时,需改用 `resultMap` 而非 `resultType` 来描述复杂对象结构[^2]。 #### 完整代码实现 假设有一个 Mapper 接口如下: ```java public interface TestMapper { BigDecimal getReturnAmount(String status); } ``` 配合上述 XML 配置即可完成对 `BigDecimal` 类型的处理。 --- ### 关于基础类型的补充说明 Java 提供了基本数据类型及其包装类的支持,在 MyBatis 中可以灵活运用这些类型。例如,`int` 和 `Integer` 是两种不同的表示形式,前者是原始类型而后者是其包装类[^3]。同样地,`BigDecimal` 是一种高精度数值类型,适用于金融计算或其他需要精确控制小数位的应用场景。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值