Springboot集成Easyexcel

java后端导入、导出excel,因此在此记录学习一下如何使用Springboot整合easyExcel。

JAVA解析Excel工具Easyexcel

解析、生成Excel比较有名的框架有apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,POI有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大.EASYEXCEL重写了POI对07版Excel的解析,能够原本一个3M的Excel用POI SAX依然需要100 m左右内存降低到几M,并且再大的EXCEL不会出现内存溢出,03版依赖POI的SAX模式。在上层做了模型转换的封装,让使用者更加简单方便

pom

在pom文件中添加依赖

<!-- easyexcel相关依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>1.1.1</version>
        </dependency>

excel导出

(1)user实体类

//@Data是lombok的一个注解,加上它会自动生成getter、setter方法
@Data
public class User extends BaseRowModel {
    @ExcelProperty(value = "ID", index = 0)
    private String id;
    @ExcelProperty(value = "姓名", index = 1)
    private String name;
    @ExcelProperty(value = "年龄", index = 2)
    private Integer age;
}

(2)Usercontroller

@GetMapping("/user/excel")
    public void excelExport(HttpServletResponse response) throws IOException {
        userService.excelExport(response);
    }

(3)Userservice

//导出excle
    public void excelExport(HttpServletResponse response) throws IOException {
        ExcelWriter writer = null;
        // 文件输出位置
        OutputStream out = null;
        try {
            List<User> userList = userMapper.getAllUser();
            out = response.getOutputStream();
            writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
            String fileName = "用户信息表格";
            // 写仅有一个 Sheet 的 Excel 文件, 此场景较为通用
            Sheet sheet = new Sheet(1, 0, User.class);
            // 第一个 sheet 名称
            sheet.setSheetName("用户信息");
            // 写数据到 Writer 上下文中
            // 入参1: 数据库查询的数据list集合
            // 入参2: 要写入的目标 sheet
            writer.write(userList, sheet);
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName + ".xlsx").getBytes(), "ISO8859-1"));
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                // 将上下文中的最终 outputStream 写入到指定文件中
                writer.finish();
            }
            if (out != null) {
                try {
                    // 关闭流
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

excel导入

(1)Usercontroller

//导入excle
    @PostMapping("/user/excelImport")
    public String excelImport(@RequestParam("file") MultipartFile file) throws IOException {
        userService.excelImport(file);
        return "success";
    }

(2)Userservice

//导入excle
    public void excelImport(MultipartFile file) throws IOException {
        if(!file.getOriginalFilename().equals("用户名单.xls") && !file.getOriginalFilename().equals("用户名单.xlsx") ){
            return;
        }
        InputStream inputStream = new BufferedInputStream(file.getInputStream());
        //实例化实现了AnalysisEventListener接口的类
        ExcelListener excelListener = new ExcelListener(userMapper);
        ExcelReader reader = new ExcelReader(inputStream,null,excelListener);
        //读取信息
        reader.read(new Sheet(1,1,User.class));
    }

(3)ExcelListener

public class ExcelListener extends AnalysisEventListener<User> {
    private List<User> datas = new ArrayList<>();
    private static final int BATCH_COUNT = 3000;
    private UserMapper userMapper;

    public ExcelListener(UserMapper userMapper){
        this.userMapper = userMapper;
    }

    @Override
    public void invoke(User user, AnalysisContext analysisContext) {
        //数据存储到datas,供批量处理,或后续自己业务逻辑处理。
        datas.add(user);
        //达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if(datas.size() >= BATCH_COUNT){
            saveData();
            // 存储完成清理datas
            datas.clear();
        }
    }

    private void saveData() {
        for(User user : datas){
            userMapper.insert(user);
        }
    }

    public List<User> getDatas() {
        return datas;
    }

    public void setDatas(List<User> datas) {
        this.datas = datas;
    }

    /**
     * 所有数据解析完成了 都会来调用
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        saveData();//确保所有数据都能入库
    }
}

参考链接:https://blog.csdn.net/Felix_ar/article/details/103480950

发布了34 篇原创文章 · 获赞 1 · 访问量 3154

猜你喜欢

转载自blog.csdn.net/weixin_43700342/article/details/104872555
今日推荐