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. @Aspect 注解使用详解

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点, ...

  2. BUAA-OO-第四单元总结——终章

    面向对象第四单元博客总结--终章 第四单元作业设计 第13次作业设计 类和对应方法属性设计 类设计如下图所示 本次作业主要涉及六个类,其中包括主类 Main ,通用Map类 UmlElementIdM ...

  3. envoy 官方example运行失败问题处理

    镜像内安装包失败处理 方法一:修改Dockerfile,在Dockerfile中增加如下 ubuntu示例 RUN sed -i 's/archive.ubuntu.com/mirrors.aliyu ...

  4. [c++] 文件包含

    当一个类用到另一个类时,有两种包含方式,在.h中包含和在.cpp中包含 用到公共类库时,在.h文件中包含(公共类库可视为不变的) 用到项目开发过程中自己或同事写的类时,在.cpp文件中包含(可能根据需 ...

  5. RHEL高级磁盘管理—Stratis

    2. Stratis 本地存储管理工具,通过Stratis可以便捷的使用Thin Provisioning.Snapshots.Pool-based的管理和监控等高级存储功能. Stratis 基于x ...

  6. Canal和Otter介绍和使用

    Canal Canal原理 原理相对比较简单: canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议 mysql master收 ...

  7. MySQL 查询操作

    目录 基本语法 查询常量 查看表达式 查询函数 查询指定字段 查询所有列 列别名 表别名 条件查询 条件查询运算符 逻辑查询运算符 排序与分页 排序查询(order by) 排序方式 limit 分组 ...

  8. IDEA 配置 Tomcat(详细)(Day_12)

    如果这世界上真有奇迹,那只是努力的另一个名字.生命中最难的阶段,不是没有人懂你,而是你不懂你自己. 运行环境 AND 版本 JDK8 + IntelliJ IDEA 2018.3  +   Tomca ...

  9. MongoDB(7)- 文档插入操作

    插入方法 db.collection.insertOne() 插入单条文档到集合中 db.collection.insertMany() 插入多条文档到集合中 db.collection.insert ...

  10. Archlinux常用软件推荐 更新于2021年4月

    记录一下常用软件 必装软件 包管理工具 yay 代替pacman的包管理 yaourt 备用 终端工具 zsh oh-my-zsh-git 搭配zsh利器` proxychains4 终端代理工具` ...