一、maven依赖jar包

 <dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>

二、导出view

public class ExportMemberVo {
private String name; private Integer gender; private String idCard; private String bankNo; private String bankName; private String phone; /**
* 性别处理
*/
public String getGender() {
return gender == 0 ? "男" : "女";
}
/****为了节省篇幅,省略setter/getter/constructor****/
}

三、导出Excel核心处理代码,继承自AbstractXlsView ,并实现buildExcelDocument

import export.entity.ExportMemberVo;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.springframework.web.servlet.view.document.AbstractXlsView; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map; /**
* @Author Kent.Wang
* @Date 2017/6/26
*/
public abstract class ExcelView extends AbstractXlsView { @Override
protected void buildExcelDocument(Map<String, Object> map,
Workbook workbook,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
String excelName = map.get("name").toString() + ".xls";
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(excelName,"utf-8"));
response.setContentType("application/ms-excel; charset=UTF-8");
response.setCharacterEncoding("UTF-8");
@SuppressWarnings("unchecked")
List<ExportMemberVo> list = (List<ExportMemberVo>) map.get("members");
Sheet sheet = workbook.createSheet("User Detail");
sheet.setDefaultColumnWidth(30);
CellStyle style = workbook.createCellStyle();
Font font = workbook.createFont();
font.setFontName("Arial");
style.setFillForegroundColor(HSSFColor.BLUE.index);
style.setFillPattern((short) 1);
font.setBold(true);
font.setColor(HSSFColor.WHITE.index);
style.setFont(font);
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("姓名");
header.getCell(0).setCellStyle(style);
header.createCell(1).setCellValue("性别");
header.getCell(1).setCellStyle(style);
header.createCell(2).setCellValue("手机号");
header.getCell(2).setCellStyle(style);
header.createCell(3).setCellValue("身份证号");
header.getCell(3).setCellStyle(style);
header.createCell(4).setCellValue("银行卡号");
header.getCell(4).setCellStyle(style);
int rowCount = 1;
for (ExportMemberVo user : list) {
Row userRow = sheet.createRow(rowCount++);
userRow.createCell(0).setCellValue(user.getName());
userRow.createCell(1).setCellValue(user.getGender());
userRow.createCell(2).setCellValue(user.getPhone());
userRow.createCell(3).setCellValue(user.getIdCard());
userRow.createCell(4).setCellValue(user.getBankNo());
}
}
}

四、controller代码

 @RequestMapping(value = "", method = RequestMethod.GET)
public ModelAndView download() { List<ExportMemberVo> list = new ArrayList<ExportMemberVo>();
for (int i = 0; i < 5; i++) {
ExportMemberVo exportMemberVo = new ExportMemberVo();
exportMemberVo.setName("Kent" + i);
@SuppressWarnings("unchecked")
int gender = ThreadLocalRandom.current().nextInt(0, 2);
exportMemberVo.setGender(gender);
exportMemberVo.setPhone("182xxxxxxxx");
exportMemberVo.setBankName("建设银行");
list.add(exportMemberVo);
} Map<String, Object> map = new HashMap<String, Object>();
map.put("members", list);
map.put("name", "魅力城市");
ExcelView excelView = new UserInfoExcelView();
return new ModelAndView(excelView, map);
}

运行,访问download结果如下: 

这是网络上一般的导出方法,没什么特别的,拿来即用,在使用的过程中也碰到一些问题,和疑问,下面谈谈我自己的理解。

五、火狐浏览器导出excel中文乱码问题

 这个问题是因浏览器的不同所造成的,那只要对response.setHeader做些处理就可以了。我只测试了chrome和firefox,其他浏览器或许还有些差异,在此不一一枚举。

String Agent = request.getHeader("User-Agent");
if (null != Agent) {
Agent = Agent.toLowerCase();
if (Agent.indexOf("firefox") != -1) {
response.setHeader("content-disposition", String.format("attachment;filename*=utf-8'zh_cn'%s", URLEncoder.encode(excelName, "utf-8"))); } else {
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(excelName, "utf-8"));
}
}

六、buildExcelDocument是怎么被调用的

 我们看到继承自AbstractXlsView 的buildExcelDocument方法是protected的,只能被同一包下面和子类调用,理论上controller不会去继承ExcelView ,也不会在同一包下,那我们如何去调用他,在springMVC和spring boot下,我们需要用到ModelAndView。 
我通过两幅图来列举下buildExcelDocument调用的过程:

download方法执行return之后会大致执行如下过程,我们可以看到buildExcelDocument是如何被调用的,具体过程有兴趣可以自己debug。

