在管理一个系统时,总会有许多的数据,为了方便浏览查看数据,系统总会提供「导出Excel」的功能;有导出就有导入,在要向数据库中插入大量的数据时,我们向程序提供准备好的 Excel,然后程序读取表格内容,并将数据添加到数据库中。

实现这个「导入/导出 Excel」的功能也不复杂,我们使用第三方的类库即可实现。

1.技术选型

能够实现「导入/导出 Excel」的第三方常用类库有 Apache poi、Java Excel(JXL)和阿里巴巴开源的 Easyexcel 等。这么多类库该怎么选呢?在这里我给大家推荐阿里巴巴开源的「Easyexcel」。

  • 性能对比
    poi 和 jxl 对内存的消耗很大,在处理大批量的数据时,容易造成内存溢出。比如处理一个 3M 的 Excel,poi 和 jxl 可能需要上百兆的内存,但 easyexcel 可能只需要几百或几千 KB(内存消耗对比有些夸张)。在性能这一块,Excel 完全是吊打 poi 和 jxl。
  • 学习复杂度对比
    poi,在学习它的时候,理解起来不难,就是操作的时候太特么的难了。因为 poi 需要自己处理数据,还有复杂的表格样式,就光是处理数据这一款就很头疼了。等你写好所有的代码,没有几百行,你是实现不了的。反观 easyexcel。它能自己处理数据,表格格式也简单,即使是小白也很容易上手。在学习复杂的这块也吊打 poi,而 jxl 我没了解,但多半也是被吊打。

2.easyexc拟解决的问题

  • Excel读写时内存溢出
  • 使用简单
  • Excel格式解析

3.工作原理

用java代码实现将Excel表格中的图片导入数据库表中 java excel表导入导出_User

添加maven依赖

<!-- EasyExcel核心文件 -->
	<dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>easyexcel</artifactId>
          <version>2.2.3</version>
     </dependency>
     
     <!-- fastjson依赖包 -->
     <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.51</version>
     </dependency>
     
	<!-- 解析上传数据 -->
	<dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
    </dependency>
	
	<!-- slf4j/log4j日志 -->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>1.7.25</version>
    </dependency>

Excel下载

  • HTML
<a href="tAccount/DownLoadExcel">下载</a>
  • 封装数据的Java类
public class User {
	@ExcelProperty("用户编号")
	private Integer userId;
	@ExcelProperty("用户名称")
	private String userName;
	@ExcelProperty("用户性别")
	private String gender;
	@ExcelProperty("创建时间")
	private Date createTime;
}
  • 下载操作
@GetMapping("DownLoadExcel")
    public void dopost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        /**
         * EasyExcel下载步骤
         */
        //设置响应头
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        //设置防止文件名中文乱码
        String fileName = URLEncoder.encode("user1中文文件名","utf-8");
        response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
        //构建写入到Excel中的数据(此数据可以从数据库中获取)
        List<User> users = new ArrayList<>();
        User user1 = new User(1001, "李四1", "男", new Date());
        User user2 = new User(1002, "李四2", "男", new Date());
        User user3 = new User(1003, "李四3", "男", new Date());
        users.add(user1);
        users.add(user2);
        users.add(user3);
        EasyExcel.write(response.getOutputStream(),User.class).sheet("用户信息").doWrite(users);
    }

Excel上传

  • 前端页面
<form action="tAccount/UploadExcelServlet" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="上传">
</form>
  • 接收从Excel中获取到的数据
public class User {

	@ExcelProperty("用户编号")
	private Integer userId;
	@ExcelProperty("用户名称")
	private String userName;
	@ExcelProperty("用户性别")
	private String gender;
	@ExcelProperty("创建时间")
	private Date createTime;
}
  • 上传操作
@PostMapping("UploadExcelServlet")
    public void doposts(HttpServletRequest req, HttpServletResponse resp)throws IOException{
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload fileUpload = new ServletFileUpload(factory);
        //设置单个文件为3M
        fileUpload.setFileSizeMax(1024*1024*3);
        //总文件大小为30M
        fileUpload.setSizeMax(1024*1024*3*10);

        try {
            List<FileItem> list = fileUpload.parseRequest(req);

            for (FileItem fileItem : list) {

                //判断是否为附件
                if(!fileItem.isFormField()) {
                    //是附件
                    InputStream inputStream = fileItem.getInputStream();
                    EasyExcel.read(inputStream,User.class,new AnalysisEventListener<User>() {

                        @Override
                        public void doAfterAllAnalysed(AnalysisContext arg0) {
                            System.out.println("Excel全部读完被执行......");
                        }

                        @Override
                        public void invoke(User data, AnalysisContext arg1) {
                            //读完一行就执行一次(调用数据库进行插入操作)
                            System.out.println("解析一行: "+data);
                        }
                    }).sheet().doRead();
                }else {
                    //普通表单
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
        //上传完成进行转发或者重定向
    }