SpringMVC-4.2+ExcelView视图进行Excel文件下载

jar包方面大家可自行下载,springMvc4.2+版本+poi-3.10.1版本

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

1、4.2以后,使用了AbstractXlsxView和AbstractXlsxStreamingView代替了原有的AbstractExcelView 来进行excel下载的视图构建
这里有一个问题,如果数据为空,则默认调用父类生成的excel会无法打开,
最后发现原因是,空的SXSSFWorkbool没有创建sheet,导致excel打开需要修复,这里创建一个空sheet即可,可参见https://blog.csdn.net/z69183787/article/details/82734931

import com.dianping.emidas.manage.biz.external.mp.util.ExcelExportUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.web.servlet.view.document.AbstractXlsxStreamingView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

public class MpManageExcelView extends AbstractXlsxStreamingView {

    @Override
    protected SXSSFWorkbook createWorkbook(Map<String, Object> model, HttpServletRequest request) {
        List<?> data = (List<?>) model.get("data");
        if(CollectionUtils.isNotEmpty(data)) {
            return ExcelExportUtil.export(data);
        }
        return super.createWorkbook(model, request);
    }

    @Override
    protected void buildExcelDocument(Map<String, Object> model, Workbook workbook,
                                      HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        //解决空sheet无法现在的问题
        if(workbook.getNumberOfSheets() == 0){
            workbook.createSheet("sheet1");
        }
        String filename = model.get("fileName") + ".xlsx"; // 取下载时客户端Excel的名称

        //处理中文文件名
        String reqCharset = request.getCharacterEncoding(); /*根据request的getCharacterEncoding得到请求时的编码*/
        filename = new String(filename.getBytes(reqCharset), "ISO8859-1");
        response.setCharacterEncoding(reqCharset);
        // 若想下载时自动填好文件名,则需要设置响应头的"Content-disposition"
        response.setHeader("Content-disposition", "attachment;filename=" + filename);
    }
}

方法其实显而易见,重写buildExcelDocument ,对model对象及poi中的workbook对象进行修改及赋值,最终response进行输出。可以在方法中对workbook进行createsheet及row的一些poi操作。也可以和例子中一样,重写父类中的createWorkbook,创建自己的workbook对象。父类中原逻辑为创建了一个空的 workbook对象,供build方法使用

 */
public abstract class AbstractXlsxStreamingView extends AbstractXlsxView {

	/**
	 * This implementation creates a {@link SXSSFWorkbook} for streaming the XLSX format.
	 */
	@Override
	protected SXSSFWorkbook createWorkbook(Map<String, Object> model, HttpServletRequest request) {
		return new SXSSFWorkbook();
	}

当然,当真正进行下载时的整体逻辑在父类AbstractXlsxView中已经以模板模式的方式给出了定义,定义了方法的大致业务逻辑及骨架,通过子类自行进行重写,实现自身逻辑