其中比较重要的一个环节是view.render,这里用到了Java的多态特性,AbstractView是继承自View的,ExcelView自然也继承View,所以获取到的ModelAndView中的view执行view.render实际上会去调用AbstractView的render方法,然后AbstractView中有个抽象方法renderMergeOutputModel,供子类实现不同的输出模型,输出Excel文件就是其中的一个子类,还有输出PDF文件也是同理实现该方法。

具体handle方法返回ModelAndView的过程如下: 

七、包装一下Excel输出模版

 我们可能需要输出许多Excel,有成员信息,商品信息,规格信息等等。所以将所有设置Excel的代码全放在ExcelView类中有点不合时宜,很显然至少列名和值的绑定都写死了,难以扩展。

仿照AbstractView中用到的模板方法模式,我们也可以将具体设置Sheet提取出来,写个抽象方法,由子类去实现具体设置Sheet.

修改过的ExcelView如下:

public CellStyle cellStyle;

/**
* 设置样式
*
* @param workbook
*/
protected abstract void setStyle(Workbook workbook); /**
* 设置Row,由子类实现
*
* @param sheet
* @param map
*/
protected abstract void setRow(Sheet sheet, Map<String, Object> map); @Override
protected void buildExcelDocument(Map<String, Object> map,
Workbook workbook,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
String excelName = map.get("name").toString() + ".xls";
String Agent = request.getHeader("User-Agent");
if (null != Agent) {
Agent = Agent.toLowerCase();
if (Agent.indexOf("firefox") != -1) {
response.setHeader("content-disposition", String.format("attachment;filename*=utf-8'zh_cn'%s", URLEncoder.encode(excelName, "utf-8"))); } else {
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(excelName, "utf-8"));
}
}
response.setContentType("application/ms-excel; charset=UTF-8");
Sheet sheet = workbook.createSheet("User Detail");
sheet.setDefaultColumnWidth(30);
this.setStyle(workbook);
setRow(sheet, map);
}

 我们写个导出成员信息UserInfoExcelView ,所有Sheet设置都在这里完成:

public class UserInfoExcelView extends ExcelView {

    @Override
public void setRow(Sheet sheet, Map<String, Object> map) { // create header row
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("姓名");
header.getCell(0).setCellStyle(super.cellStyle);
header.createCell(1).setCellValue("性别");
header.getCell(1).setCellStyle(super.cellStyle);
header.createCell(2).setCellValue("手机号");
header.getCell(2).setCellStyle(super.cellStyle);
header.createCell(3).setCellValue("身份证号");
header.getCell(3).setCellStyle(super.cellStyle);
header.createCell(4).setCellValue("银行卡号");
header.getCell(4).setCellStyle(super.cellStyle); @SuppressWarnings("unchecked")
List<ExportMemberVo> list = (List<ExportMemberVo>) map.get("members");
int rowCount = 1;
for (ExportMemberVo user : list) {
Row userRow = sheet.createRow(rowCount++);
userRow.createCell(0).setCellValue(user.getName());
userRow.createCell(1).setCellValue(user.getGender());
userRow.createCell(2).setCellValue(user.getPhone());
userRow.createCell(3).setCellValue(user.getIdCard());
userRow.createCell(4).setCellValue(user.getBankNo());
}
} @Override
protected void setStyle(Workbook workbook) {
DefaultCellStyle defaultCellStyle = new DefaultCellStyleImpl();
super.cellStyle = defaultCellStyle.setCellStyle(workbook);
} }

如果还需要导出其他excel,同样继承下ExcelView并实现setRow和setStyle就可以了。

由于样式可能会设置通用的,但又有扩展的可能性,所以可以实现一个默认样式接口。

DefaultCellStyle.java

public interface DefaultCellStyle {
CellStyle setCellStyle(Workbook workbook);
}

DefaultCellStyleImpl.java

public class DefaultCellStyleImpl implements DefaultCellStyle {
@Override
public CellStyle setCellStyle(Workbook workbook) {
// create style for header cells
CellStyle cellStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setFontName("Arial");
cellStyle.setFillForegroundColor(HSSFColor.BLUE.index);
cellStyle.setFillPattern((short) 1);
font.setBold(true);
font.setColor(HSSFColor.WHITE.index);
cellStyle.setFont(font);
return cellStyle;
}
}

https://blog.csdn.net/wang124454731/article/details/73850645

