快速整合EasyExcel实现Excel的上传下载

1.EasyExcel
2.Excel的上传(读Excel)
3.Excel的下载(写Excel)
4.结语

1.EasyExcel

首先,这里给出EasyExcel的官方文档:https://easyexcel.opensource.alibaba.com/
alibaba.com不用我多说了吧,大家都认识,这个东西就是阿里开发的:EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。(这段话听着好牛的样子,没错,官方给出的你说呢)
那么由于下面的案例中,涉及到Excel表格的样式问题,所以我这里采用了 EasyExcel
3.1.x的版本。https://easyexcel.opensource.alibaba.com/docs/current/ 开始吧,👇👇👇

2.Excel的上传(读Excel)

我这里首先给大家分享一下SpringBoot结合EasyExcel实现对 Excel 中数据的读取,并且将读取到的数据存入MySQL数据库。
说到这里,要加什么依赖大家肯定都心知肚明了。😄😄😄

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
 
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.9</version>
        </dependency>
 
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
 
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.1.1</version>
        </dependency>
 
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.28</version>
        </dependency>

既然要读取Excel,同时存入数据库,那么就必然需要对应的表了,这就引出了 表对应的实体类。 我这里写了两个,这是因为 Excel
对应了一个类,而数据库表对应的是另外一个,原因考虑到可能Excel表格会增加一些不必要的字段,而这些字段并不需要存入数据库中(反过来也是一样,可能数据库实体类中有10个字段,而Excel这边仅有6个字段,而剩余的4个字段我们可能会从其他渠道获取)。
上面我说的可能是在公司实际开发中会遇到的某些场景吧,但是为了方便大家理解,这两个类我还是定义的相同的字段。

package com.distributeredis.redis_springboot.springbooteasyexcel.vo;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class GoodsExcelDTO {
    @ExcelProperty(index = 0)
    private Integer id;
    @ExcelProperty(index = 1)
    private String name;
    @ExcelProperty(index = 2)
    private String info;
    @ExcelProperty(index = 3)
    @DateTimeFormat(value = "yyyy-MM-dd HH:mm:ss")
    private String buyTime;
}
package com.distributeredis.redis_springboot.springbooteasyexcel.vo;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Goods {
    private Integer id;
    private String name;
    private String info;
    //@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    @DateTimeFormat(value = "yyyy-MM-dd HH:mm:ss")
    private Date buyTime;
}

Excel对应的类中 buyTime是 String类型,而数据库实体类的 buyTime是Date类型,这是因为:👇👇👇
(阿里官方文档给出的规定)
在这里插入图片描述

下面给出goods这张表的sql脚本。

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
 
-- ----------------------------
-- Table structure for goods
-- ----------------------------
DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '商品名称',
  `info` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '商品信息',
  `buyTime` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '购买时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
 
-- ----------------------------
-- Records of goods
-- ----------------------------
INSERT INTO `goods` VALUES (1, 'Java核心技术卷I', 'Java四大名著之一', '2021-12-01 13:05:23');
INSERT INTO `goods` VALUES (2, 'Java核心技术卷II', 'Java四大名著之一', '2022-02-28 09:21:55');
INSERT INTO `goods` VALUES (3, 'Java编程思想', 'Java四大名著之一', '2020-05-15 14:16:18');
INSERT INTO `goods` VALUES (4, 'Effective Java', 'Java四大名著之一', '2022-07-06 22:33:44');
INSERT INTO `goods` VALUES (5, '深入理解Java虚拟机', 'JVM由此开始', '2021-06-06 20:59:37');
INSERT INTO `goods` VALUES (6, 'SpringBoot实战应用教程', 'SpringBoot极速开发框架', '2020-03-17 10:02:31');
INSERT INTO `goods` VALUES (7, '快速上手SSM', '一本优秀的书籍', '2021-08-14 19:08:26');
INSERT INTO `goods` VALUES (8, 'MySQL是怎样运行的', '深入学习MySQL', '2022-04-09 15:37:05');
INSERT INTO `goods` VALUES (9, 'Java并发编程', '并发编程之美', '2020-01-18 21:12:13');
INSERT INTO `goods` VALUES (10, 'Java从入门到精通', '小白的Java之路', '2021-09-11 17:18:21');
 
