一、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. 脚踏实地学C#5-扩展方法

    扩展方法(Extension Method) MSDN定义:能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法须知: 1.扩展方法声明所在的类必须被声明为 ...

  2. ORA-32001:write to SPFILE requested but no SPFILE is in use

    oracle报错: ORA-32001:write to SPFILE requested but no SPFILE is in use 解决方法: 1.查看是否有spfile sql> sh ...

  3. 数据表示Numpy

    1 基本 1.1 基本介绍 掌握表示, 清洗, 统计和展示数据的能力 Numpy, Matplotlib, Pandas, Projects 摘要: 有损的提取数据特征的过程 可以将一组数据, 摘要出 ...

  4. bzoj 2238 Mst——树链剖分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2238 一条非树边可以对一条链的树边产生影响.注意是边,所以把边下放到点上,只要跳 top 时 ...

  5. 洛谷 P3803 多项式乘法(FFT) —— FFT

    题目:https://www.luogu.org/problemnew/show/P3803 终于学了FFT了! 参考博客:https://www.cnblogs.com/zwfymqz/p/8244 ...

  6. 23.java方法的深入

    深入: public class MethodTest05{ public static void main(String[] args){ int i=m1(ture); System.out.pr ...

  7. C# 计算时间日期

    System.DateTime datetime = System.DateTime.Now.AddSeconds(fixtime); // fixtime 是往后的秒数 : datetime是现在时 ...

  8. 极客时间_Vue开发实战_07.Vue组件的核心概念(3):插槽

    07.Vue组件的核心概念(3):插槽 严格来的说在2.0之后已经不分区这两种插槽的概念了. 因为它底层的实现已经趋向于相同了. 2.6为了兼容2.5的版本,现在依然可以用这两种写法 作用域插槽就是多 ...

  9. Flutter实战视频-移动电商-12.首页_GridView类别导航制作

    12.首页_GridView类别导航制作 首页导航区的制作 外面用一个gridview来写.里面单独提出来 新建导航组件 还是在home_page.dart里面写代码 新建一个静态的组件: 快捷键写组 ...

  10. jquery中innerheight outerHeight()与height()的区别

    1. .height() 获取匹配元素集合中的第一个元素的当前计算高度值 或 设置每一个匹配元素的高度值(带一个参数). 注意:1).css('height')和.height()之间的区别是后者返回 ...