1、前言

​ 在Spring Boot项目中,将数据导出成Excel格式文件是常见的功能。与Excel文件导入类似,此处也用代码框架式的方式实现Excel文件导出,使得代码具有可重用性,并保持导出数据转换的灵活性。

​ 相对于导入Excel文件的处理,导出Excel文件要简单一些。这里的Excel文件支持xlsx格式。

2、基本框架

​ 包括一个接口类ExcelExportable和一个Excel导出处理类ExcelExportHandler,以及支持ExcelExportable接口类的实体类。与基类相比,使用接口类的好处是可以实现多个接口类,而不会有多重继承的麻烦。这样实体类可以同时支持Excel和CSV格式文件的导出。

2.1、Excel导出处理类ExcelExportHandler

​ ExcelExportHandler类的代码如下:

package com.abc.questInvest.excel;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List; import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import com.abc.questInvest.excel.ExcelExportable; /**
* @className : ExcelExportHandler
* @description : Excel导出处理类
*
*/
public class ExcelExportHandler<T extends ExcelExportable> { /**
*
* @methodName : exportExcelFile
* @description : 导出Excel文件供下载
* @param rowDataList : 导出的数据列表
* @param excelFilePath : Excel文件临时文件路径
* @param sheetName: sheet页名称
* @throws Exception : 发生异常时,抛出
*
*/
public void exportExcelFile(List<T> rowDataList,String excelFilePath,String sheetName)
throws Exception {
if (rowDataList.size() == 0) {
//必须要有导出数据,否则创建标题列失败
throw new Exception("无导出数据.");
} XSSFWorkbook wb = null;
wb = new XSSFWorkbook(); //创建sheet页
XSSFSheet sheet = wb.createSheet(sheetName); //创建标题行
createTitle(wb,sheet,rowDataList.get(0)); //添加数据
addSheetContent(sheet,wb,rowDataList); //输出文件数据供下载
outputExcelFile(excelFilePath,wb); } /**
*
* @methodName : createTitle
* @description : 设置标题行
* @param workbook : workbook对象
* @param sheet : sheet对象
* @throws Exception : 发生异常时,抛出
*
*/
private void createTitle(XSSFWorkbook workbook, XSSFSheet sheet,T rowData) throws Exception{
XSSFRow row = sheet.createRow(0);
//取得标题行
String[] arrTitles = rowData.outputTitleList(); //设置列宽
for (int i = 0; i < arrTitles.length; i++){
//设置固定宽度,setColumnWidth的第二个参数的单位是1/256个字节宽度
sheet.setColumnWidth(i,arrTitles[i].getBytes("UTF-8").length * 256); //设置自适应宽度,性能不高,故不用了
//sheet.autoSizeColumn(i);
} //设置为居中加粗
XSSFCellStyle style = workbook.createCellStyle();
XSSFFont font = workbook.createFont();
font.setBold(true);
style.setAlignment(HorizontalAlignment.CENTER);
style.setFont(font); XSSFCell cell;
for (int i = 0; i < arrTitles.length; i++){
cell = row.createCell(i);
cell.setCellValue(arrTitles[i]);
cell.setCellStyle(style);
} } /**
*
* @methodName : addSheetContent
* @description : 为sheet对象添加数据行内容
* @param sheet : sheet对象
* @param workbook : workbook对象
* @param rowDataList : 数据行列表
* @throws Exception : 发生异常时,抛出
*
*/
private void addSheetContent(XSSFSheet sheet, XSSFWorkbook workbook, List<T> rowDataList)
throws Exception
{
//单元格居中
XSSFCellStyle style = workbook.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER); //数据行下标从1开始
int rowNum=1;
//遍历导出数据行
for(int i=0;i<rowDataList.size();i++){
XSSFRow row = sheet.createRow(rowNum);
XSSFCell cell;
T rowData = rowDataList.get(i);
String[] arrRow = rowData.outputList();
for (int j = 0; j < arrRow.length; j++) {
cell = row.createCell(j);
cell.setCellValue(arrRow[j]);
cell.setCellStyle(style);
}
rowNum++;
}
} /**
*
* @methodName : outputExcelFile
* @description : 输出Excel文件
* @param filePath : 输出的文件路径
* @param workbook : workbook对象
* @throws Exception : 发生异常时,抛出
*
*/
private void outputExcelFile(String filePath,XSSFWorkbook workbook) throws Exception{
OutputStream outputStream = new FileOutputStream(new File(filePath));
workbook.write(outputStream);
outputStream.flush();
outputStream.close();
}
}