SET FOREIGN_KEY_CHECKS = 1;

大家参考官方文档之后,肯定知道,针对Excel的读,我们需要写一个监听器,去不断的监听读取Excel的每一行数据,最终加入数据库类似这样的操作。
下面就是监听器代码。 有个很重要的点 DemoDataListener
不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去。这也就是监听器中需要声明
private GoodsService goodsService; 这个成员变量的原因。
invoke 方法:解析Excel中的每一条数据都会来调用它。
invokeHead 方法:针对Excel表头的一些操作。
doAfterAllAnalysed 方法:所有数据解析完成了会来调用它。

package com.distributeredis.redis_springboot.springbooteasyexcel.write.goodListener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ConverterUtils;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import com.distributeredis.redis_springboot.springbooteasyexcel.vo.Goods;
import com.distributeredis.redis_springboot.springbooteasyexcel.vo.GoodsExcelDTO;
import com.distributeredis.redis_springboot.springbooteasyexcel.write.service.GoodsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Excel模板的读取类
 * 有个很重要的点 DemoDataListener 不能被spring管理
 * 要每次读取excel都要new, 然后里面用到spring可以构造方法传进去
 */
@Slf4j
public class GoodsListener implements ReadListener<GoodsExcelDTO> {
    @Autowired
    private GoodsService goodsService;

    private List<GoodsExcelDTO> goodsExcelDTOList = ListUtils.newArrayList();
    private final List<Goods> goodsList = ListUtils.newArrayList();
    private int count = 0;

    public GoodsListener() {
    }

    public GoodsListener(GoodsService goodsService) {
        this.goodsService = goodsService;
    }

    @Override
    public void invoke(GoodsExcelDTO goodsExcelDTO, AnalysisContext analysisContext) {
        log.info("解析到第 {} 条数据:{}", (++count), JSON.toJSONString(goodsExcelDTO));
        goodsExcelDTOList.add(goodsExcelDTO);
    }

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        Map<Integer, String> stringMap = ConverterUtils.convertToStringMap(headMap, context);
        Set<Integer> keySet = stringMap.keySet();
        System.out.println("该Excel表头信息是:");
        for (int i = 0; i < keySet.size(); i++) {
            System.out.println("第 " + (i + 1) + " 列 = " + stringMap.get(i));
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("该Excel的所有数据解析完成!!!");
        goodsExcelDTOList.forEach(item -> {
            try {
                Goods goods = new Goods();
                goods.setId(item.getId());
                goods.setName(item.getName());
                goods.setInfo(item.getInfo());
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = sdf.parse(item.getBuyTime());
                goods.setBuyTime(date);
                goodsList.add(goods);
            } catch (ParseException e) {
                log.error(e.getMessage());
            }
        });
        goodsExcelDTOList = ListUtils.newArrayList();
        goodsService.batchInsert(goodsList);
    }
}

好的,下面就是我们的mapper、service、controller了。这都是大家很熟悉的东西了。

