SpringBoot 解析前端上传的 Excel文件并导入数据库 --- 稍作优化(范型巧用)

一、准备工作:

  • pom.xml 导入相应解析Excel文件依赖包
<!--解析excel-->
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>4.0.1</version>
		</dependency>

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>4.0.1</version>
		</dependency>
  • 准备一份Excel模板
    在这里插入图片描述
  • 准备SQL数据库表
    在这里插入图片描述

二、优化点:

ExcelUtil 工具类定义为范型类,使得ExcelUtil可以解析任何Excel文件并且封装到相对应的实体类再放入LIst集合中,执行动态SQL语句插入数据库中,达到一个解析工具的多次复用。


三、代码实现:

1. Controller 层:

/**
    *@ClassName: StudentController
    *@Description: 上传excel
    *@Params: file
    *@Return:
    *@Author xxw
    *@Date 2020/12/15
    */

    @PostMapping("/uploadExcel")
    public Msg uploadExcel(@RequestParam("file")MultipartFile file) throws IOException {
    
    
        String fileName = file.getOriginalFilename(); // 获取文件名

        InputStream is = null;

        try{
    
    
            is = file.getInputStream();
            List<Map> studentList = studentService.getListByExcel(is,fileName);// 获取解析后的List集合
			// System.out.println(studentList.toString());
            Boolean result = studentService.batchImportStuInfo(studentList); // 把数据插入数据库
            if (result){
    
    
                return Msg.sussess().add("info", "文件上传成功!");
            }else {
    
    
                return Msg.failure().add("info", "文件上传失败!");
            }
        }catch (Exception e){
    
    
            e.printStackTrace();
        } finally {
    
    
            is.close();
        }
        return Msg.failure().add("info", "文件错误!");
    }

2. Service 层:

public List<Map> getListByExcel(InputStream is,String fileName) throws IOException {
    
    

        try{
    
    
            List<Map> studentList = new ExcelUtil(new Student()).AnalysisExcel(is, fileName);
            return studentList;
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
        return new ArrayList<>();
    }
public Boolean batchImportStuInfo(List<Map> list){
    
    
        Integer flag = studentMapper.batchImportStuInfo(list);
        if (flag > 0){
    
    
            return true;
        } else return false;
    }

3. mapper 层:

package com.xxw.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;

@Repository
@Mapper
public interface StudentMapper {
    
    
    // 批量导入学生信息
    Integer batchImportStuInfo(List<Map> studentList);
}


4. ExcelUtil 工具类:

package com.xxw.utils;

/*
* 解析excel工具类
* */

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.*;

public class ExcelUtil<T> {
    
    

    // 定义范型,这样就能传对应的实体类来封装excel数据
    private T t;

    public ExcelUtil(T t) {
    
    
        this.t = t;
    }

    /**
    *@ClassName: ExcelUtil
    *@Description: 传入excel解析excel文件,提取出信息
    *@Params: InputStream is, String fileName
    *@Return:
    *@Author xxw
    *@Date 2020/12/15
    */

    public List<Map> AnalysisExcel(InputStream is, String fileName) throws IOException {
    
    

        List<Map> list = new ArrayList<>();
        Workbook workbook = createWorkbookByExcelType(is, fileName); // 创建工作簿

        Sheet sheet = workbook.getSheetAt(0);
        Row row = null;

        // 获取最大行数
        int maxRowNum = sheet.getLastRowNum();

        // 获取第一行
        row = sheet.getRow(0);

        // 获取最大列数
        int maxColNum = row.getLastCellNum();

        List<String> arrayList = new ArrayList<>();

        Field[] declaredFields = t.getClass().getDeclaredFields();

        // 把需要封装的实体类的属性名存入arrayList
        for (int i = 0; i < declaredFields.length; i++) {
    
    
            String name = declaredFields[i].getName();
            arrayList.add(name);
        }

        // 循环遍历excel表格,把每条数据封装成 map集合,再放入list集合中
        for (int i = 0; i <= maxRowNum; i++) {
    
    
            Map<String, String> map = new HashMap<>();

            row = sheet.getRow(i);

            if (row != null){
    
    
                for (int j = 0; j < maxColNum; j++) {
    
    
                    String cellData = (String)getCellFormatValue(row.getCell(j));
                    map.put(arrayList.get(j), cellData); // map 封装
                }
                list.add(map); // map存入list
            }
        }
        return list;
    }


    //根据传入的文件名后缀判断是xls还是xlsx
    public static Workbook createWorkbookByExcelType(InputStream inputStream,String fileName){
    
    
        Workbook wb = null;
        if(fileName == null){
    
    
            return null;
        }
        String extString = fileName.substring(fileName.lastIndexOf("."));
        InputStream is = null;
        try {
    
    
            is = inputStream;
            if(".xls".equals(extString)){
    
    
                return wb = new HSSFWorkbook(is); // 2003版本 .xls
            }else if(".xlsx".equals(extString)){
    
    
                return wb = new XSSFWorkbook(is); // 2007版本 .xlsx
            }else{
    
    
                return wb = null;
            }
        } catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                is.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        return wb;
    }

    // 用于获取表格中的数据方法
    public static Object getCellFormatValue(Cell cell){
    
    
        Object cellValue = null;
        if(cell!=null){
    
    
            //判断cell类型
            switch(cell.getCellType()){
    
    
                case NUMERIC:{
    
    
                    cellValue = String.valueOf(cell.getNumericCellValue());
                    break;
                }
                case FORMULA:{
    
    
                    //判断cell是否为日期格式
                    if(DateUtil.isCellDateFormatted(cell)){
    
    
                        //转换为日期格式YYYY-mm-dd
                        cellValue = cell.getDateCellValue();
                    }else{
    
    
                        //数字
                        cellValue = String.valueOf(cell.getNumericCellValue());
                    }
                    break;
                }
                case STRING:{
    
    
                    cellValue = cell.getRichStringCellValue().getString();
                    break;
                }
                default:
                    cellValue = "";
            }
        }else{
    
    
            cellValue = "";
        }
        return cellValue;
    }

}


5. Mapper.xml 映射文件:

<insert id="batchImportStuInfo" parameterType="java.util.List">
        insert into student values
        <foreach item="item" collection="list" separator=",">
            (
            #{item.id},
            #{item.stuName},
            #{item.sex},
            #{item.cardId},
            #{item.stuId},
            #{item.political},
            #{item.major},
            #{item.classGrade},
            #{item.tel},
            #{item.stuStatus}
            #{item.city}
            )
        </foreach>
    </insert>

6. application.yml 配置文件:

spring:
  servlet:
    multipart:
      max-file-size: 1000MB        #上传文件大小
      max-request-size: 1000MB     #下载文件大小

四、 代码分析:

在这里插入图片描述

MultipartFile为org.springframework.web.mutipart包下的一个类,也就是说如果想使用MultipartFile这个类就必须引入spring框架,换句话说,如果想在项目中使用MultipartFile这个类,那么项目必须要使用spring框架才可以,否则无法引入这个类。MultipartFile翻译成中文来讲就是“多组件的文档”,一般来讲使用MultipartFile这个类主要是来实现以表单的形式进行文件上传功能。


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


五、效果展示:

在这里插入图片描述


猜你喜欢

转载自blog.csdn.net/haduwi/article/details/111292886