	@Override
	protected final void renderMergedOutputModel(
			Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		// Create a fresh workbook instance for this render step.
		Workbook workbook = createWorkbook(model, request);

		// Delegate to application-provided document code.
		buildExcelDocument(model, workbook, request, response);

		// Set the content type.
		response.setContentType(getContentType());

		// Flush byte array to servlet output stream.
		renderWorkbook(workbook, response);
	}

 

剩下就是一些工具类和实际的controller类的代码:

Excel工具类:


import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class ExcelExportUtil {

    private static final Logger logger = LoggerFactory.getLogger(ExcelExportUtil.class);

    private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    private static final int MAX_SHEET_ROWS = 60000;

    public static SXSSFWorkbook export(List<?> dataList){
        // data
        if (dataList==null || dataList.size()==0) {
            throw new RuntimeException("data is empty,can not generate excel file");
        }

        //获取对象类型注解
        Class<?> targetClass = dataList.get(0).getClass();
        String sheetName = targetClass.getSimpleName();
        ExcelSheet excelSheet = targetClass.getAnnotation(ExcelSheet.class);
        if(excelSheet != null && StringUtils.isNotBlank(excelSheet.name())){
            sheetName = excelSheet.name();
        }

        // 解析字段
        List<Field> fields = new ArrayList<Field>();
        if (targetClass.getDeclaredFields()!=null && targetClass.getDeclaredFields().length>0) {
            for (Field field: targetClass.getDeclaredFields()) {
                if (Modifier.isStatic(field.getModifiers())) {
                    continue;
                }
                fields.add(field);
            }
        }

        if (fields==null || fields.size()==0) {
            throw new RuntimeException("data field can not be empty");
        }

        SXSSFWorkbook wb = new SXSSFWorkbook(100);
        int dataSize = dataList.size();
        int index = 0;
        do{
            List<?> subList = dataList.subList(index,Math.min(dataSize,index+MAX_SHEET_ROWS));
            resolveSheet(wb,fields,subList,sheetName+"-"+index);
            index += MAX_SHEET_ROWS;
        }while (index < dataSize);

        return wb;
    }


    /**
     * 处理一定数量的sheet
     * @param workbook
     * @param dataList
     */
    private static void resolveSheet(Workbook workbook,List<Field> fields,List<?> dataList,String sheetName){
        Sheet sheet = workbook.createSheet(sheetName);

        //head
        Row headRow = sheet.createRow(0);
        CellStyle headStyle = generateHeadStyle(workbook);
        for (int i = 0; i < fields.size(); i++) {
            Field field = fields.get(i);
            ExcelField excelField = field.getAnnotation(ExcelField.class);
            String fieldName = field.getName();
            if(excelField != null && StringUtils.isNotBlank(excelField.column())){
                fieldName = excelField.column();
            }
            Cell cellX = headRow.createCell(i, Cell.CELL_TYPE_STRING);
            cellX.setCellStyle(headStyle);
            cellX.setCellValue(String.valueOf(fieldName));
        }

        //data
        for (int dataIndex = 0; dataIndex < dataList.size(); dataIndex++) {
            int rowIndex = dataIndex+1;
            Object rowData = dataList.get(dataIndex);
            Row rowX = sheet.createRow(rowIndex);
            for (int i = 0; i < fields.size(); i++) {
                Field field = fields.get(i);
                try {
                    field.setAccessible(true);
                    Object fieldValue = field.get(rowData);
                    Cell cellX = rowX.createCell(i, Cell.CELL_TYPE_STRING);
                    cellX.setCellValue(generateValue(fieldValue));
                } catch (IllegalAccessException e) {
                    logger.error(e.getMessage(), e);
                    throw new RuntimeException(e);
                }
            }
        }
    }

    /**
     *
     * @param obj
     * @return
     */
    private static String generateValue(Object obj){
        if(obj == null) return StringUtils.EMPTY;
        if(obj instanceof Date){
            return df.format(obj);
        }
        return String.valueOf(obj);
    }

    /**
     * 生成head样式
     * @param wb
     * @return
     */
    private static CellStyle generateHeadStyle(Workbook wb){
        CellStyle style = wb.createCellStyle();

        /*****************************使用默认颜色**************************************************/
        // 填充色
        style.setFillForegroundColor(IndexedColors.ORANGE.getIndex());
        style.setFillPattern(CellStyle.BIG_SPOTS);

        // 字体颜色
        Font font = wb.createFont();
        font.setColor(IndexedColors.BLACK.getIndex());
        style.setFont(font);

        return style;
    }
}

controller:

@RequestMapping(value = "/download", method = RequestMethod.GET)
    public ModelAndView download(@RequestParam String beginTime,
                                 @RequestParam String endTime) {
        List<MpPrizeExportVo> result = manageFade.export(beginTime,endTime);
        Map<String,Object> map = new HashMap<>();
        map.put("fileName","数据下载-"+beginTime+"-"+endTime);
        map.put("data",result);
        return new ModelAndView(new MpManageExcelView(),map);
    }

 

 

springboot:是一个基于Java开发的框架,简化了Spring应用的初始化配置和部署过程。它提供了一套开发规范和约定,帮助开发人员快速搭建高效稳定的应用程序。 mybatis-plus:是基于MyBatis的增强工具,提供了一些便捷的CRUD操作方法和代码生成功能,简化了数据库操作的开发工作。它能够轻松集成到SpringBoot应用中,提高开发效率。 springmvc:是一种基于MVC设计模式的Web框架,用于构建Web应用程序。它能够从URL中解析请求参数,并将请求分发给对应的Controller进行处理。SpringMVC提供了一套灵活的配置和注解方式,支持RESTful风格的API开发。 shiro:是一种用于身份验证和授权的框架,可以集成到SpringBoot应用中。它提供了一套简单易用的API,可以处理用户认证、角色授权、会话管理等安全相关的功能。Shiro还支持集成其他认证方式,如LDAP、OAuth等。 redis:是一种开源的内存数据库,采用键值对存储数据。Redis具有高性能、高并发和持久化等特点,常用于缓存、消息队列和分布式锁等场景。在企业级报表后台管理系统中,可以使用Redis来进行缓存数据,提高系统的响应速度和性能。 企业级报表后台管理系统:是一种用于统一管理和生成报表的系统。它通常包括用户权限管理、报表设计、报表生成、数据分析等功能。使用SpringBoot、MyBatis-Plus、SpringMVC、Shiro和Redis等技术,可以快速搭建一个可靠、高效的报表管理系统,满足企业对数据分析和决策的需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值