​ ExcelExportHandler支持泛型T,T限定必需支持ExcelExportable接口类。只要实体类实现ExcelExportable类的接口方法,就可以利用ExcelExportHandler的方法实现Excel文件导出。

2.2、可Excel导出的接口类ExcelExportable

​ ExcelExportable类的代码如下:

package com.abc.questInvest.excel;

/**
* @className : ExcelExportable
* @description : 可Excel导出的接口类,由POJO类实现
*
*/
public interface ExcelExportable { /**
*
* @methodName : outputTitleList
* @description : 输出标题列表,用于标题行
* @return : 字符串数组
*
*/
public String[] outputTitleList(); /**
*
* @methodName : outputList
* @description : 输出数据列表,用于数据行
* @return : 字符串数组
*
*/
public String[] outputList();
}

​ ExcelExportable类定义了2个接口方法:

  • outputTitleList方法,输出标题列表,用于标题行。
  • outputList方法,输出数据列表,用于数据行。

2.3、实体类例子

​ 对需要导出Excel文件的现有的实体类进行改造,使之支持ExcelExportable接口类。

​ 实体类为AnswerInfo,代码如下:

package com.abc.questInvest.entity;

import java.util.Date;

import javax.persistence.Column;

import com.abc.questInvest.excel.ExcelExportable;

import lombok.Data;

/**
* @className : AnswerInfo
* @description : 答卷信息类,支持Excel数据导出
*
*/
@Data
public class AnswerInfo implements ExcelExportable {
// 记录id
@Column(name = "rec_id")
private Integer recId; // 发布任务id
@Column(name = "task_id")
private Integer taskId; // 问卷id
@Column(name = "questionnaire_id")
private Integer questionnaireId; // 问题编号
@Column(name = "question_no")
private Integer questionNo; // 答案
@Column(name = "answer")
private String answer; //========记录操作信息================
// 操作人姓名
@Column(name = "login_name")
private String loginName; // 记录删除标记,保留
@Column(name = "delete_flag")
private Byte deleteFlag; // 创建时间
@Column(name = "create_time")
private Date createTime; // 更新时间
@Column(name = "update_time")
private Date updateTime; //========实现ExcelExportable接口================ //导出的Excel数据的列数
private static final int COLUMN_COUNT = 5; /**
*
* @methodName : outputTitleList
* @description : 输出标题列表,用于标题行
* @return : 字符串数组
*
*/
@Override
public String[] outputTitleList() {
String[] arrTitle = new String[COLUMN_COUNT];
arrTitle[0] = "问卷ID";
arrTitle[1] = "发布任务ID";
arrTitle[2] = "记录ID";
arrTitle[3] = "题号";
arrTitle[4] = "答案";
return arrTitle;
} /**
*
* @methodName : outputList
* @description : 输出数据列表,用于数据行
* @return : 字符串数组
*
*/
@Override
public String[] outputList() {
String[] arrRowData = new String[COLUMN_COUNT]; //各属性字段,从数据库中取出,都为非null值
//此处实现导出字段的物理含义转换和计算
arrRowData[0] = questionnaireId.toString();
arrRowData[1] = taskId.toString();
arrRowData[2] = recId.toString();
arrRowData[3] = questionNo.toString();
arrRowData[4] = answer; return arrRowData;
}
}

2.4、单元测试

​ 下面进行Excel文件导出的单元测试。测试代码如下:

package com.abc.questInvest.excel;

