1.客户端网页下载文件, 如果文件比较大,后台要进行压缩在传输给客户端。
2.后台进行压缩以后,要保存到服务器硬盘上, 当下次请求下载,则直接传输。
3.当请求下载的压缩文件不存在,需要查询数据,生成csv,最后将多个文件进行压缩保存到服务器硬盘上。
4.多线程进行查询,单线程进行压缩。
先看一个方法:
public String accountingVerificationExport(String zipFileName) {
String zipSrc = "";
try {
/**
* 导出到本地, 然后压缩成zip,并返回zip文件地址
*/
zipSrc = exportToLocation(zipFileName);
} catch(Exception ex) {
LOGGER.info("exec accountingVerificationExport error.{}", ex.getMessage());
}
return zipSrc;
}
方法的参数zipFileName是指定压缩之后文件名.exportLocation
/**
* 启动四个线程,同步导出
* @param zipFileName
* @return
*/
private String exportToLocation(String zipFileName) {
ResourceLoadUtil rlu = new ResourceLoadUtil("/hx.properties");
final Properties prop = rlu.getProp();
final String exportLocation = prop.getProperty("hx.export.location.href");
final CountDownLatch end = new CountDownLatch(4); //子线程
final String [] typeName = new String[]{"receipt","output1","output2","back"};
final List fileSrcs = new ArrayList();// 用于存放生成的文件名称
final SessionFactory sessionFactory = accountingVerificationDao.getSessionFactory();
LOGGER.info("导出线程开始运行 !");
for(int i = 0; i < typeName.length; i++) {
final int index = i;
new Thread(new Runnable() {
public void run() {
LOGGER.info("启动子线程{}", typeName[index]);
/**
* 子线程等待
*/
boolean participate = ConcurrentUtil.bindHibernateSessionToThread(accountingVerificationDao.getSessionFactory());
String fileSrc1 = exportList(exportLocation,prop.getProperty("hx.export."+typeName[index]+".fileName"),
prop.getProperty("hx.export."+typeName[index]+".sheetColumn"),
prop.getProperty("hx.export."+typeName[index]+".sql"));
if(!StringUtil.isEmpty(fileSrc1)) {
fileSrcs.add(fileSrc1);
}
ConcurrentUtil.closeHibernateSessionFromThread(participate, sessionFactory);
end.countDown();
LOGGER.info("{} 线程结束运行.",typeName[index]);
}
}).start();
}
try {
end.await();
} catch (InterruptedException e) {
LOGGER.info("{}",e.getMessage());
}
LOGGER.info("导出线程结束运行 !");
String zipSrcName = "";
if(!CollectionUtil.isEmpty(fileSrcs) && fileSrcs.size() > 0) {
zipSrcName = exportLocation + "/" + zipFileName + ".zip";
File zip = new File(zipSrcName);// 压缩文件
File srcfile[] = new File[fileSrcs.size()];
for (int i = 0, n = fileSrcs.size(); i < n; i++) {
srcfile[i] = new File(fileSrcs.get(i));
}
FileZip.ZipFiles(srcfile, zip);
}
return zipSrcName;
}
CountDownLatch: 作用是启动多个线程,主线程等待所有线程完成在执行
ConcurrentUtil.bindHibernateSessionToThread: 最多线程情况下为每个线程绑定session(只有绑定了session才可以用spring的dao bean)
/**
* 导出csv文件,csv没有文件行数限制
* @param exportLocation 输出到硬盘的临时地址
* @param fileName 文件名
* @param titles 标题
* @param sql
* @return
*/
private String exportList(String exportLocation, String fileName, String titles, String sql) {
String fileSrc = exportLocation + "/" + fileName + ".csv";
List
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* HIbernate子线程中绑定session
* @author Administrator
*
*/
public class ConcurrentUtil {
public static boolean bindHibernateSessionToThread(SessionFactory sessionFactory) {
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
// Do not modify the Session: just set the participate flag.
return true;
} else {
Session session = sessionFactory.openSession();
session.setFlushMode(FlushMode.MANUAL);
SessionHolder sessionHolder = new SessionHolder(session);
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
}
return false;
}
public static void closeHibernateSessionFromThread(boolean participate, Object sessionFactory) {
if (!participate) {
SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSession(sessionHolder.getSession());
}
}
}