赞
踩
上一篇文章springmvc–jsp视图解析响应原理,详细的介绍了jsp
的解析响应原理,但是这项技术毕竟已经过时了,所以本篇文章我们来介绍点不一样的,使用视图来实现xlsx
表格下载功能。我们使用poi
来构建表格,如果对poi
技术不了解,建议先看一下这篇文章POI
的简单使用
这个例子我们来实现表格下载功能,我们先创建一个springmvc
应用
除了springmvc
相关依赖外,只需要额外导入poi
的依赖即可
<!-- poi --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.2</version> </dependency>
//我们将这个视图放入容器中,取名为xlsxView @Component(value = "xlsxView") public class XlsxView extends AbstractXlsxView { /** * Application-provided subclasses must implement this method to populate * the Excel workbook document, given the model. * * @param model the model Map * @param workbook the Excel workbook to populate * @param request in case we need locale etc. Shouldn't look at attributes. * @param response in case we need to set cookies. Shouldn't write to it. */ @Override protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception { //创建一个sheet XSSFSheet sheet = (XSSFSheet) workbook.createSheet("test1"); XSSFRow row1 = sheet.createRow(3); XSSFCell cell1 = row1.createCell(3); //设置单元格值类型 cell1.setCellType(CellType.STRING); //设置单元格内容 cell1.setCellValue(43543); //设置单元格样式 //单元格样式要从工作空间创建,不能直接new XSSFCellStyle cellStyle = (XSSFCellStyle) workbook.createCellStyle(); //设置单元格顶部线条的粗细程度 cellStyle.setBorderTop(BorderStyle.THIN); //设置单元格顶部边框颜色为红色 cellStyle.setBorderColor(XSSFCellBorder.BorderSide.TOP, new XSSFColor(Color.RED)); cell1.setCellStyle(cellStyle); //设置字体 XSSFFont font = (XSSFFont) workbook.createFont(); font.setColor(IndexedColors.LEMON_CHIFFON.getIndex()); cellStyle.setFont(font); } }
springmvc
已经为我们提供了一个抽象类AbstractXlsxView
,它已经为我们做了如下工作
- 工作空间的创建
- 文件下载响应头的设置
- 表格文件写入响应体
这三部分是固定不变的,所以
springmvc
将它们抽取出来,放到父类中,子类只需要实现在工作空间中创建一个表格即可。典型的模板方法模式。
@Configuration @EnableWebMvc @ComponentScan({"cn.lx.spring.controller","cn.lx.spring.view"}) public class MvcConfig implements WebMvcConfigurer { public void configureViewResolvers(ViewResolverRegistry registry) { //创建视图解析器,根据视图名从容器中取出视图对象 BeanNameViewResolver viewResolver = new BeanNameViewResolver(); registry.viewResolver(viewResolver); } public void addViewControllers(ViewControllerRegistry registry) { //添加视图映射 registry.addViewController("/xlsx").setViewName("xlsxView"); } }
配置了一个视图解析器,并添加视图关系映射
启动程序,当我们访问
http://localhost:8080/项目名/xlsx
时,服务器就会使用BeanNameViewResolver
这个视图解析器从容器中取出beanName
为xlsxView
的视图对象,然后调用视图对象的render()
方法渲染视图,完成表格的下载。
为什么我们只需要写短短几行代码就能实现表格下载功能呢,这个因为其他事情springmvc
已经自动帮我们做了。
先来看一下我们编写的视图类的继承关系
AbstractView
这个类源码在springmvc–jsp视图解析响应原理这篇文章中说过,这里不再贴出源码了。该类只是简单的定义渲染视图的流程,如下所示
createMergedOutputModel(model, request, response);
方法:合并模型数据和静态数据prepareResponse(request, response);
方法:响应之前的准备工作renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
方法:渲染视图AbstractXlsView
:添加对XLS
格式的表格下载的功能AbstractXlsxView
:添加对XLSX
格式的表格下载的功能
接下来,我们一个一个的看后面两个类的源码
AbstractXlsView
该类重写了它父类的两个方法,分别为
generatesDownloadContent()
方法,返回true
表示文件下载
renderMergedOutputModel(model, request, response)
方法,渲染视图的过程
generatesDownloadContent()
@Override
protected boolean generatesDownloadContent() {
return true;
}
简单的返回一个
true
,表示文件下载。它父类会根据这个方法的返回值设置文件下载的响应头
renderMergedOutputModel(model, request, response)
/** * Renders the Excel view, given the specified model. */ @Override protected final void renderMergedOutputModel( Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // Create a fresh workbook instance for this render step. //创建命名空间,见3.1.2.1 Workbook workbook = createWorkbook(model, request); // Delegate to application-provided document code. //设置表格内容和样式,见3.1.2.2 buildExcelDocument(model, workbook, request, response); // Set the content type. //设置响应的内容类型,见3.1.2.3 response.setContentType(getContentType()); // Flush byte array to servlet output stream. //渲染视图,见3.1.2.4 renderWorkbook(workbook, response); }
该方法定义了表格创建过程的模板
- 创建命名空间
- 设置表格内容和样式
- 设置响应的内容类型
- 渲染视图,就是将表格写入响应体中
/**
* Template method for creating the POI {@link Workbook} instance.
* <p>The default implementation creates a traditional {@link HSSFWorkbook}.
* Spring-provided subclasses are overriding this for the OOXML-based variants;
* custom subclasses may override this for reading a workbook from a file.
* @param model the model Map
* @param request current HTTP request (for taking the URL or headers into account)
* @return the new {@link Workbook} instance
*/
protected Workbook createWorkbook(Map<String, Object> model, HttpServletRequest request) {
return new HSSFWorkbook();
}
简单的
new
了一个HSSFWorkbook
对象,它生成Microsoft Excel XLS
格式的表格如果需要
Microsoft Excel OOXML XLSX
格式的表格,只需要重写这个方法即可,事实上,它的子类AbstractXlsxView
就是这么做的
/**
* Application-provided subclasses must implement this method to populate
* the Excel workbook document, given the model.
* @param model the model Map
* @param workbook the Excel workbook to populate
* @param request in case we need locale etc. Shouldn't look at attributes.
* @param response in case we need to set cookies. Shouldn't write to it.
*/
protected abstract void buildExcelDocument(
Map<String, Object> model, Workbook workbook, HttpServletRequest request, HttpServletResponse response)
throws Exception;
抽象方法,具体表格的内容和样式应该由用户自己设置,我们的视图
XlsxView
就是重写的这个方法,实现表格内容和格式的定制化
getContentType()
方法是父类AbstractView
的方法,它返回contentType
字段值,而这个字段值如果用户不修改的话,默认为"text/html;charset=ISO-8859-1"
。但是需要注意,在AbstractXlsView
类构造方法中给这个字段重新赋值了
/**
* Default Constructor.
* Sets the content type of the view to "application/vnd.ms-excel".
*/
public AbstractXlsView() {
setContentType("application/vnd.ms-excel");
}
响应的内容类型为
application/vnd.ms-excel
/**
* The actual render step: taking the POI {@link Workbook} and rendering
* it to the given response.
* @param workbook the POI Workbook to render
* @param response current HTTP response
* @throws IOException when thrown by I/O methods that we're delegating to
*/
protected void renderWorkbook(Workbook workbook, HttpServletResponse response) throws IOException {
//响应体输出流
ServletOutputStream out = response.getOutputStream();
//写入表格
workbook.write(out);
//关流
workbook.close();
}
这里没什么好说的,就是简单的将表格写入响应体中
AbstractXlsxView
抽象类,仅仅重写了父类的
createWorkbook(model, request)
方法,创建生成Microsoft Excel OOXML XLSX
格式表格的命名空间
/**
* This implementation creates an {@link XSSFWorkbook} for the XLSX format.
*/
@Override
protected Workbook createWorkbook(Map<String, Object> model, HttpServletRequest request) {
return new XSSFWorkbook();
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。