作为一名不称职的程序员,不爱记笔记更是个坏习惯,有时候我遇到的问题总是觉得熟悉,就是想不起来怎么解决的,说明人老了记忆力和行动力都减弱,还是勤记笔记。
说一下最近遇到的问题吧,年后回来的工作其实挺轻松,没有太多的新需求进行开发,都是对年前开发完的需求出现的bug进行修改。其中一个bug是导出excel表,年前写完测试的时候并没有发现什么问题,当放假回来测试人员进行测试的时候,当时我就有些懵逼,jvm直接outmemory,对于经验很是不足的我来说这是什么鬼啊,根据测试人员的描述来调试的时候发现在查询数据的时候需要很长的时间,然后就直接报错了,我采用的是poi的HSSFWorkbook 的方式,这个存在一个限制,excel的一个表最多是65536行,根本不能够满足现在的需求,而且边查边写的操作很是浪费时间,导出几千条数据都慢的不行。经过百度之后,很多人都推荐使用.csv的方式,所以我也决定采用这个方法。下面直接把代码贴上。
package com.zst.cloudzst.util.exportcsv;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import com.sun.org.apache.commons.beanutils.BeanUtils;
//此处的outPutPath指的是request.getRealPath("")
//exportData指的是数据
//rowMapper指的是表头
public class ExportCsv {
public static File createCSVFile(List<HashMap<String, Object>> exportData, LinkedHashMap<String, String> rowMapper,String outPutPath) {
File csvFile = null;
BufferedWriter csvFileOutputStream = null;
String separator = System.getProperty("file.separator");//区分正反斜杠 windows / linux系统
outPutPath = outPutPath+separator+"meeting";
try {
File file = new File(outPutPath);
if (!file.exists()) {
file.mkdir();
}
//定义文件名格式并创建
csvFile = File.createTempFile("meetingDetail", ".csv", new File(outPutPath));
System.out.println("csvFile:" + csvFile);
// UTF-8使正确读取分隔符","
csvFileOutputStream = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
csvFile), "UTF-8"), 1024);
System.out.println("csvFileOutputStream:" + csvFileOutputStream);
// 写入文件头部
for (Iterator propertyIterator = rowMapper.entrySet().iterator(); propertyIterator.hasNext();) {
java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator.next();
/*System.out.println(propertyEntry.getKey()+":"+propertyEntry.getValue());*/
csvFileOutputStream.write("\"" + (String) propertyEntry.getValue() != null ? (String) propertyEntry
.getValue() : "" + "\"");
if (propertyIterator.hasNext()) {
csvFileOutputStream.write(",");
}
}
csvFileOutputStream.newLine();
// 写入文件内容
for (Iterator iterator = exportData.iterator(); iterator.hasNext();) {//记忆中百度说用这种方式的循环不用在乎源数据的内部结构,修改率较低
Object row = (Object) iterator.next();
for (Iterator propertyIterator = rowMapper.entrySet().iterator(); propertyIterator.hasNext();) {
java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator.next();
Object obj = BeanUtils.getProperty(row, propertyEntry.getValue().toString());
/*System.out.println("Object="+obj);*/
csvFileOutputStream.write((String) BeanUtils.getProperty(row,(String) propertyEntry.getValue()));
if (propertyIterator.hasNext()) {
csvFileOutputStream.write(",");
}
}
if (iterator.hasNext()) {
csvFileOutputStream.newLine();
}
}
csvFileOutputStream.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
csvFileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return csvFile;
}
}
导出的时候先是ajax请求,然后返回的时候用window.location.href 调用浏览器的下载框,同事说这是个比较鸡肋的方法,但是暂时解决了问题,如果有更好的方法请推荐
success: function(msg){
if(msg.path){
var path = msg.path;
var local = window.location;
var contextPath = local.pathname.split("/")[1];
var basePath = local.protocol+"//"+local.host+"/"+contextPath+"/";
window.location.href = basePath+path;
}
}