首先说一下背景,公司某项目年代久远,大致环境要求如下:不可使用servlet(配置文件更新管理杂乱);基本框架没有,大部分是原始的JSP2.0。这对习惯了热门框架的开发人员来说是一种非常糟糕的体验,不仅维护难度大,并且扩展性极差。但是,还是硬着头皮去做。
主要软件环境:POI3.1,Jsp2.0,JDK1.7
示例代码如下:
1.前端页面,提供一个下载链接
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Get excel</title>
<script type="text/javascript">
function go_excel(){
var ff = document.myform;
ff.action = "/test/pages/do_act.jsp";
ff.target = "hidden_frame"
ff.submit();
}
</script>
</head>
<body>
<form method="post" οnsubmit="return false;" name="myform">
<input type="hidden" name="file_num" value="1">
<h2>Files to download</h2>
<a href="javascript:go_excel()">Download</a>
<iframe name="hidden_frame" src="" frameborder="0" width="0" height="0" scrolling="yes" marginheight="0" marginwidth="0"></iframe>
</form>
</body>
</html>
2使用JSP作为action处理:
<%@page import="com.yan.service.ExcelExport"%>
<%@page import="java.io.FileInputStream"%>
<%@page import="java.io.OutputStream"%>
<%@page import="java.io.File"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String value = request.getParameter("file_num");
String path = request.getSession().getServletContext().getRealPath("");
path = path.replace("\\", "/");
String file_name = "";
File file = null;
if("1".equals(value)){
file_name = "test_xls.xls";
ExcelExport eep = new ExcelExport(path);
eep.generateFile(request);
file = new File(path+"/test_xls.xls");
}
response.setHeader("Content-disposition", "attachment;filename="+file_name);
response.setContentType("application/vnd.ms-excel");
long length = file.length();
response.setHeader("Content_Length", String.valueOf(length));
OutputStream os = response.getOutputStream();
byte b[] = new byte[1024];
FileInputStream in = new FileInputStream(file);
int len = 0;
while((len = in.read(b))!=-1){
os.write(b, 0, len);
}
os.flush();
os.close();//注意下面的用法
os=null;
response.flushBuffer();
out.clear();
out = pageContext.pushBody();
in.close();
%>
值得注意的是:在Jsp中使用OutPutStream时,若不经过特殊处理,程序将会报以下异常:getOutputStream() has already been called for this response。具体原因是因为JSP在编译成Servlet时,在_jspService(HttpServletRequest request, HttpServletResponse response)方法之后有如下的一段代码:
finally {
if (_jspxFactory != null)
_jspxFactory.releasePageContext(_jspx_page_context);
}
主要作用是释放JSP中使用到的一些内置对象,同时也会调用response.getWriter(),这个方法和response.getOutPutStream()是互相冲突的,因此在输出流使用完毕后需要添加上面的几行特殊处理代码。
3.后端服务程序:
后端程序主要是POI的一些用法,建立excel文件,提供下载。通常在实际应用中,这些数据需要从数据库加载,并非静态数据。
package com.yan.service;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* @ClassName: ExcelExport
* @Description: (这里用一句话描述这个类的作用)
* @author Helen
* @date 2015年10月6日 上午10:21:39
*/
public class ExcelExport {
private String path;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public ExcelExport(String path){
this.path = path;
}
public void generateFile(HttpServletRequest request){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("User_info");
sheet.setColumnWidth((short)0, (short)3000);
sheet.setColumnWidth((short)1, (short)5000);
sheet.setColumnWidth((short)2, (short)3000);
HSSFRow row = sheet.createRow(0);
HSSFCell cell[] = new HSSFCell[4];
HSSFCell col_cell = null;
//DB数据示例
for (int i = 0; i < cell.length; i++) {
cell[i] = row.createCell((short)i);
}
cell[0].setCellValue(new HSSFRichTextString("编号"));
cell[1].setCellValue(new HSSFRichTextString("用户名"));
cell[2].setCellValue(new HSSFRichTextString("性别"));
cell[3].setCellValue(new HSSFRichTextString("地区"));
for (int i = 1; i < 11; i++) {
row = sheet.createRow(i);
for (int j = 0; j < cell.length; j++) {
col_cell = row.createCell((short)0);
col_cell.setCellValue(new HSSFRichTextString("编号"+i));
col_cell = row.createCell((short)1);
col_cell.setCellValue(new HSSFRichTextString("用户名"+i));
col_cell = row.createCell((short)2);
col_cell.setCellValue(new HSSFRichTextString("性别"+i));
col_cell = row.createCell((short)3);
col_cell.setCellValue(new HSSFRichTextString("地区"+i));
}
}
File f = new File(path+"/test_xls.xls");
if(!f.exists()){
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
FileOutputStream os = new FileOutputStream(f);
workbook.write(os);
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上就完成了此次核心功能的开发。