【springboot+vue项目(十一)】springboot整合EasyExcel

        EasyExcel是阿里巴巴开源的一个Java库,用于操作Excel文件。它提供了简单易用的API,可以读取、写入和转换Excel文件,支持大量数据的导入和导出操作。

一、添加依赖(版本3.2)



    com.alibaba
    easyexcel
    3.2.0

二、根据Excel来建立数据库表

        根据Excel的表头建立数据库表,注意每一张表有2个字段需要添加,即id和period(账期),建在最前面,此项工作可以借助chatgpt来完成

三、快速生成代码

        使用EasyCode 快速生成代码entity、service、mapper、servicelmpl

【springboot+vue项目(十一)】springboot整合EasyExcel_第1张图片

四、修改实体类entity

修改实体类entity,添加“账期”字段的自动插入

【springboot+vue项目(十一)】springboot整合EasyExcel_第2张图片

五、类继承、引用的方法引入

entity、service、mapper.、servicelmpl类继承、引用的方法引入,使用Alt+Enter键

六、easyExcel的model和listeners

package com.pbcnn.easyExcelCollector.excel.model;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

import java.math.BigDecimal;

@Data
public class SheetSucffiBwbModel {

    @ExcelProperty(index = 1)
    private String indexName;

    @ExcelProperty(index = 2)
    private BigDecimal currentBalance;

    @ExcelProperty(index = 3)
    private BigDecimal currentMonthChange;

    @ExcelProperty(index = 4)
    private BigDecimal currentYearChange;

    @ExcelProperty(index = 5)
    private BigDecimal yearChangeRate;

    @ExcelProperty(index = 6)
    private BigDecimal lastYearBalance;

    @ExcelProperty(index = 7)
    private BigDecimal lastTwoYearsBalance;

    @ExcelProperty(index = 8)
    private BigDecimal lastYearGrowthRate;

}
package com.pbcnn.easyExcelCollector.excel.listeners;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson2.JSON;
import com.pbcnn.easyExcelCollector.common.SpringUtil;
import com.pbcnn.easyExcelCollector.entity.data.User;
import com.pbcnn.easyExcelCollector.excel.model.ExcelUserData;
import com.pbcnn.easyExcelCollector.mapper.UploadFileMapper;
import com.pbcnn.easyExcelCollector.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**
 * ExcelModelListener 不能被spring管理,要每次读取 excel 都要 new,然后里面用到 spring 可以构造方法传进去
 *
 * @author makejava
 * @create 2023-01-19 20:59
 */
@Slf4j
public class UserDataListener implements ReadListener {


    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理 list ,方便内存回收,避免 OOM
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据,在 invoke 函数中存储每次读到的数据,这里的泛型虽业务变化而变化,存储的可以是excel表数据处理后的数据
     * 假如我要啊存入数据库中就需要将 ExcelUserData 转换成 User 那么这里的泛型就是User,在 invoke 中处理后添加
     */
    private List cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    /**
     * 这个是一个DAO,当然有业务逻辑这个也可以是一个service。可以用来解析数据后操作数据库
     */
    @Autowired
    private UserService userService;

    @Autowired
    private UploadFileMapper uploadFileMapper;

    /**
     * 每读到一条数据都会调用这个函数,可以在这里对数据的预处理
     *
     * @param excelUserData
     * @param analysisContext
     */
    @Override
    public void invoke(ExcelUserData excelUserData, AnalysisContext analysisContext) {
        log.info("解析到一条数据:{}", JSON.toJSONString(excelUserData));
        cachedDataList.add(excelUserData);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            log.info("已达到BATCH_COUNT,共{}条数据", cachedDataList.size());

            // 调用储存数据函数
            saveData();

            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用 做收尾工作,确保最后遗留的数据也持久化(存储到数据库)
     *
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());

        //  TODO 数据存储,使用批处理操作防止多次连接数据库,例如 userService.saveBatch();
        if (cachedDataList.size() > 0) {
            List userList = BeanUtil.copyToList(cachedDataList, User.class, null);
            UserService userService = SpringUtil.getBean(UserService.class);
            userService.saveBatch(userList);
        }

        log.info("存储数据库成功!");
    }

}

添加的时候:

  1. model,复制entity的类,然后添加@ExcelProperty(index = 1),去掉id和period(账期)
  2. Listeners,直接复制其他类,然后将类的名字替换掉即可。

七、controller 解析Excel

package com.pbcnn.easyExcelCollector.controller;

import com.alibaba.excel.EasyExcel;
import com.pbcnn.easyExcelCollector.excel.listeners.UserDataListener;
import com.pbcnn.easyExcelCollector.excel.model.ExcelUserData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

@RestController
public class UploadController {

    @Value("${file.upload-dir}")
    private String uploadDir;


    @PostMapping(value = "/uploadFiles", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity upload(@RequestParam("files") MultipartFile[] files) {
        try {
            List fileNames = new ArrayList<>();
            for (MultipartFile file : files) {
                if (!file.isEmpty()) {
                    String fileName = UUID.randomUUID().toString() + "_" + StringUtils.cleanPath(file.getOriginalFilename());
                    Path dest = Path.of(uploadDir, fileName);
                    try (InputStream inputStream = file.getInputStream()) {
                        Files.copy(inputStream, dest, StandardCopyOption.REPLACE_EXISTING);
                    }
                    fileNames.add(fileName);

                    // 异步保存上传信息到数据库
                    //CompletableFuture.runAsync(() -> {
                    //    UploadFile uploadFile = new UploadFile();
                    //    uploadFile.(fileName);
                    //    uploadFile.setFilePath(dest.toString());
                    //    uploadFile.setUploadTime(new Date());
                    //    uploadFile.setStatus(0);
                    //    uploadFileMapper.insert(uploadFile);
                    //});

                    /*
                        根据文件路径读取excel
                     */
                    String pathName = dest.toString();
                    CompletableFuture.runAsync(() -> {
                        EasyExcel.read(pathName, ExcelUserData.class, new UserDataListener()).sheet().doRead();

                    });
                }
            }
            return ResponseEntity.ok(fileNames);
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("上传文件失败");
        }
    }
}

你可能感兴趣的:(vue.js,spring,boot,java)