import java.util.ArrayList;
import java.util.List; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import com.abc.questInvest.entity.AnswerInfo; /**
* @className : ExcelExportHandlerTest
* @description : Excel文件导出测试
*
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ExcelExportHandlerTest { @Test
public void exportExcelFileTest() {
ExcelExportHandler<AnswerInfo> excelExp = new ExcelExportHandler<AnswerInfo>(); AnswerInfo item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(1);
item.setQuestionNo(1);
item.setAnswer("A");
dataList.add(item); item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(1);
item.setQuestionNo(2);
item.setAnswer("B");
dataList.add(item); item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(1);
item.setQuestionNo(3);
item.setAnswer("A");
dataList.add(item); item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(2);
item.setQuestionNo(1);
item.setAnswer("B");
dataList.add(item); item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(2);
item.setQuestionNo(2);
item.setAnswer("B");
dataList.add(item); item = new AnswerInfo();
item.setQuestionnaireId(1);
item.setTaskId(1);
item.setRecId(2);
item.setQuestionNo(3);
item.setAnswer("C");
dataList.add(item); String property = System.getProperty("user.dir");
String filePath = property + "\\answer_data_Q1_T1.xlsx";
String sheetName = "Q1_T1"; List<AnswerInfo> dataList = new ArrayList<AnswerInfo>(); try {
excelExp.exportExcelFile(dataList,filePath, sheetName);
}catch(Exception e) {
e.printStackTrace();
} }
}

执行测试代码,可以看到导出的Excel文件,文件内容如下:

3、Excel文件导出并下载

​ 在导出生成了Excel文件后,只需与文件下载代码结合起来,就可以实现Excel文件下载了。

​ 文件下载,可作为静态的公共方法,放入工具类中。代码如下:

	/**
*
* @methodName : download
* @description : 下载指定路径的文件
* @param response : reponse对象
* @param filePath : 需要下载的文件路径
* @param contentType : response header中的ContentType,常用取值如下:
* 普通二进制文件 : application/octet-stream
* Excel文件 : application/vnd.ms-excel
* 文本文件 : text/plain; charset=utf-8
* html文件 : text/html; charset=utf-8
* xml文件 : text/xml; charset=utf-8
* jpeg文件 : image/jpeg
* @throws Exception : 异常发生时,抛出。没有异常,说明下载成功。
*
*/
public static void download(HttpServletResponse response,String filePath,
String contentType) throws Exception{ File file = new File(filePath);
if (file.exists()) {
//设置读取流的缓存为1K
byte[] buffer = new byte[1024];
FileInputStream fis = null;
BufferedInputStream bis = null;
//设置ContentType
response.setContentType(contentType);
// 下载文件能正常显示中文
String filename = filePath.substring(filePath.lastIndexOf("/")+1);
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
//获取输入流
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
//输出流
OutputStream os = response.getOutputStream();
int len = bis.read(buffer);
while (len != -1) {
os.write(buffer, 0, len);
len = bis.read(buffer);
} //关闭流
if (bis != null) {
bis.close();
}
if (fis != null) {
fis.close();
}
}
}

​ 调用download方法,contentType参数取值为“application/vnd.ms-excel”即可。