package com.distributeredis.redis_springboot.springbooteasyexcel.write.mapper;
import com.distributeredis.redis_springboot.springbooteasyexcel.vo.Goods;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface GoodsMapper {
    /**
     * 批量插入
     */
    void batchInsert(List<Goods> goodsList);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.distributeredis.redis_springboot.springbooteasyexcel.write.mapper.GoodsMapper">
    <!-- 使用insert、update、delete、select标签编写sql语句 -->

    <insert id="batchInsert" parameterType="java.util.List">
        insert into goods
        values
        <foreach collection="list" item="item" index="index" separator=",">
            (#{item.id}, #{item.name}, #{item.info}, #{item.buyTime})
        </foreach>
    </insert>
</mapper>
package com.distributeredis.redis_springboot.springbooteasyexcel.write.service;
import com.distributeredis.redis_springboot.springbooteasyexcel.vo.Goods;
import java.util.List;
public interface GoodsService {
    void batchInsert(List<Goods> goodsList);
}

package com.distributeredis.redis_springboot.springbooteasyexcel.write.service.impl;

import com.distributeredis.redis_springboot.springbooteasyexcel.vo.Goods;
import com.distributeredis.redis_springboot.springbooteasyexcel.write.mapper.GoodsMapper;
import com.distributeredis.redis_springboot.springbooteasyexcel.write.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
@Service
public class GoodsServiceImpl implements GoodsService {
    @Autowired
    private GoodsMapper goodsMapper;
    @Override
    @Transactional
    public void batchInsert(List<Goods> goodsList) {
        this.goodsMapper.batchInsert(goodsList);
    }
}
package com.distributeredis.redis_springboot.springbooteasyexcel.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.fastjson.JSON;
import com.distributeredis.redis_springboot.springbooteasyexcel.read.service.StudentService;
import com.distributeredis.redis_springboot.springbooteasyexcel.read.vo.StudentExcelDTO;
import com.distributeredis.redis_springboot.springbooteasyexcel.vo.GoodsExcelDTO;
import com.distributeredis.redis_springboot.springbooteasyexcel.write.goodListener.GoodsListener;
import com.distributeredis.redis_springboot.springbooteasyexcel.write.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping(value = "/excel")
public class EasyExcelController {
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private StudentService studentService;

    /**
     * 文件excel上传
     */
    @PostMapping(value = "/upload")
    public String upload(MultipartFile file) throws Exception {
        EasyExcel.read(file.getInputStream(), GoodsExcelDTO.class, new GoodsListener(goodsService)).sheet().headRowNumber(1).doRead();
        return "success";
    }
    /**
     * Excel文件下载
     */
    @GetMapping(value = "/download")
    public void download(HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        //这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("学生信息表", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        List<StudentExcelDTO> studentList = studentService.queryAllStudents();
        EasyExcel.write(response.getOutputStream(), StudentExcelDTO.class).sheet("sheet1").doWrite(studentList);
    }

    /**
     * Excel文件下载并且失败的时候返回json
     */
    @GetMapping(value = "/downloadFailedUsingJson")
    public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            //这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("学生信息表", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            List<StudentExcelDTO> studentList = studentService.queryAllStudents();
            EasyExcel.write(response.getOutputStream(), StudentExcelDTO.class).autoCloseStream(Boolean.FALSE).sheet("sheet1").doWrite(studentList);
        } catch (Exception e) {
            //重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = MapUtils.newHashMap();
            map.put("status", "failure");
            map.put("message", "Excel文件下载失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
        }
    }
}

再然后就是SpringBoot的核心配置文件和主启动类。

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mysql_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
    username: root
    password: 123456
  application:
    name: RedisDemo
  #Redis????
  redis:
    host: localhost
    port: 6379
    #password: 123456
    database: 0 #????0????
    jedis:
      #Redis?????
      pool:
        max-active: 8 #?????
        max-wait: 1ms #???????????
        max-idle: 4 #???????????
        min-idle: 0 #???????????

由于这是上传操作,所以我这里也给大家提供我创建的Excel文档。可以看到和上面的goods表的字段都是对应好的。
在这里插入图片描述

下面我们启动项目,在postman中对上传Excel接口进行测试。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.Excel的下载(写Excel)

这里仍然用到的和上面的读Excel是同一个SpringBoot项目,所以依赖、核心配置文件、主启动类这些都是一样的,就不再给出了,大家参考上面的就行了。
那么对于Excel的下载,也就是说向Excel中写入数据,相较于上传操作就要简单多了。 来看下面的步骤:👇👇👇
这里模拟的场景是:从数据库中的某张表获取到对应的数据集,然后将这个List集合写入Excel中。
所以自然也是需要实体类,那么和上面的上传操作一样,我仍然是创建两个类,一个是Excel表格对应的实体类,另一个是我们数据库对应的实体类。

package com.distributeredis.redis_springboot.springbooteasyexcel.read.vo;
 
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.*;
import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
/**
 * 类上面的注解,来自lombok和EasyExcel官方,用来自定义表头、宽度等信息
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ColumnWidth(25)
@HeadRowHeight(30)
@ContentRowHeight(20)
@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)
public class StudentExcelDTO {
 
    @ExcelProperty({"学生综述", "学生编号"})
    private Integer id;
 
    @ExcelProperty({"学生综述", "学生姓名"})
    private String name;
 
    @ExcelProperty({"学生综述", "学生年龄"})
    private Integer age;
 
    @ExcelProperty({"学生综述", "学生爱好"})
    private String hobby;
 
    @ExcelIgnore
    private String address;
}
package com.distributeredis.redis_springboot.springbooteasyexcel.read.vo;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
/**
 *
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
 
    private Integer id;
 
    private String name;
 
    private Integer age;
 
    private String hobby;
 
    private String address;
}

student这张表的sql脚本,我也给到大家。

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
 
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键,暂定学生编号',
  `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '学生姓名',
  `age` int(11) NOT NULL COMMENT '学生年龄',
  `hobby` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '学生爱好',
  `address` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '学生住址',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
 
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, '张三', 41, '睡觉', '湖北省武汉市');
INSERT INTO `student` VALUES (2, '李四', 66, '吃饭', '湖南省长沙市');
INSERT INTO `student` VALUES (3, '王五', 28, '打游戏', '江苏省南京市');
INSERT INTO `student` VALUES (4, '赵六', 35, '玩手机', '浙江省杭州市');
INSERT INTO `student` VALUES (5, '田七', 52, '旅游', '上海市黄浦区');
INSERT INTO `student` VALUES (6, '小哥', 22, '盗墓', '河南省洛阳市');
INSERT INTO `student` VALUES (7, '张起灵', 18, '倒斗', '北京市海淀区');
INSERT INTO `student` VALUES (8, '闷油瓶', 20, '挖坟', '广东省深圳市');
 
SET FOREIGN_KEY_CHECKS = 1;

下面就是我们的mapper、service、controller了,还是大家熟悉的那一套。

package com.distributeredis.redis_springboot.springbooteasyexcel.read.mapper;
 
import com.distributeredis.redis_springboot.springbooteasyexcel.read.vo.Student;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface StudentMapper {
 
    /**
     * 获取学生列表
     */
    List<Student> queryAllStudents();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.distributeredis.redis_springboot.springbooteasyexcel.read.mapper.StudentMapper">
    <!-- 使用insert、update、delete、select标签编写sql语句 -->

    <sql id="student_column_list">
        id, name, age, hobby, address
    </sql>

    <resultMap id="studentMap" type="com.distributeredis.redis_springboot.springbooteasyexcel.read.vo.Student">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="age" property="age"></result>
        <result column="hobby" property="hobby"></result>
        <result column="address" property="address"></result>
    </resultMap>

    <select id="queryAllStudents" resultMap="studentMap">
        select <include refid="student_column_list"/>
        from student
    </select>

</mapper>
package com.distributeredis.redis_springboot.springbooteasyexcel.read.service;
 
import com.distributeredis.redis_springboot.springbooteasyexcel.read.vo.StudentExcelDTO;

import java.util.List;
 
/**
 *
 */
public interface StudentService {
 
    List<StudentExcelDTO> queryAllStudents();
}
package com.distributeredis.redis_springboot.springbooteasyexcel.read.service.impl;

import com.distributeredis.redis_springboot.springbooteasyexcel.read.mapper.StudentMapper;
import com.distributeredis.redis_springboot.springbooteasyexcel.read.service.StudentService;
import com.distributeredis.redis_springboot.springbooteasyexcel.read.vo.Student;
import com.distributeredis.redis_springboot.springbooteasyexcel.read.vo.StudentExcelDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentMapper studentMapper;

    @Override
    public List<StudentExcelDTO> queryAllStudents() {
        List<Student> studentList = studentMapper.queryAllStudents();
        List<StudentExcelDTO> students = new ArrayList<>();
        studentList.forEach(item -> {
            StudentExcelDTO student = new StudentExcelDTO();
            BeanUtils.copyProperties(item, student);
            students.add(student);
        });
        return students;
    }
}

