springmvc--13--表格视图原理

springmvc–表格视图原理

1 介绍

上一篇文章springmvc–jsp视图解析响应原理,详细的介绍了jsp的解析响应原理,但是这项技术毕竟已经过时了,所以本篇文章我们来介绍点不一样的,使用视图来实现xlsx表格下载功能。我们使用poi来构建表格,如果对poi技术不了解,建议先看一下这篇文章POI的简单使用

2 例子

这个例子我们来实现表格下载功能,我们先创建一个springmvc应用

2.1 依赖

除了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>

2.2 实现表格下载功能的视图

//我们将这个视图放入容器中,取名为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,它已经为我们做了如下工作

  1. 工作空间的创建
  2. 文件下载响应头的设置
  3. 表格文件写入响应体

这三部分是固定不变的,所以springmvc将它们抽取出来,放到父类中,子类只需要实现在工作空间中创建一个表格即可。典型的模板方法模式。

2.3 配置类

@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");
    }
}

配置了一个视图解析器,并添加视图关系映射

2.4 测试

启动程序,当我们访问http://localhost:8080/项目名/xlsx时,服务器就会使用BeanNameViewResolver这个视图解析器从容器中取出beanNamexlsxView的视图对象,然后调用视图对象的render()方法渲染视图,完成表格的下载。

3 原理

为什么我们只需要写短短几行代码就能实现表格下载功能呢,这个因为其他事情springmvc已经自动帮我们做了。

先来看一下我们编写的视图类的继承关系

在这里插入图片描述

  • AbstractView这个类源码在springmvc–jsp视图解析响应原理这篇文章中说过,这里不再贴出源码了。该类只是简单的定义渲染视图的流程,如下所示
    • createMergedOutputModel(model, request, response);方法:合并模型数据和静态数据
    • prepareResponse(request, response);方法:响应之前的准备工作
    • renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);方法:渲染视图
  • AbstractXlsView:添加对XLS格式的表格下载的功能
  • AbstractXlsxView:添加对XLSX格式的表格下载的功能

接下来,我们一个一个的看后面两个类的源码

3.1 AbstractXlsView

该类重写了它父类的两个方法,分别为

  • generatesDownloadContent()方法,返回true表示文件下载

  • renderMergedOutputModel(model, request, response)方法,渲染视图的过程

3.1.1 generatesDownloadContent()

@Override
protected boolean generatesDownloadContent() {
    return true;
}

简单的返回一个true,表示文件下载。它父类会根据这个方法的返回值设置文件下载的响应头

3.1.2 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);
}

该方法定义了表格创建过程的模板

  1. 创建命名空间
  2. 设置表格内容和样式
  3. 设置响应的内容类型
  4. 渲染视图,就是将表格写入响应体中
3.1.2.1 创建命名空间
/**
 * 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就是这么做的

3.1.2.2 设置表格内容和样式
/**
 * 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就是重写的这个方法,实现表格内容和格式的定制化

3.1.2.3 设置响应的内容类型

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

3.1.2.4 渲染视图,就是将表格写入响应体中
/**
 * 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();
}

这里没什么好说的,就是简单的将表格写入响应体中

3.2 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();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值