一、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. Spring 事务管理高级应用难点剖析: 第 1 部分

    Spring 的事务管理是被使用得最多的功能之一,虽然 Spring 事务管理已经帮助程序员将要做的事情减到了最小.但在实际开发中,如果使用不当,依然会造成数据连接泄漏等问题.本系列以实际应用中所碰到 ...

  2. javascript之闭包,递归,深拷贝

    闭包 理解:a函数执行后return出b函数且b函数可以访问a函数的数据 好处:子函数存储在复函数内部,子函数执行完不会被自动销毁 坏处:占用内存比较大 ex: function bibao(){ v ...

  3. 不能访问tomcat中的项目

    tomcat在eclipse里面能正常启动,而在浏览器中访问http://localhost:8080/不能访问,且报404错误.同时其他项目页面也不能访问. 关闭eclipse里面的tomcat,在 ...

  4. @Autowired注解和启动自动扫描的三种方式(spring bean配置自动扫描功能的三种方式)

    前言: @Autowired注解代码定义 @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, Elemen ...

  5. Paint Tree

    题意: 给定一棵n个点的树,给定平面上n个点,将n个点用线段连起来画成树的形状,使得不存在不在端点相交的线段,构造出一种情况. 解法: 首先观察我们常规画出来的树形图可知,树的子树是根据极角分开的,这 ...

  6. classpath路径指什么

    一.classpath路径指什么 只知道把配置文件如:mybatis.xml.spring-web.xml.applicationContext.xml等放到src目录(就是存放代码.java文件的目 ...

  7. HDOJ-1391

    Number Steps Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  8. webpack内置模块ProvidePlugin

    webpack配置ProvidePlugin后,在使用时将不再需要import和require进行引入,直接使用即可. 使用方法: 在webpack.dev.conf.js和webpack.prod. ...

  9. 201621123016《Java程序设计》第1周学习总结

    1. 本周学习总结 本周的学习内容:java的发展历史,java程序设计环境,java简单语法. java与c++一样是一门面向对象的程序设计语言(相比于c++它是一门更彻底的面向对象的程序设计语言) ...

  10. PhpStorm之操作数据库

    对数据库进行基本的操作 还不清楚如何使用PhpStorm连接本地数据库的朋友看一下我的上一篇博客配置数据库连接 点击已经连接好的数据库,找到下图中的 Consoles,然后点击 console(def ...