核心配置文件、主启动类这些都是和上面的案例一样的,就不再给出了。 下面直接启动项目,在postman中进行测试。
这里大家注意一下,有的小伙伴可能直接点了Send,然后postman反馈了一堆乱码,但是此时把接口地址拿到浏览器中是可以直接访问的。
解决办法就是:点击下图中的 Send and Download。

在这里插入图片描述
在这里插入图片描述

保存之后,我们的Excel下载接口就可以正常跑通,下面就是下载成功的Excel了。😄😄😄
在这里插入图片描述

4.结语

> 上面的两个案例就是SpringBoot整合EasyExcel,实现Excel的读写(上传下载)的操作。
> 我这里所有的整合步骤均来自阿里的EasyExcel官方文档,所以大家有什么疑问都可以去官方文档中查找,地址在文章开头已经给出了。
> 或者大家也可以在文章下面评论,我都会一一回复的,和大家一起讨论技术话题。😄😄😄 ```

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/231735.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023-12-05 Qt学习总结2

点击 <C 语言编程核心突破> 快速C语言入门 Qt学习总结 前言五 Hello Qt!六 Qt控件和事件七 Qt信号和槽八 Qt自定义信号和槽总结 前言 要解决问题: 学习qt最核心知识, 多一个都不学. 五 Hello Qt! 现在我们已经有了一个空窗口工程, 传统上, 我们要实现一个"Hello …

HXDSP2441-Demo板

板卡图示 下图为HXDSP2441DEMO板&#xff0c;HXDSP2441DEMO板是围绕HXDSP2441构建的芯片演示验证平台。 板卡简介 除了为HXDSP2441芯片提供供电、时钟、储存、网络及调试电路&#xff0c;来实现芯片最基本的功能&#xff0c;也添加了相关模块以搭建HXDSP2441的典型应用场景…

活久见—当设置不同坐标系统时,ArcMap中的图形相关位置关系会变化

这两天一件十分神奇的事情发生了&#xff1a;当设置不同坐标系统时&#xff0c;ArcMap中的图形相对位置关系会变化。 事情起因是这样的&#xff1a;博主和同行用ArcMap同时验证2个相邻多边形的相对位置关系&#xff0c;见下图图1和图2的多边形&#xff0c;在博主的ArcMap中&am…

快速登录界面关于如何登录以及多账号列表解析以及config配置文件如何读取以及JsLogin模块与SdoLogin模块如何通信(4)

1、### Jslogin模块与前端以及JsLogin模块与Sdologin的交互 配置文件的读取: <CompanyIdForQq value"301"/> <CompanyIdForWx value"300"/><CompanyIdForWb value"302"/><qq value"https://graph.qq.com/oauth2.0/au…

爱智EdgerOS之深入解析如何应用爱智的视频流模块完成拉流

一、ONVIF 规范和常见视频流传输协议 ① ONVIF 规范 随着视频监控产业链的成熟&#xff0c;市面上陆陆续续出现了各式各样的网络摄像设备&#xff0c;这些设备都需要通讯协议才能进行数据传输。早期厂商都采用私有协议&#xff0c;但是现在厂商分工明确&#xff0c;有的负责生…

计算机毕业设计springboot+ssm停车场车位预约系统java

管理员不可以注册账号 停车位包括车位所在楼层、车位编号、车位类型(全时间开放/高峰期开放)、预定状态等 用户预约时要求支付预约时间段的停车费用 违规行为&#xff1a;1.停车超过预约时间段 2.预约未使用 于系统的基本要求 &#xff08;1&#xff09;功能要求&am…

【go-zero】go-zero使用ent框架 如何使用源生sql完成查询

背景 本篇教程我们采用的是go-zero的快速脚手架工具 simple-admin 框架的开发 github地址:https://github.com/suyuan32/simple-admin-core 因为框架推荐使用Ent 这篇教程我们则对Ent的基本使用的几种形式进行一个总结 一、开启ent的源生sql 1、simple-admin生成rpc 【go-…

BUUCTF [CISCN2019 华北赛区 Day2 Web1]Hack World 1(SQL注入之布尔盲注)

题目环境判断注入类型 1 2 3 1’ 输入1’报错提示bool(false) 可知是字符型的布尔注入&#xff08;盲注&#xff09; 尝试万能密码 1’ or ‘1’1 已检测SQL注入 猜测某些关键字或者字符被过滤 FUZZ字典爆破 可以看到部分关键字被过滤&#xff0c;包括空格 All You Want Is In …

[面试题~Docker] 云原生必问基础篇

文章目录 基础相关1. Docker 是什么&#xff1f;2. 镜像是什么3. 容器是什么4. 数据卷是什么5. Docker 和虚拟机的区别&#xff1f;6. Docker 常用命令有哪些&#xff1f; 原理相关1. docker 有几种网络模式host 模式container模式none模式bridge模式 2. docker 网络实现在Linu…

AWTK 串口屏开发(1) - Hello World

1. 功能 这个例子很简单&#xff0c;制作一个调节温度的界面。在这里例子中&#xff0c;模型&#xff08;也就是数据&#xff09;里只有一个温度变量&#xff1a; 变量名数据类型功能说明温度整数温度。范围 (0-100) 摄氏度 2. 创建项目 从模板创建项目&#xff0c;将 hmi/…

物奇平台CLI MIC切换对应ADC关系

是否需要申请加入数字音频系统研究开发交流答疑群(课题组)&#xff1f;可加我微信hezkz17, 本群提供音频技术答疑服务&#xff0c;群赠送语音信号处理降噪算法&#xff0c;蓝牙耳机音频&#xff0c;DSP音频项目核心开发资料, 物奇平台CLI MIC切换对应ADC关系 1 发送CLI指令…

tqdm详细教程,实现tqdm进度条完美设计;解决进度条多行一直刷新的问题;如何使得滚动条不上下滚动(保持一行内滚动)

一、tqdm简介 tqdm是一个python进度条库&#xff0c;可以在 Python长循环中添加一个进度提示信息。 二、3种使用方法 1.tqdm(range)-自动更新 import time from tqdm import range# 自动更新 for i in tqdm(range(10)): # 共可以更新10次进度条time. Sleep(0.5) # 每次更新间…

leetcode系列:反转链表的形象表示

反转链表是一道比较简单的题&#xff0c;主要考察的是对链表数据结构的理解和双指针应用&#xff0c;比较容易出错的地方是指针的移动顺序。在练习的过程中想到了一个比较形象的表示方法&#xff0c;于是记录下来。 # Definition for singly-linked list. # class ListNode: #…

高效便捷的淘宝商品详情关键词搜索API接口

联讯数据可以介绍一些高效便捷的淘宝商品详情关键词搜索API接口。 以下是一些可以考虑使用的API接口&#xff1a; 阿里云搜索引擎API&#xff1a;阿里云搜索引擎API是一个基于云计算技术的搜索引擎&#xff0c;提供商品详情关键词搜索功能。它支持中文搜索&#xff0c;并且具…

听GPT 讲Rust源代码--src/tools(12)

File: rust/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs 在Rust源代码中&#xff0c;rust/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs文件的作用是定义和解析rust-analyzer的配置文件。该文件包含了各种配置项的数据结构和枚举类型&#xf…

Mysql、Oracle安全项检查表及操作脚本

软件开发全资料获取&#xff1a;点我获取 Mysql检查表 Oracle检查表

基于微群机器人的二次开发

请求URL&#xff1a; http://域名地址/modifyGroupName 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说明wId是String登录实例标识chatRoom…

vue3自定义路由栈pinia+vue-router来实现

我们知道vue-router使用push跳转可以通过浏览器的返回箭头&#xff0c;就能回到上一页&#xff0c;是因为它有路由栈&#xff0c;每次跳转都会存放&#xff08;记录&#xff09;当前路由的相关信息。 根据这个思路我们利用piniavue-router 来自定义路由栈。 说下项目中 自定义…

前端知识(九)------------JavaScript底层知识

1.事件循环机制 在实际的编码过程中小伙伴们不知道有没有遇到过这样的问题&#xff0c;我们都知道js是单线程的。而且是一门解释型语言。那么正常来讲执行代码的顺序就是自上而下一句一句执行对吧 但是有的时候我们发现返回的结果并不是自上而下执行的。我们先写了一段代码 …

国产化软件突围!怿星科技eStation产品荣获2023铃轩奖“前瞻优秀奖”

11月11日&#xff0c;2023中国汽车供应链峰会暨第八届铃轩奖颁奖典礼在江苏省昆山市举行。怿星科技凭借eStation产品&#xff0c;荣获2023铃轩奖“前瞻智能座舱类优秀奖”&#xff0c;怿星CEO潘凯受邀出席铃轩奖晚会并代表领奖。 2023铃轩奖“前瞻智能座舱类优秀奖” 铃轩奖&a…