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. PTA 第三章 栈与队列

    一.判断题 1.若一个栈的输入序列为1,2,3,--,N,输出序列的第一个元素为i,则第j个输出的元素是j-i-1    (×)解析:应该是不确定的,不能保证数字出栈后不会再入栈 2.所谓" ...

  2. CRM帮助B2B企业持续改善战略决策「上篇」

    数据一直都是企业和客户的热点话题.客户期望得到更加个性化的感受,企业则期望使用数据来持续改善战略决策和给予更好的服务 B2B企业如何更合理地利用客户资料: 数据采集 长期以来,B2C行业的企业都是通过 ...

  3. [Java]数据分析--数据可视化

    时间序列 需求:将一组字符顺序添加到时间序列中 实现:定义时间序列类TimeSeries,包含静态类Entry表示序列类中的各项,以及add,get,iterator,entry方法 TimeSeri ...

  4. [刷题] 206 Reverse Linked List

    要求 反转一个链表 不得改变节点的值 示例 head->1->2->3->4->5->NULL NULL<-1<-2<-3<-4<-5 ...

  5. nginx 日志管理配置详解

    nginx的日志管理 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$statu ...

  6. python基础之面向对象(一)(概念、实例、魔法方法)

    一.面向对象概念理解 1.面向对象和面向过程 面向过程:核心过程二字,过程即解决问题的步骤,就是先干什么后干什么 基于该思想写程序就好比在这是一条流水线,是一种机械式的思维方式 优点:复杂的过程流程化 ...

  7. Linux中级之keepalived配置

    hacmp: ibm的高可用集群软件,并且是商业的(收费),一般用于非x86架构机器当中 AIX,Unix 去IOE:ibm,oracle,emckeepalived: 一款高可用集群软件,利用vrr ...

  8. 安装beanstalkd队列问题——No package beanstalkd available

    CentOS7.4安装beanstalkd 时无可用源 No package beanstalkd availableError:Nothing to do 可从以下获取:wget /etc/yum. ...

  9. 【Azure 环境】Azure Key Vault (密钥保管库)中所保管的Keys, Secrets,Certificates是否可以实现数据粒度的权限控制呢?

    问题描述 Key Vault (密钥保管库) 能不能针对用户授权实现指定用户只能访问某个或某些特定的key? 如当前有两个用户(User1, User2),在Key Vault中有10个Key,Use ...

  10. 痞子衡嵌入式:在SBL项目实战中妙用i.MXRT1xxx里SystemReset不复位的GPR寄存器

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1xxx里SystemReset不复位的GPR寄存器的小妙用. 我们知道稍大规模的项目代码设计一般都是多人协作完成的,在项目 ...