springboot使用EasyExcel导入导出填充,解决导出乱码问题(web)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: springboot使用EasyExcel导入导出填充,解决导出乱码问题(web)

官网文档地址:Alibaba Easy Excel - 简单、省内存的Java解析Excel工具 | 首页


maven最新版本地址:https://mvnrepository.com/artifact/com.alibaba/easyexcel

一、添加依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.0.5</version>
</dependency>

二、web导入

1、文件上传

样例数据

可以忽略mapPointInfoMapper,正常的批插入mapper

    @PostMapping("/writexxx")
    @ApiOperation("xxx")
    public AjaxResult writeMapInfo(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), MapPointInfo.class, new ExcelListener(mapPointInfoMapper)).sheet().doRead();
        return toAjax(1);
    }

2、接收数据的model

package xxxx;
 
import com.alibaba.excel.annotation.ExcelIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
 
import java.io.Serializable;
import java.math.BigDecimal;
 
 
@Getter
@Setter
@ToString
public class MapPointInfo implements Serializable {
    @ApiModelProperty("主键id")
    @ExcelIgnore
    private Long id;
 
    @ApiModelProperty("名称")
    private String name;
 
    @ApiModelProperty("经度")
    private BigDecimal longitude;
 
    @ApiModelProperty("纬度")
    private BigDecimal latitude;
 
    @ApiModelProperty("地址")
    private String address;
 
    @ApiModelProperty("电话")
    private String phone;
 
    @ApiModelProperty("分类")
    private String type;
}

3、处理数据的监听器

package xxxx.listener;
 
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import com.lets.psccs.mapper.MapPointInfoMapper;
import com.lets.psccs.model.MapPointInfo;
import lombok.extern.slf4j.Slf4j;
 
import java.util.List;
 
@Slf4j
public class ExcelListener extends AnalysisEventListener<MapPointInfo> {
    /**
     * 每隔5条存储数据库,实际使用中可以3000条,然后清理list
     */
    private static final int BATCH_COUNT = 5;
    List<MapPointInfo> list = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    private MapPointInfoMapper mapPointInfoMapper;
 
    public ExcelListener() {
    }
 
    public ExcelListener(MapPointInfoMapper mapPointInfoMapper) {
        this.mapPointInfoMapper = mapPointInfoMapper;
    }
 
    /**
     * 这个每一条数据解析都会来调用
     */
    @Override
    public void invoke(MapPointInfo data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        //mapPointInfoMapper.insertSelective(data);
        list.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }
 
    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }
 
    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", list.size());
        mapPointInfoMapper.insertList(list);
        log.info("存储数据库成功!");
    }
}
 

三、web导出

1、导出接口

操作日志的导出demo,operationLogs 自己加模拟数据就可以

    @ApiOperation("导出操作日志")
    @GetMapping("/export")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "date1", value = "开始日期", defaultValue = "2020-12-01",required = true),
            @ApiImplicitParam(name = "date2", value = "开始日期", defaultValue = "2021-12-01",required = true),
    })
    public void downchin(HttpServletResponse response, String date1, String date2) throws IOException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
        String date = sdf.format(new Date());
        List<OperationLog>  operationLogs = operationLogMapper.selectOperationLog(date1,date2);
        //定义输出文件名称
        String fileName = URLEncoder.encode("操作日志"+date + ".xlsx","UTF-8") ;
        //设置响应字符集
        response.setCharacterEncoding("UTF-8");
        //设置响应媒体类型
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment;filename="+fileName);
        EasyExcel.write(response.getOutputStream(),OperationLog.class).sheet("操作日志").doWrite(operationLogs);
    }

2、导出的model

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
 
import java.io.Serializable;
import java.util.Date;
 
/**
 * operation_log
 * @author 
 */
@Data
public class OperationLog implements Serializable {
    /**
     * 自增主键
     */
    @TableId(type = IdType.AUTO)
    @ExcelIgnore
    private Integer id;
    /**
     * 操作防区
     */
    @ExcelProperty(value = {"操作日志"})
    private String defence;
 
 
    /**
     * 动作
     */
    @ExcelProperty(value = {"操作日志","动作"})
    @ColumnWidth(16)
    private String action;
 
    /**
     * 操作员姓名
     */
    @ExcelProperty(value = {"操作日志","操作人"})
    private String nickname;
 
    /**
     * 操作人员id
     */
    @ExcelIgnore
    private Integer userId;
 
    /**
     * 操作时间
     */
    @TableField(fill = FieldFill.INSERT)
    @ExcelProperty(value = {"操作日志","处理时间"})
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    @ColumnWidth(23)
    private Date createTime;
 
    /**
     * 操作命令
     */
    @ExcelIgnore
    @JsonIgnore
    private String command;
 
    /**
     * 执行状态
     */
    @ExcelProperty(value = {"操作日志","执行状态"})
    @ColumnWidth(23)
    private String state;
 
    /**
     * 备注
     */
    @ExcelIgnore
    @JsonIgnore
    private String remark;
 
    private static final long serialVersionUID = 1L;
}


四、Excel数据填充

1、准备一个excel模板

2、创建一个对应填充的类

import lombok.Getter;
import lombok.Setter;
 
