springboot导入excel(POI)

POI官方文档

引入依赖

复制代码
        <!--POI-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.2</version>
        </dependency>

编写导入工具类

结合springboot导出(POI)用到的自定义注解,让导入使用起来更方便简洁且更容易扩展。

java 复制代码
public class ExcelImportUtil {

    /*
     * @description: 读取excel数据 <br>
     * @create: 2023/9/20 16:12 <br>
     * @param file
     * @param tClass
     * @return java.util.List<T>
     */
    public static<T> List<T> readExcel(MultipartFile file, Class<T> tClass){
        if(file.isEmpty()){
            return new ArrayList<>();
        }
        //获取列名与属性名的映射
        Map<String, String> feildMap = getFeildMap(tClass);
        if(ObjectUtils.isEmpty(feildMap)){
            return new ArrayList<>();
        }
        InputStream inputStream = null;
        Workbook workbook = null;
        try {
            //解析文件
            inputStream = file.getInputStream();
            workbook = new XSSFWorkbook(inputStream);
            Sheet sheet = workbook.getSheetAt(0);
            int lastRowNum = sheet.getLastRowNum();
            int lastCellNum = sheet.getRow(0).getLastCellNum();
            //解析表头
            Row headerRow = sheet.getRow(0);
            List<String> headerNameList = new ArrayList<>();
            for (int i = 0; i < lastCellNum; i++) {
                headerNameList.add(headerRow.getCell(i).getStringCellValue());
            }
            //读取数据
            List<Map<String, Object>> dataList = new ArrayList<>();
            for (int i = 1; i <= lastRowNum; i++) {
                Row row = sheet.getRow(i);
                Map<String, Object> rowValueMap = new HashMap<>();
                for (int j = 0; j < lastCellNum; j++) {
                    String key = feildMap.get(headerNameList.get(j));
                    Object value = getCellValue(row.getCell(j));
                    rowValueMap.put(key, value);
                }
                dataList.add(rowValueMap);
            }
            workbook.close();
            inputStream.close();
            List<T> list = convertToList(dataList);
            return list;
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(workbook != null){
                    workbook.close();
                }
                if(inputStream !=null){
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return new ArrayList<>();
    }

    /*
     * @description: 解析导入的实体,获取列名与属性名的映射 <br>
     * @create: 2023/9/20 16:27 <br>
     * @param tClass
     * @return java.util.Map<java.lang.String,java.lang.String>
     */
    private static<T> Map<String, String> getFeildMap(Class<T> tClass){
        Field[] fields = tClass.getDeclaredFields();
        if(ObjectUtils.isEmpty(fields)){
            return null;
        }
        Map<String, String> keyMap = new HashMap<>();
        for(Field field : fields){
            ExcelField excelField = field.getAnnotation(ExcelField.class);
            if(ObjectUtils.isNotEmpty(excelField)){
                keyMap.put(excelField.name(), field.getName());
            }
        }
        return keyMap;
    }

    /*
     * @description: 获取单元格的值 <br>
     * @create: 2023/9/20 16:47 <br>
     * @param cell
     * @return java.lang.Object
     */
    private static Object getCellValue(Cell cell){
        if(cell == null){
            return null;
        }
        CellType cellType = cell.getCellType();
        if(cellType.equals(CellType.BLANK)){
            return null;
        }
        //字符串
        if (cellType.equals(CellType.STRING)){
            return cell.getStringCellValue();
        }
        if(cellType.equals(CellType.NUMERIC)){
            //日期
            if(HSSFDateUtil.isCellDateFormatted(cell)){
                return cell.getDateCellValue();
            }else{
                //数值
                return cell.getNumericCellValue();
            }
        }
        //布尔
        if(cellType.equals(CellType.BOOLEAN)){
            return cell.getBooleanCellValue();
        }
        return null;
    }

    /*
     * @description: 转list <br>
     * @create: 2023/9/20 17:54 <br>
     * @param obj
     * @return java.util.List<T>
     */
    private static<T> List<T> convertToList(Object obj){
        ObjectMapper objectMapper = new ObjectMapper();
        //日期格式
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        //设置时区
        objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        //序列化-忽略null值的属性
        objectMapper.setSerializationInclusion(Include.NON_NULL);
        //序列化-允许序列化空对象
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        //反序列化-在遇到未知属性的时候不抛出异常
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        if(null == obj){
            return null;
        }
        return objectMapper.convertValue(obj, new TypeReference<List<T>>() {});
    }
}

测试

导入模板

导入的泛型(对象)

java 复制代码
@Data
public class ImportTest {

    @ExcelField(name = "字符串")
    private String feild1;

    @ExcelField(name = "数值")
    private BigDecimal feild2;

    @ExcelField(name = "布尔")
    private Boolean feild3;

    @ExcelField(name = "日期")
    private Date feild4;
}

controller

java 复制代码
@Api(tags = "测试")
@RestController
@RequestMapping("/test")
public class TestController {

    @ApiOperation("导入")
    @PostMapping("/importExcel")
    public ResponseEntity<List<ImportTest>> importExcel(@ApiParam(name = "file") @RequestPart("file") MultipartFile file){
        List<ImportTest> list = ExcelImportUtil.readExcel(file, ImportTest.class);
        System.out.print(list);
        return ResponseEntity.ok(list);
    }
}

response

相关推荐
武子康1 小时前
Java-72 深入浅出 RPC Dubbo 上手 生产者模块详解
java·spring boot·分布式·后端·rpc·dubbo·nio
_殊途2 小时前
《Java HashMap底层原理全解析(源码+性能+面试)》
java·数据结构·算法
椰椰椰耶3 小时前
【Spring】拦截器详解
java·后端·spring
没有bug.的程序员3 小时前
JAVA面试宝典 - 《MyBatis 进阶:插件开发与二级缓存》
java·面试·mybatis
没有羊的王K5 小时前
SSM框架学习——day1
java·学习
又菜又爱coding5 小时前
安装Keycloak并启动服务(macOS)
java·keycloak
不知道叫什么呀5 小时前
【C】vector和array的区别
java·c语言·开发语言·aigc
G_whang6 小时前
jenkins使用Jenkinsfile部署springboot+docker项目
spring boot·docker·jenkins
wan_da_ren6 小时前
JVM监控及诊断工具-GUI篇
java·开发语言·jvm·后端
cui_hao_nan6 小时前
JAVA并发——什么是Java的原子性、可见性和有序性
java·开发语言