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

相关推荐
java_heartLake5 分钟前
设计模式之建造者模式
java·设计模式·建造者模式
G皮T5 分钟前
【设计模式】创建型模式(四):建造者模式
java·设计模式·编程·建造者模式·builder·建造者
niceffking9 分钟前
JVM HotSpot 虚拟机: 对象的创建, 内存布局和访问定位
java·jvm
菜鸟求带飞_12 分钟前
算法打卡:第十一章 图论part01
java·数据结构·算法
骆晨学长28 分钟前
基于springboot的智慧社区微信小程序
java·数据库·spring boot·后端·微信小程序·小程序
AskHarries33 分钟前
利用反射实现动态代理
java·后端·reflect
@月落34 分钟前
alibaba获得店铺的所有商品 API接口
java·大数据·数据库·人工智能·学习
bjzhang7535 分钟前
SpringBoot开发——整合SpringDoc实现在线接口文档
spring boot·springdoc
liuyang-neu40 分钟前
力扣 42.接雨水
java·算法·leetcode
z千鑫43 分钟前
【人工智能】如何利用AI轻松将java,c++等代码转换为Python语言?程序员必读
java·c++·人工智能·gpt·agent·ai编程·ai工具