Spring Boot下的一种导出Excel文件的代码框架的更多相关文章

  1. Spring Boot下的一种导入Excel文件的代码框架

    1.前言 ​ Spring Boot下如果只是导入一个简单的Excel文件,是容易的.网上类似的文章不少,有的针对具体的实体类,代码可重用性不高:有的利用反射机制或自定义注解,开发了Excel导入工具 ...

  2. Spring Boot下的一种导出CSV文件的代码框架

    1.前言 ​ CSV,逗号分隔值(Comma-Separated Values),即为逗号分隔的文本文件.如果值中含有逗号.换行符.制表符(Tab).单引号及双引号,则需要用双引号括起来:如果值中包含 ...

  3. jxl导出Excel文件

    一.java项目实现读取Excel文件和导出Excel文件 实现读取和导出Excel文件的代码: package servlet; import java.io.FileInputStream; im ...

  4. JavaScript 上万条数据 导出Excel文件(改装版)

    最近项目要js实现将数据导出excel文件,网上很多插件实现~~那个开心呀,谁知道后面数据量达到上万条时出问题:浏览器不仅卡死,导出的excel文件一直提示网络失败.... debug调试发现var  ...

  5. Spring Boot下Druid连接池+mybatis

      目前Spring Boot中默认支持的连接池有dbcp,dbcp2, hikari三种连接池.  引言: 在Spring Boot下默认提供了若干种可用的连接池,Druid来自于阿里系的一个开源连 ...

  6. 创建Spring Boot项目的几种方式总结

    一.我们可以使用Spring Initializr来创建SpringBoot项目. Spring Initializr从本质上来说就是一个Web应用程序,它能为你生成Spring Boot项目结构.虽 ...

  7. Spring Boot2 系列教程(二)创建 Spring Boot 项目的三种方式

    我最早是 2016 年底开始写 Spring Boot 相关的博客,当时使用的版本还是 1.4.x ,文章发表在 CSDN 上,阅读量最大的一篇有 43W+,如下图: 2017 年由于种种原因,就没有 ...

  8. spring boot下为配置属性值加密的正确姿势

    最近做电商系统,安全性要求比较高,针对配置属性值的加密自然也是需要增强的点之一,那么如何加密呢? 网上搜索了些,有jasypt加密mysql密码的最为普遍,可惜问题就在于只能加密mysql信息,其他的 ...

  9. .Net MVC 导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) 通过MVC控制器导出导入Excel文件(可用于java SSH架构)

    .Net MVC  导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) [原文地址] 通过MVC控制器导出导入Excel文件(可用于java SSH架构)   public cl ...

随机推荐

  1. 克鲁斯卡尔(Kruskal)算法(代码)

    算法代码 C#代码 using System; using System.Linq; namespace Kruskal { class Program { static void Main(stri ...

  2. 如何实现一个简易版的 Spring - 如何实现 AOP(上)

    前言 本文是「如何实现一个简易版的 Spring 系列」的第五篇,在之前介绍了 Spring 中的核心技术之一 IoC,从这篇开始我们再来看看 Spring 的另一个重要的技术--AOP.用过 Spr ...

  3. 【CentOS_7】一行shell实现自动清理过期日志

    昨日web测试环境登录白屏,慌忙登上机器查看,半天没找到问题. 不知哪根筋不对,df -h 一看 , /dev/sda1 已经100%. 立马 du -sh *,发现log日志有点大. 手工清理后,业 ...

  4. 强哥MySQL学习笔记

    数据库服务器:1.数据库2.数据表 数据表:1.表结构(字段)2.表数据(记录)3.表索引(加快检索) 表引擎:1.myisam2.innodb 查看表字段desc table;删除数据库:drop ...

  5. Git工作中的使用

    Git工作中的使用 2019-01-16 14:29:31 雯雯木 阅读数 207更多 分类专栏: 自动化测试   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出 ...

  6. wmctrl像xmonad那样方便地用快捷键来控制任务窗口的显示

    窗口左右互搏之wmctrl篇 分类: LINUX 2012-10-24 16:34:41   一直有个念头,就是能够像xmonad那样方便地用快捷键来控制任务窗口的显示,今天弄wmctrl,刚好有时间 ...

  7. Linux命令行欢迎界面美化

    默认的SSH命令行登录欢迎界面如下 [c:\~]$ Connecting to 10.x.13.x:22... Connection established. To escape to local s ...

  8. Lua中的基本函数库--(转自忧郁的加菲猫)

    基本函数库为Lua内置的函数库,不需要额外装载assert (v [, message])功能:相当于C的断言,参数:v:当表达式v为nil或false将触发错误,message:发生错误时返回的信息 ...

  9. Python3统计gitlab上的代码量

    import threading import gitlab import xlwt #获取所有的user def getAllUsers(): usersli = [] client = gitla ...

  10. Linux Socket编程-(转自吴秦(Tyler))

    "一切皆Socket!" 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. --有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信 ...