@Getter
@Setter
public class xxxxPrint {
    /**
     *所属部门
     */
    private String deptName;
    /**
     * 申请人
     */
    private String userName;
    /**
     *申请时间
     */
    private String createTime;
    /**
     *xx标题
     */
    private String name;
    /**
     *申请内容
     */
    private String detail;
    /**
     *部门时间
     */
    private String deptTime;
    /**
     *中心时间
     */
    private String centerTime;
    /**
     *xx状态
     */
    private Integer status;
    /**
     *驳回原因
     */
    private String rejectReason;
    /**
     *xxx
     */
    private String urgentType;
    /**
     *xxxx
     */
    private String eventType;
 
}

 3、编写填充代码

 @GetMapping("/getExcel")
    @ApiOperation("获取Excel")
    public void writeMapInfo(HttpServletResponse res,Long id) throws IOException {
        //获取xx打印 表格
        xxPrint xxPrint = xxService.getxxPrint(id);
        //定义输出文件名称
        String fileName = URLEncoder.encode(teamCasePrint.getName() + ".xlsx","UTF-8") ;
        //设置响应字符集
        res.setCharacterEncoding("UTF-8");
        //设置响应媒体类型
        res.setContentType("application/vnd.ms-excel");
        //设置响应的格式说明
        res.setHeader("Content-Disposition", "attachment;filename="+fileName);
        //读取响应文件的模板
        File file= ResourceUtils.getFile("classpath:templete/申请表打印.xls");
        //替换模板的数据
        EasyExcel.write(res.getOutputStream()).withTemplate(file).sheet().doFill(teamCasePrint);
    }

4、执行结果

乱码的主要原因是字符编码和媒体类型

//定义输出文件名称
String fileName = URLEncoder.encode(teamCasePrint.getName() + ".xlsx","UTF-8") ;
//设置响应字符集
res.setCharacterEncoding("UTF-8");
//设置响应媒体类型
res.setContentType("application/vnd.ms-excel");

相关文章
|
1月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
42 4
|
15天前
|
存储 easyexcel Java
SpringBoot+EasyExcel轻松实现300万数据快速导出!
本文介绍了在项目开发中使用Apache POI进行数据导入导出的常见问题及解决方案。首先比较了HSSFWorkbook、XSSFWorkbook和SXSSFWorkbook三种传统POI版本的优缺点,然后根据数据量大小推荐了合适的使用场景。接着重点介绍了如何使用EasyExcel处理超百万数据的导入导出,包括分批查询、分批写入Excel、分批插入数据库等技术细节。通过测试,300万数据的导出用时约2分15秒,导入用时约91秒,展示了高效的数据处理能力。最后总结了公司现有做法的不足,并提出了改进方向。
|
1月前
|
easyexcel Java UED
SpringBoot中大量数据导出方案:使用EasyExcel并行导出多个excel文件并压缩zip后下载
在SpringBoot环境中,为了优化大量数据的Excel导出体验,可采用异步方式处理。具体做法是将数据拆分后利用`CompletableFuture`与`ThreadPoolTaskExecutor`并行导出,并使用EasyExcel生成多个Excel文件,最终将其压缩成ZIP文件供下载。此方案提升了导出效率,改善了用户体验。代码示例展示了如何实现这一过程,包括多线程处理、模板导出及资源清理等关键步骤。
|
1月前
|
Java BI API
spring boot 整合 itextpdf 导出 PDF,写入大文本,写入HTML代码,分析当下导出PDF的几个工具
这篇文章介绍了如何在Spring Boot项目中整合iTextPDF库来导出PDF文件,包括写入大文本和HTML代码,并分析了几种常用的Java PDF导出工具。
404 0
spring boot 整合 itextpdf 导出 PDF,写入大文本,写入HTML代码,分析当下导出PDF的几个工具
|
1月前
|
监控 Java Maven
springboot学习二:springboot 初创建 web 项目、修改banner、热部署插件、切换运行环境、springboot参数配置,打包项目并测试成功
这篇文章介绍了如何快速创建Spring Boot项目,包括项目的初始化、结构、打包部署、修改启动Banner、热部署、环境切换和参数配置等基础操作。
120 0
|
1月前
|
NoSQL Java 数据库连接
springBoot:整合其他框架&condition&切换web配置 (五)
本文档介绍了如何在Spring Boot项目中整合JUnit、Redis和MyBatis等框架,并提供了相应的依赖配置示例。同时,还展示了如何通过条件注解实现Bean的条件创建,以及如何切换Web服务器配置,从默认的Tomcat切换到Jetty。
|
3月前
|
Java Spring Apache
Spring Boot邂逅Apache Wicket:一次意想不到的完美邂逅,竟让Web开发变得如此简单?
【8月更文挑战第31天】Apache Wicket与Spring Boot的集成提供了近乎无缝的开发体验。Wicket以其简洁的API和强大的组件化设计著称,而Spring Boot则以开箱即用的便捷性赢得开发者青睐。本文将指导你如何在Spring Boot项目中引入Wicket,通过简单的步骤完成集成配置。首先,创建一个新的Spring Boot项目并在`pom.xml`中添加Wicket相关依赖。
95 0
|
3月前
|
Java Spring 开发者
Java Web开发新潮流:Vaadin与Spring Boot强强联手,打造高效便捷的应用体验!
【8月更文挑战第31天】《Vaadin与Spring Boot集成:最佳实践指南》介绍了如何结合Vaadin和Spring Boot的优势进行高效Java Web开发。文章首先概述了集成的基本步骤,包括引入依赖和配置自动功能,然后通过示例展示了如何创建和使用Vaadin组件。相较于传统框架,这种集成方式简化了配置、提升了开发效率并便于部署。尽管可能存在性能和学习曲线方面的挑战,但合理的框架组合能显著提升应用开发的质量和速度。
65 0
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
143 1
|
17天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
95 62

热门文章

最新文章