java springboot poi 从controller 接收不同类型excel 文件处理

根据poi接收controller层的excel文件导入

可使用后缀名xls或xlsx格式的excel。

1.pom引入

    <!-- poi 操作Excel -->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.17</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>3.17</version>
    </dependency>

2.ExcelImportUtil 工具类创建 

import com.guard.biz.common.util.excel.ExcelIn;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author Wei
 * @time 2019/10/29
 * @Description excel 导入工具类
 */
public class ExcelImportUtil<T> {
  private static final Logger log = LoggerFactory.getLogger(ExcelImportUtil.class);
  private static BeanUtilsBean beanUtilsBean = new BeanUtilsBean();
  static {
    beanUtilsBean.getConvertUtils().register(new org.apache.commons.beanutils.converters.DateConverter(null), java.util.Date.class);
  }
  /**
   * 表头名字和对应所在第几列的下标,用于根据title取到对应的值
   */
  private final Map<String, Integer> title_to_index = new HashMap<>();
  /**
   * 所有带有ExcelIn注解的字段
   */
  private final List<Field> fields = new ArrayList<>();
  /**
   * 统计表格的行和列数量用来遍历表格
   */
  private int firstCellNum = 0;
  private int lastCellNum = 0;
  private int firstRowNum = 0;
  private int lastRowNum = 0;
  private String sheetName;
  private Sheet sheet;
  public List<T> read(InputStream in, Class clazz) throws Exception {
    gatherAnnotationFields(clazz);
    configSheet(in);
    configHeader();
    List rList = null;
    try {
      rList = readContent(clazz);
    } catch (IllegalAccessException e) {
      throw new Exception(e);
    } catch (InstantiationException e) {
      throw new Exception(e);
    } catch (InvocationTargetException e) {
      throw new Exception(e);
    }
    return rList;
  }
  private List readContent(Class clazz) throws IllegalAccessException, InstantiationException, InvocationTargetException {
    Object o = null;
    Row row = null;
    List<Object> rsList = new ArrayList<>();
    Object value = null;
    for (int i = (firstRowNum + 1); i <= lastRowNum; i++) {
      o = clazz.newInstance();
      row = sheet.getRow(i);
      Cell cell = null;
      for (Field field : fields) {
        //根据注解中的title,取到表格中该列所对应的的值
        Integer column = title_to_index.get(field.getAnnotation(ExcelIn.class).title());
        if (column == null) {
          continue;
        }
        cell = row.getCell(column);
        value = getCellValue(cell);
        if (null != value && StringUtils.isNotBlank(value.toString())) {
          beanUtilsBean.setProperty(o, field.getName(), value);
        }
      }
      rsList.add(o);
    }
    return rsList;
  }
  private void configSheet(InputStream in) throws Exception {
    // 根据文件类型来分别创建合适的Workbook对象
    try (Workbook wb = WorkbookFactory.create(in)) {
      getSheetByName(wb);
    } catch (FileNotFoundException e) {
      throw new Exception(e);
    } catch (IOException e) {
      throw new Exception(e);
    }
  }
  /**
   * 根据sheet获取对应的行列值,和表头对应的列值映射
   */
  private void configHeader() {
    this.firstRowNum = sheet.getFirstRowNum();
    this.lastRowNum = sheet.getLastRowNum();
    //第一行为表头,拿到表头对应的列值
    Row row = sheet.getRow(firstRowNum);
    this.firstCellNum = row.getFirstCellNum();
    this.lastCellNum = row.getLastCellNum();
    for (int i = firstCellNum; i < lastCellNum; i++) {
      title_to_index.put(row.getCell(i).getStringCellValue(), i);
    }
  }
  /**
   * 根据sheet名称获取sheet
   *
   * @param workbook
   * @return
   * @throws Exception
   */
  private void getSheetByName(Workbook workbook) throws Exception {
    int sheetNumber = workbook.getNumberOfSheets();
    for (int i = 0; i < sheetNumber; i++) {
      String name = workbook.getSheetName(i);
      if (StringUtils.equals(this.sheetName, name)) {
        this.sheet = workbook.getSheetAt(i);
        return;
      }
    }
    throw new Exception("excel中未找到名称为" + this.sheetName + "的sheet");
  }
  /**
   * 根据自定义注解,获取所要导入表格的sheet名称和需要导入的字段名称
   *
   * @param clazz
   * @throws Exception
   */
  private void gatherAnnotationFields(Class clazz) throws Exception {
    if (!clazz.isAnnotationPresent(ExcelIn.class)) {
      throw new Exception(clazz.getName() + "类上没有ExcelIn注解");
    }
    ExcelIn excelIn = (ExcelIn) clazz.getAnnotation(ExcelIn.class);
    this.sheetName = excelIn.sheetName();
    // 得到所有定义字段
    Field[] allFields = FieldUtils.getAllFields(clazz);
    // 得到所有field并存放到一个list中
    for (Field field : allFields) {
      if (field.isAnnotationPresent(ExcelIn.class)) {
        fields.add(field);
      }
    }
    if (fields.isEmpty()) {
      throw new Exception(clazz.getName() + "中没有ExcelIn注解字段");
    }
  }
  private Object getCellValue(Cell cell) {
    if (cell == null) {
      return "";
    }
    Object obj = null;
    switch (cell.getCellTypeEnum()) {
      case BOOLEAN:
        obj = cell.getBooleanCellValue();
        break;
      case ERROR:
        obj = cell.getErrorCellValue();
        break;
      case FORMULA:
        try {
          obj = String.valueOf(cell.getStringCellValue());
        } catch (IllegalStateException e) {
          obj = numericToBigDecimal(cell);
        }
        break;
      case NUMERIC:
        obj = getNumericValue(cell);
        break;
      case STRING:
        String value = String.valueOf(cell.getStringCellValue());
        value = value.replace(" ", "");
        value = value.replace("\n", "");
        value = value.replace("\t", "");
        obj = value;
        break;
      default:
        break;
    }
    return obj;
  }
  private Object getNumericValue(Cell cell) {
    // 处理日期格式、时间格式
    if (HSSFDateUtil.isCellDateFormatted(cell)) {
      return cell.getDateCellValue();
    } else if (cell.getCellStyle().getDataFormat() == 58) {
      // 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58)
      double value = cell.getNumericCellValue();
      return org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value);
    } else {
      return numericToBigDecimal(cell);
    }
  }
  private Object numericToBigDecimal(Cell cell) {
    String valueOf = String.valueOf(cell.getNumericCellValue());
    BigDecimal bd = new BigDecimal(valueOf);
    return bd;
  }
}