spring boot使用AbstractXlsView导出excel的更多相关文章

  1. spring boot:使用poi导出excel电子表格文件(spring boot 2.3.1)

    一,什么是poi? 1,poi poi是用来兼容微软文档格式的java api, 它是apache的顶级项目之一, 也是我们在生产环境中导出excel时使用最多的库 2,poi官方网站: http:/ ...

  2. Spring Boot利用poi导出Excel

    至于poi的用法就不多说了,网上多得很,但是发现spring boot结合poi的就不多了,而且大多也有各种各样的问题. public class ExcelData implements Seria ...

  3. spring boot 整合 poi 导出excel

    一. 第一种方式 1.首先从中央仓库中导入架包Poi3.14以及Poi-ooxml3.14. <dependency> <groupId>org.apache.poi</ ...

  4. Spring Boot:添加导出Excel表格功能

    1.添加POI依赖 2.创建EXCEL实体类 3.创建表格工具类 4.创建ExcelConstant 5.创建ExcelController 1.添加POI依赖 <dependency> ...

  5. spring boot 使用POI导出数据到Excel表格

    在spring boot 的项目经常碰到将数据导出到Excel表格的需求,而POI技术则对于java操作Excel表格提供了API,POI中对于多种类型的文档都提供了操作的接口,但是其对于Excel表 ...

  6. spring boot + easypoi两行代码excel导入导出

    easypoi封装了poi让我们能够非常简单的实现Excel导出,Excel模板导出,Excel导入,Word模板导出等,具体可见官网:http://www.afterturn.cn/. 我这边实现了 ...

  7. spring mvc项目中导出excel表格简单实现

    查阅了一些资料,才整理出spring mvc 项目导出excel表格的实现,其实很是简单,小计一下,方便以后查阅,也希望帮助有需要的朋友. 1.导入所需要依赖(Jar包).我使用的是maven,所以坐 ...

  8. spring boot 使用 POI 读取Excel文件

    内容简介 本文主要介绍使用POI进行Excel文件的相关操作,涉及读取文件,获取sheet表格,对单元格内容进行读写操作,以及合并单元格的操作. Excel文件目录 Excel模板文件存了resour ...

  9. Spring Boot 系列教程12-EasyPoi导出Excel下载

    Java操作excel框架 Java Excel俗称jxl,可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件,现在基本没有更新了 http://jxl.sourcef ...

随机推荐

  1. 存储过程系列四: decode函数使用学习

    Oracle 中 decode 函数用法 含义解释:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值) 该函数的含义如下:IF 条件=值1 THEN RETURN(翻译 ...

  2. python学习笔记:第二天(基本数据类型)

    Python3 基本数据类型 1.标准数据类型 Python3中有六个标准的数据类型:Number(数字).String(字符串).List(列表).Tuple(元组).Sets(集合).Dictio ...

  3. hdu-5621 KK's Point(dp+数学)

    题目链接: KK's Point Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others ...

  4. 利用PDF.JS插件解决了本地pdf文件在线浏览问题(根据需要隐藏下载功能,只保留打印功能)

    我是在IE11和谷歌上做的测试,都可以显示,把做出的东西记录下来,方便大家还有自己学习! 可以在IIS7服务器上也可以下载Tomcat来做服务器 Tomcat下载地址   http://pan.bai ...

  5. Flutter实战视频-移动电商-03.底部导航栏制作

    03.底部导航栏制作 material是谷歌退出的 还有另外的一种:cupertino是IOS的风格 我们底部的导航栏,静态的widget是不合适的,这垃圾我们用到动态的widget 这重新改成动态的 ...

  6. CodeForces 496D Tennis Game (暴力枚举)

    题意:进行若干场比赛,每次比赛两人对决,赢的人得到1分,输的人不得分,先得到t分的人获胜,开始下场比赛,某个人率先赢下s场比赛时, 游戏结束.现在给出n次对决的记录,问可能的s和t有多少种,并按s递增 ...

  7. 简单运行Lua代码

    http://blog.csdn.net/hamenny/article/details/4420522

  8. Android教程

    转载,但请务必在明确位置注明出处! http://stormzhang.com/android/2014/07/07/learn-android-from-rookie/ Android Killer ...

  9. Codeforces714B【读题-水】

    题意: 给你n个数,然后让你自己选择X,先选择一些+一次:然后选择一些-一次. 思路: 首先要去判断是不是不需要处理或者处理一次的情况: 其实这样的话,你不可能选x然后最小和最大都加减一次,所以肯定是 ...

  10. 洛谷P4884 多少个1?(BSGS)

    传送门 模数好大……__int128好麻烦……而且BSGS第一次写有点写蒙了…… $11...1(N个1)\equiv k(mod m)$很难算,那么考虑转化一下 先把$11...1(N个1)$写成$ ...