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. 一道codeforces题目引发的差分学习

    Codeforces Round #688 (Div. 2) 题目:B. Suffix Operations 题意:给定一个长为n的数组a,你可以进行两种操作:1).后缀+1;     2)后缀-1: ...

  2. [bug] VMvare 虚拟机磁盘空间耗尽

    问题 VMvare虚拟机文件默认创建在C盘,装大程序的时,空间用尽就会报错,此时补救的办法是把虚拟机文件复制到空间足够的盘,再重新打开 最好一开始就选再有足够空间的盘里创建虚拟机 参考 https:/ ...

  3. 1.4 重置root用户密码

    图1-45  系统的欢迎界面 1.4 重置root用户密码 平日里让运维人员头疼的事情已经很多了,因此偶尔把Linux系统的密码忘记了并不用慌,只需简单几步就可以完成密码的重置工作.但是,如果您是第一 ...

  4. Ansible_使用文件模块将修改文件复制到受管主机

    一.描述常用文件模块 1.常用文件模块 模块名称 模块说明 blockinfile 插入.更新或删除由可自定义标记线包围的多行文本块 copy 将文件从本地或远程计算机复制到受管主机上的某个位置.类似 ...

  5. Linux 操作系统(三) 添加用户、切换用户、删除用户

    以下命令均已在 Kali Linux 验证. 1.添加用户 --1-- useradd -m username            //username 代表你所添加的用户名 --2-- passw ...

  6. Linux进阶之综合练习

    综合练习: 1.准备2台centos7系统的服务器,远程互相免密登录,以下所有题目过程中开启防火墙 2.给1号机和2号机使用光盘搭建本地yum源(永久生效) 3.给服务器1添加2块硬盘,1块1GB,1 ...

  7. FreeRTOS相关转载-(朱工的专栏)

    FreeRTOS系列第1篇---为什么选择FreeRTOS? 1.为什么学习RTOS? 作为基于ARM7.Cortex-M3硬件开发的嵌入式工程师,我一直反对使用RTOS.不仅因为不恰当的使用RTOS ...

  8. 第5讲 | 从物理层到MAC层:如何在宿舍里自己组网玩联机游戏?

    第一层(物理层) 水晶头要做交叉线,用的就是所谓的 1-3.2-6 交叉接法. 有一个叫做 Hub 的东西,也就是集线器.这种设备有多个口,可以将宿舍里的多台电脑连接起来.但是,和交换机不同,集线器没 ...

  9. Elasticsearch快速入门和环境搭建

    内容概述 什么是Elasticsearch,为什么要使用它? 基础概念简介 节点(node) 索引(index) 类型映射(mapping) 文档(doc) 本地环境搭建,创建第一个index 常用R ...

  10. 服务器ip迁移纪要

    21楼机房之前已配25网段静态ip,机架上14台服务器接22楼机房交换机,同样25网段. 实际有两种情况, a.25网段ip没有被他人占用,这种情况无需更改ip. b.该IP已被外部使用,ip冲突,无 ...