3.ExcelIn注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @author Lei
 * @time 2019/10/29
 * @Description
 */
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE, ElementType.FIELD})
public @interface ExcelIn {
  /**
   * 导入sheet名称
   *
   * @return
   */
  String sheetName() default "";
  /**
   * 字段对应的表头名称
   *
   * @return
   */
  String title() default "";
}

4.创建excel中的对象

import lombok.Data;
import lombok.ToString;
import java.util.Date;
/**
 * @author Lei
 * @time 2019/10/29
 * @Description
 */
@ToString
@Data
@ExcelIn(sheetName = "用户")
public class User {
  private String id;
  @ExcelIn(title = "姓名")
  private String name;
  @ExcelIn(title = "年龄")
  private Integer age;
  @ExcelIn(title = "出生日期")
  private Date birthDate;
}

5.controller层接收

@PostMapping("/batch/excel")
  @ApiOperation(value = "根据excel文件批量导入")
  public ResponseVO batchAddDeviceByExcelImport(MultipartFile multipartFile) {
    return new ResponseVO(deviceService.addDeviceByExcelImport(multipartFile));
  }

6.service处理(此处仅打印)

public boolean addDeviceByExcelImport(MultipartFile multipartFile) {
    File file = null;
    try {
      file = File.createTempFile("temp", null);
    } catch (IOException e) {
      e.printStackTrace();
    }
    try {
      multipartFile.transferTo(file);
    } catch (IOException e) {
      e.printStackTrace();
    }
    file.deleteOnExit();
    InputStream inputStream = null;
    try {
      inputStream = new FileInputStream(file);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
    ExcelImportUtil<User> reader = new ExcelImportUtil<>();
    List<User> userList = null;
    try {
      userList = reader.read(inputStream, User.class);
    } catch (Exception e) {
      log.error(e.getMessage());
      throw new CodeException("51302", e.getMessage());
    }
      userList.stream().forEach(e -> log.info(e.toString()));
    return true;
  }

7.测试

(1)两种文件类型的excel

(2)excel中格式如下,注意红色箭头所指的地方 对应user对象中的字段以及sheet名

(3)swagger测试

(4)成功打印

总结

以上所述是小编给大家介绍的java springboot poi 从controller 接收不同类型excel 文件处理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

(0)

相关推荐

  • 详解SpringBoot Controller接收参数的几种常用方式

    第一类:请求路径参数 1.@PathVariable 获取路径参数.即url/{id}这种形式. 2.@RequestParam 获取查询参数.即url?name=这种形式 例子 GET http://localhost:8080/demo/123?name=suki_rong 对应的java代码: @GetMapping("/demo/{id}") public void demo(@PathVariable(name = "id") String id, @Re

  • 解决SpringMVC Controller 接收页面传递的中文参数出现乱码的问题

    新配置一个spring的MVC项目,发现对Get请求的中文参数出现了乱码: 查看了SpingMVC中关于编码的配置(在web.xml中),如下: <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param>

  • 解决Spring Boot 正常启动后访问Controller提示404问题

    问题描述 今天重新在搭建Spring Boot项目的时候遇到访问Controller报404错误,之前在搭建的时候没怎么注意这块.新创建项目成功后,作为项目启动类的Application在com.blog.start包下面,然后我写了一个Controller,然后包的路径是com.blog.ty.controller用的@RestController 注解去配置的controller,然后路径也搭好了,但是浏览器一直报404.最后找到原因是Spring Boot只会扫描启动类当前包和以下的包 ,

  • SpringMVC @ControllerAdvice使用场景

    这篇文章主要介绍了SpringMVC @ControllerAdvice使用场景,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 @ControllerAdvice ,很多初学者可能都没有听说过这个注解,实际上,这是一个非常有用的注解,顾名思义,这是一个增强的 Controller.使用这个 Controller ,可以实现三个方面的功能: 全局异常处理 全局数据绑定 全局数据预处理 灵活使用这三个功能,可以帮助我们简化很多工作,需要注意的是,这

  • spring boot中controller的使用及url参数的获取方法

    类上加上@RequestMapping其访问的地址就是类上的加上方法上的菜能访问到该方法,例如上图的地址就是/hello/say @RequestMapping(value = "/hello",method = RequestMethod.GET) 和@GetMapping(value = "/hello")是等同的 这样就能获取url参数的值了,其结果如下 总结 以上所述是小编给大家介绍的spring boot中controller的使用及url参数的获取方法,

  • 详解Spring MVC如何测试Controller(使用springmvc mock测试)

    在springmvc中一般的测试用例都是测试service层,今天我来演示下如何使用springmvc mock直接测试controller层代码. 1.什么是mock测试? mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法. 2.为什么要使用mock测试? 使用Mock O bject进行测试,主要是用来模拟那些在应用中不容易构造(如HttpServletRequest必须在Servlet容器中才能构造出来)或者比较复杂的对象(如J

  • SpringBoot Controller Post接口单元测试示例

    概述 在日常的开发中,我们一般会定义一个service层,用于实现业务逻辑,并且针对service层会有与之对应的齐全的覆盖率高的单元测试.而对于controller层,一般不怎么做单元测试,因为主要的核心业务逻辑都在service层里,controller层只是做转发,调用service层接口而已.但是还是建议使用单元测试简单的将controller的方法跑一下,看看转发和数据转换的代码是否能正常工作. 在Spring Boot里对controller层进行单元测试非常简单,只需要几个注解和一

  • Spring注解@RestControllerAdvice原理解析

    这篇文章主要介绍了Spring注解@RestControllerAdvice原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言 前段时间部门搭建新系统,需要出异常后统一接口的返回格式,于是用到了Spring的注解@RestControllerAdvice.现在把此注解的用法总结一下. 用法 首先定义返回对象ResponseDto package com.staff.points.common; import lombok.Data;

  • java springboot poi 从controller 接收不同类型excel 文件处理

    根据poi接收controller层的excel文件导入 可使用后缀名xls或xlsx格式的excel. 1.pom引入 <!-- poi 操作Excel --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <d

  • Java中用POI实现将数据导出到Excel

    一.前言 数据导出为Excel在我们写项目的过程中经常用到 需要用到的jar包 poi-3.17.jar 二.具体实现步骤 //第一步创建一个webbook,对应一个Excel文件 HSSFWorkbook wb=new HSSFWorkbook(); //第二步,在webbook中添加一个sheet,对应Excel文件中的sheet HSSFSheet sheet=wb.createSheet("食物信息数据"); //第三步,在sheet中添加表头第0行 HSSFRow row =

  • Java 使用poi把数据库中数据导入Excel的解决方法

    Java 利用poi把数据库中数据导入Excel 效果: 使用时先把poi包导入工程的path,注意只需要导入poi包即可,下载后有三个jar包 核心代码: 连接数据库:DBConnection.java 复制代码 代码如下: package org.xg.db;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;i

  • Java使用poi组件导出Excel格式数据

    在做管理系统的时候,我想Excel的导出是我们很难规避掉的,而且这也是个很实用很人性化的功能. Java中对于Excel的支持有很多种,比如说JXL,POI等.我这边使用的是POI进行一个Excel的操作,下面我会简单分享下POI组件的使用,以及我使用比较多一个工具类. POI组件 poi组件是由Apache提供的组件包,主要职责是为我们的Java程序提供对于office文档的相关操作.本文主要是它对于Excel操作的一个介绍. 官方主页:http://poi.apache.org/index.

  • SpringBoot 导出数据生成excel文件返回方式

    一.基于框架 1.IDE IntelliJ IDEA 2.软件环境 Spring boot mysql mybatis org.apache.poi 二.环境集成 1.创建spring boot项目工程 略过 2.maven引入poi <!--数据导出依赖 excel--> <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependency> <groupId>org.apac

  • springboot:接收date类型的参数方式

    目录 springboot:接收date类型的参数 springboot 传递Date等实体参数时候报错 springboot:接收date类型的参数 今天有个postmapping方法,地址都正确,就是死活进不去,真是奇怪了. 终于从日志中得出些端倪,见下: 只有这个属性报错,恰恰这个属性是Date型. 这句话说得更清楚: "defaultMessage":"Failed to convert property value of type 'java.lang.String

  • SpringBoot实现前后端、json数据交互以及Controller接收参数的几种常用方式

    目录 前言 获取参数的几种常用注解 一.请求路径参数get请求 二.Body参数POST请求 四.HttpServletRequest 五.参数校检 最终选择交互方式 参考文献 总结 前言 现在大多数互联网项目都是采用前后端分离的方式开发,前端人员负责页面展示和数据获取,后端负责业务逻辑处理和接口封装.当与前端交互的过程当中,常用json数据与前端进行交互,这样想取出前端传送过来的json数据的时候,就需要用到@RequestBody这个注解.@RequestBody注解用于读取http请求的内

  • Java SpringBoot集成文件之如何使用POI导出Word文档

    目录 前言 知识准备 什么是POI 实现案例 Pom依赖 导出Word 前言 通过Apache POI导出excel,而Apache POI包含是操作Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API.所以也是可以通过POI来导出word的.本文主要介绍通过SpringBoot集成POI工具实现Word的导出功能. 知识准备 需要理解Apache POI遵循的标准(Office Open XML(OOXML)标准和微软的OLE 2复合文档

  • 详解SpringBoot中Controller接收对象列表实现

    如果Spring Boot中对应的Controller要接收一个对象,该对象中又存放了一个List列表,那么页面该如何传递相关应的参数信息呢. 本篇文章给大家一个简单的示例,提供一种实现方式. 实体类 首先看实体类的结构(注意使用了Lombok): @Data public class Rules { private List<Rule> rules; } 对应Rule实体类代码如下: @Data public class Rule { /** * 类名 */ private String c

  • Springboot 接口需要接收参数类型是数组问题

    目录 接口需要接收参数类型是数组 多个参以“,”拼接传递即可 那么除了这样,我们还能怎么协调呢? springboot接口接收数组及多个参数问题 若接口中需要接受数组,那接口应该如何写呢? 在body中用json格式传参数不就好了吗! 问题解决- 接口需要接收参数类型是数组 如题,一般我们普遍采用的协调方式: 多个参以“,”拼接传递即可 如: 那么除了这样,我们还能怎么协调呢? 其实对应get请求,springmvc内部是已经支持了这种以“,”逗号拼接的方式,也就是说,传参方式不变,但是我们后台

随机推荐