Spring Boot 集成 easypoi实现excel的导入导出、excel导入导出含图片

Spring Boot 集成 easypoi实现excel的导入导出、excel导入导出含图片

一、Easypoi概述

1.Easypoi

easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员,就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板语言(熟悉的表达式语法),完成以前复杂的写法。

2.为什么要使用easypoi?

Easypoi主打的功能就是容易且易上手。它可以让一个从没见接触过poi的开发人员,就可以很轻松写出Excel导入导出,而不再是看很多api才可以完成这样的工作。

通过简单的注解和模板语言(熟悉的表达式语法),完成以前复杂的写法,EasyPoi快速实现excel导入导出功能,且修改导出格式简单粗暴,快速有效。

3.easypoi提供了那些功能?

基于注解的导入导出,修改注解就可以修改Excel。

支持常用的样式自定义

基于map可以灵活定义的表头字段

支持一对多的导出,导入。

支持模板的导出,一些常见的标签,自定义标签。

支持HTML/Excel转换,如果模板还不能满足用户的变态需求,请用这个功能

支持word的导出,支持图片,Excel

4.什么场景该用哪个方法

1.ExcelExportUtil Excel导出(普通导出,模板导出)
2.ExcelImportUtil Excel导入
3.WordExportUtil Word导出(只支持docx ,doc版本poi存在图片的bug,暂不支持)

4.1 导出

ExcelExportUtil.exportExcel(常用)、ExcelExportUtil.exportBigExcelExcelExportUtil.exportExcelCloneExcelXorHtmlUtil.htmlToExcelCsvExportUtil.exportCsvWordExportUtil.exportWord07(常用)
(1)正规excel导出 (格式简单,数据量可以,5W以内吧)

注解方式:

ExcelExportUtil.exportExcel(ExportParams entity, Class<?> pojoClass,Collection<?> dataSet)

(2)不定多少列,但是格式依然简单数据库不大

自定义方式:

ExcelExportUtil.exportExcel(ExportParams entity, List<ExcelExportEntity> entityList,Collection<?> dataSet)

(3)数据量大超过5W,还在100W以内

注解方式:

ExcelExportUtil.exportBigExcel(ExportParams entity, Class<?> pojoClass,IExcelExportServer server, Object queryParams)

自定义方式:

ExcelExportUtil.exportBigExcel(ExportParams entity, List excelParams,IExcelExportServer server, Object queryParams)

(4)样式复杂,数据量尽量别大

模板导出:

ExcelExportUtil.exportExcel(TemplateExportParams params, Map<String, Object> map)

(5)一次导出多个风格不一致的sheet

模板导出:

ExcelExportUtil.exportExcel(Map<Integer, Map<String, Object>> map,TemplateExportParams params)

(6)一个模板但是要导出非常多份

模板导出:

ExcelExportUtil.exportExcelClone(Map<Integer, List<Map<String, Object>>> map,TemplateExportParams params)

(7)模板无法满足你的自定义,试试html

自己构造html,然后转成excel:

ExcelXorHtmlUtil.htmlToExcel(String html, ExcelType type)

(8)数据量过百万级了.放弃excel吧,csv导出

注解方式:

CsvExportUtil.exportCsv(CsvExportParams params, Class<?> pojoClass, OutputStream outputStream)

自定义方式:

CsvExportUtil.exportCsv(CsvExportParams params, List entityList, OutputStream outputStream)

(9)word导出

模板导出:

WordExportUtil.exportWord07(String url, Map<String, Object> map)

(9)PDF导出

模板导出: TODO

4.2 导入

ExcelImportUtil.importExcel(常用)、ExcelImportUtil.importExcelMore(常用)、ExcelImportUtil.importExcelBySaxCsvImportUtil.importCsv

如果想提高性能 ImportParams 的concurrentTask 可以帮助并发导入,仅单行,最小1000。excel有单个的那种特殊读取,readSingleCell 参数可以支持

(1)不需要检验,数据量不大(5W以内)

注解或者MAP:

ExcelImportUtil.importExcel(File file, Class<?> pojoClass, ImportParams params)

(2)需要导入,数据量不大

注解或者MAP:

ExcelImportUtil.importExcelMore(InputStream inputstream, Class<?> pojoClass, ImportParams params)

(3)数据量大了,或者你有特别多的导入操作,内存比较少,仅支持单行

SAX方式:

ExcelImportUtil.importExcelBySax(InputStream inputstream, Class<?> pojoClass, ImportParams params, IReadHandler handler)

(4)数据量超过EXCEL限制,CSV读取

小数据量:

CsvImportUtil.importCsv(InputStream inputstream, Class<?> pojoClass,CsvImportParams params)

大数据量:

CsvImportUtil.importCsv(InputStream inputstream, Class<?> pojoClass,CsvImportParams params, IReadHandler readHandler)

5.Easypoi常用注解

5.1 @Excel 注解

@Excel注解是作用到Filed上面,是对Excel一列的一个描述这个注解是必须要的注解,其属性如下:
在这里插入图片描述

5.2 @ExcelCollection 注解

@ExcelCollection 注解表示一个集合,主要针对一对多的导出
比如一个老师对应多个科目,科目就可以用集合表示,作用在一个类型是List的属性上面,属性如下:

在这里插入图片描述

5.3 @ExcelTarget注解

作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理

5.4 @ExcelEntity注解

@ExcelEntity注解表示一个继续深入导出的实体,是作用一个类型为实体的属性上面
在这里插入图片描述

5.5 @ExcelIgnore 注解

@ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导出

二、创建Excel导入导出工具类

package com.example.exceldemo.utils;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

/**
 * Excel 导入导出工具类
 * @author qzz
 */
public class ExcelUtils {
    
    

    /**
     * excel 导出
     *
     * @param list     数据列表
     * @param fileName 导出时的excel名称
     * @param response
     */
    public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response) throws IOException {
    
    
        defaultExport(list, fileName, response);
    }

    /**
     * 默认的 excel 导出
     *
     * @param list     数据列表
     * @param fileName 导出时的excel名称
     * @param response
     */
    private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) throws IOException {
    
    
        //把数据添加到excel表格中
        Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
        downLoadExcel(fileName, response, workbook);
    }

    /**
     * excel 导出
     *
     * @param list         数据列表
     * @param pojoClass    pojo类型
     * @param fileName     导出时的excel名称
     * @param response
     * @param exportParams 导出参数(标题、sheet名称、是否创建表头,表格类型)
     */
    private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) throws IOException {
    
    
        //把数据添加到excel表格中
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
        downLoadExcel(fileName, response, workbook);
    }

    /**
     * excel 导出
     *
     * @param list         数据列表
     * @param pojoClass    pojo类型
     * @param fileName     导出时的excel名称
     * @param exportParams 导出参数(标题、sheet名称、是否创建表头,表格类型)
     * @param response
     */
    public static void exportExcel(List<?> list, Class<?> pojoClass, String fileName, ExportParams exportParams, HttpServletResponse response) throws IOException {
    
    
        defaultExport(list, pojoClass, fileName, response, exportParams);
    }

    /**
     * excel 导出
     *
     * @param list      数据列表
     * @param title     表格内数据标题
     * @param sheetName sheet名称
     * @param pojoClass pojo类型
     * @param fileName  导出时的excel名称
     * @param response
     */
    public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response) throws IOException {
    
    
        defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName, ExcelType.XSSF));
    }


    /**
     * excel 导出
     *
     * @param list           数据列表
     * @param title          表格内数据标题
     * @param sheetName      sheet名称
     * @param pojoClass      pojo类型
     * @param fileName       导出时的excel名称
     * @param isCreateHeader 是否创建表头
     * @param response
     */
    public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, boolean isCreateHeader, HttpServletResponse response) throws IOException {
    
    
        ExportParams exportParams = new ExportParams(title, sheetName, ExcelType.XSSF);
        exportParams.setCreateHeadRows(isCreateHeader);
        defaultExport(list, pojoClass, fileName, response, exportParams);
    }


    /**
     * excel下载
     *
     * @param fileName 下载时的文件名称
     * @param response
     * @param workbook excel数据
     */
    private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) throws IOException {
    
    
        try {
    
    
            response.setCharacterEncoding("UTF-8");
            //设置信息头,告诉浏览器内容为excel类型
            response.setHeader("content-Type", "application/vnd.ms-excel");
            //设置下载名称
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "UTF-8"));
            //写入
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
    
    
            throw new IOException(e.getMessage());
        }
    }


    /**
     * excel 导入
     *
     * @param file      excel文件
     * @param pojoClass pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(MultipartFile file, Class<T> pojoClass) throws IOException {
    
    
        return importExcel(file, 1, 1, pojoClass);
    }

    /**
     * excel 导入
     *
     * @param filePath   excel文件路径
     * @param titleRows  表格内数据标题行
     * @param headerRows 表头行
     * @param pojoClass  pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) throws IOException {
    
    
        if (StringUtils.isBlank(filePath)) {
    
    
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        params.setNeedSave(true);
        params.setSaveUrl("/excel/");
        try {
    
    
            return ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
        } catch (NoSuchElementException e) {
    
    
            throw new IOException("模板不能为空");
        } catch (Exception e) {
    
    
            throw new IOException(e.getMessage());
        }
    }


    /**
     * excel 导入
     *
     * @param file       上传的文件
     * @param titleRows  表格内数据标题行
     * @param headerRows 表头行
     * @param pojoClass  pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass) throws IOException {
    
    
        if (file == null) {
    
    
            return null;
        }
        try {
    
    
            return importExcel(file.getInputStream(), titleRows, headerRows, pojoClass);
        } catch (Exception e) {
    
    
            throw new IOException(e.getMessage());
        }
    }

    /**
     * excel 导入
     *
     * @param inputStream 文件输入流
     * @param titleRows   表格内数据标题行
     * @param headerRows  表头行
     * @param pojoClass   pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(InputStream inputStream, Integer titleRows, Integer headerRows, Class<T> pojoClass) throws IOException {
    
    
        if (inputStream == null) {
    
    
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        params.setSaveUrl("/excel/");
        params.setNeedSave(true);
        try {
    
    
            return ExcelImportUtil.importExcel(inputStream, pojoClass, params);
        } catch (NoSuchElementException e) {
    
    
            throw new IOException("excel文件不能为空");
        } catch (Exception e) {
    
    
            throw new IOException(e.getMessage());
        }
    }
}


三、Excel导出导入实例

1.Excel导出(一对一数据)

1.1 添加项目依赖配置

在pom.xml文件中,添加Easypoi依赖,具体依赖如下:

<!--easypoi依赖,实现excel文件导入导出、word导出等-->
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>4.4.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-web</artifactId>
    <version>4.4.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-annotation</artifactId>
    <version>4.4.0</version>
</dependency>

上述依赖说明:

easypoi-base导入导出的工具包,可以完成Excel导入导出,Word导出等功能。
 
easypoi-web耦合了spring-mvc基于AbstractView,极大的简化spring-mvc下的导出功能
 
easypoi-annotation基础注解包,作用与实体对象上,拆分后方便maven多工程的依赖管理

但随着springboot的越来越流行,不可免俗的easypoi也为我们推出了easypoi-spring-boot-starter,方便我们使用。

所以我们就可以不再需要引入那么多相关的依赖啦,省的pom文件看着太长不好找。

如下就是easypoi的starter,大家自行复制,粘贴到本地的pom.xml中即可:

 <!--easypoi依赖,实现excel文件导入导出-->
 <dependency>
     <groupId>cn.afterturn</groupId>
     <artifactId>easypoi-spring-boot-starter</artifactId>
     <version>4.4.0</version>
 </dependency>

1.2 配置application.yml

# 服务端口
server:
  port: 8083

# 数据源配置
spring:
  datasource:
    name: test
    url: jdbc:mysql://localhost:3306/db_user?&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSl=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

    ## 配置连接池信息
    ## 初始化大小,最小,最大
    initialSize: 5
    minIdle: 5
    maxActive: 30
    ## 配置获取连接等待超时的时间
    maxWait: 60000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall
    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

    # 超过时间限制是否回收
    removeAbandoned: true
    # 超时时间;单位为秒。180秒=3分钟
    removeAbandonedTimeout: 180
    # 关闭abanded连接时输出错误日志
    logAbandoned: true

  #静态资源路径
  mvc:
    static-path-pattern: /**
  web:
    resources:
      static-locations: classpath\:/META-INF/resources/,classpath\:/resources/,classpath\:/static/,classpath\:/public/,file\:${
    
    web.upload-path}


##配置打印sql
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  #默认扫描mapper.xml
  mapper-locations: classpath:/mapper/*.xml

#mybatis&&通用mapper
mapper:
  mappers: com.example.exceldemo.mybatis.MyMapper
  identity: MYSQL

upload:
  dir: F:\images\company\

1.2 定义一个导出的对象

我们先来定义一个导出vo,目的是可以对每个导出字段进行长宽等样式进行自定义化,比如我就按照数据长度判断,依次给每个字段加上width 属性,定义每个字段的展示长度。

package com.example.exceldemo.excel;

import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * 学生
 * @author qzz
 */
@Data
public class StudentExcel implements Serializable {
    
    

    private static final long serialVersionUID = 1L;

    private Integer id;

    /**
     * @Excel 作用在一个filed上面,对列的描述
     * @param name 列名
     * @param orderNum 下标,从0开始。
     */
    @Excel(name = "学生姓名", width = 30)
    private String name;

    /**
     * 学生性别 1:男  2:女
     */
    @Excel(name = "学生性别", replace = {
    
    "男_1","女_0"},suffix = "生")
    private Integer sex;

    /**
     * 出生日期
     * 如果数据库是string类型,这个需要设置这个数据库时间格式(databaseFormat)  format:输出时间格式
     */
    @Excel(name = "出生日期", databaseFormat = "yyyyMMddHHmmss",format = "yyyy-MM-dd",width = 20)
    private Date birthday;

    /**
     * 进校日期
     * 字段是Date类型则不需要设置databaseFormat
     */
    @Excel(name = "出生日期", format = "yyyy-MM-dd",width = 20)
    private Date registrationDate;

    private Date createTime;

    private String createUser;

    private Date updateTime;

    private String updateUser;
}

说明:

@Excel 作用在一个filed上面,对列的描述。name:列名。orderNum:下标,从0开始。
 
没有被注解@Excel标注的字段,不会导出。
 
学生姓名定义了我们的列的行高
 
学生性别因为我们基本上都是存在数据库都是数字所以我们转换下。
 
两个日期进行了格式化输出
 
@Excel(databaseFormat="xxxx"):如果数据库字段是string类型,则需要添加该属性,并加上该时间格式,比如:databaseFormat = "yyyyMMdd"。
 
@Excel(replace={“xxx_0”, “xxx_1”,“xxx_2”},addressList = true):表示单元格下拉框展示,_0、_1表示下拉值的前后顺序,从0往后排。要实现字段下拉,addressList属性必不可少
 
@Excel(suffix="xxx"):表示自动添加该xxx为你字段文字的后缀
 
@Excel(imageType=“xxx”):表示导出类型,imageType=1:从file读取;imageType=2:从数据库中读取;默认是文件,同样导入也是一样的。

1.3 在控制器中添加一个导出类

StudentController:


    /**
     * 导出
     * @param name
     */
    @RequestMapping("/exportExcel")
    public void exportExcel(@RequestParam(name = "name",required = false) String name,HttpServletResponse response){
    
    
        try {
    
    
            StudentRequestJson requestJson = new StudentRequestJson();
            if(StringUtils.isNotEmpty(name)){
    
    
                requestJson.setName(name);
            }
            //1.从数据库查询到数据
            List<Student> list =studentService.getStudentList(requestJson);
            //2.导出时的excel名称
            String dateString = String.valueOf(System.currentTimeMillis());
            String fileName = "学生信息表" + dateString;
            //3.查看结果集转成导出vo(转成对应的类型;要不然会报错)
            List<StudentExcel> studentExcelList = new ListUtils<StudentExcel>().copyProperties(list,StudentExcel.class);
            //4.工具类导出excel
            ExcelUtils.exportExcel(studentExcelList,StudentExcel.class,fileName,new ExportParams("计算机一班学生","学生"),response);
        } catch (IOException e) {
    
    
        }
    }

1.4 实现Student类转成StudentExcel类

ListUtils类:Copy list

package com.example.exceldemo.utils;

import org.apache.commons.collections.CollectionUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

public class ListUtils<K> {
    
    
    /**
     * Copy list
     *
     * @param orig
     * @param desClass
     * @return
     */
    public List<K> copyProperties(List<?> orig, Class<K> desClass) {
    
    
        if (Objects.isNull(orig)) {
    
    
            return null;
        }
        List<K> dest = new ArrayList<K>();
        K des;
        for (Object o : orig) {
    
    
            try {
    
    
                des = desClass.newInstance();
                des = BeanUtils.copyAllPropertysNotNull(des, o);
                dest.add(des);
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
        }
        return dest;
    }

    /**
     * 将List<**Domain>转换为List<**fidld>
     *
     * @param collection 数据源
     * @param clazz      domain名称
     * @param fieldName  字段名称
     * @return
     */
    public static List<Object> getFieldValueList(Collection collection, Class clazz, String fieldName) {
    
    
        List<Object> objList = new ArrayList<Object>();
        String methodName = "get" + getFirstUpper(fieldName);
        try {
    
    
            Method m = clazz.getMethod(methodName);
            if (CollectionUtils.isNotEmpty(collection)) {
    
    
                for (Object object : collection) {
    
    
                    objList.add(m.invoke(object));
                }
            }
        } catch (Exception e) {
    
    
        }
        return objList;
    }

    public static <T> List<T> castList(Object obj, Class<T> clazz)
    {
    
    
        List<T> result = new ArrayList<T>();
        if(obj instanceof List<?>)
        {
    
    
            for (Object o : (List<?>) obj)
            {
    
    
                result.add(clazz.cast(o));
            }
            return result;
        }
        return null;
    }


    public static String getFirstUpper(String str) {
    
    
        String newStr = "";
        if (str.length() > 0) {
    
    
            newStr = str.substring(0, 1).toUpperCase() + str.substring(1, str.length());
        }
        return newStr;
    }

}

BeanUtils类:反射的Utils函数集合

package com.example.exceldemo.utils;

import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.BiFunction;


/**
 * <p>
 * Note:反射的Utils函数集合.扩展自Apache Commons BeanUtil
 * <p>
 * Date: 06/15/2015 14:37.
 *
 * @author He Jialin
 */
@SuppressWarnings({
    
    "unchecked", "rawtypes", "unused"})
public class BeanUtils<T> {
    
    

    private BeanUtils() {
    
    
    }

    public static Field getDeclaredField(Object object, String propertyName) throws NoSuchFieldException {
    
    
        return getDeclaredField(object.getClass(), propertyName);
    }

    public static Field getDeclaredField(Class clazz, String propertyName) {
    
    
        for (Class superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
    
    
            try {
    
    
                Field[] s = superClass.getDeclaredFields();
                return superClass.getDeclaredField(propertyName);
            } catch (NoSuchFieldException e) {
    
    
            }
        }
        return null;
    }

    /**
     * 直接获取属性值
     *
     * @param object
     * @param propertyName
     * @return
     */
    public static Object getNameProperty(Object object, String propertyName) {
    
    
        Field field = null;
        try {
    
    
            field = getDeclaredField(object, propertyName);
        } catch (NoSuchFieldException e1) {
    
    
        }
        Object result = null;
        if (null != field) {
    
    
            boolean accessible = field.isAccessible();
            field.setAccessible(true);
            try {
    
    
                result = field.get(object);
            } catch (Exception e) {
    
    
            }
            field.setAccessible(accessible);
        }
        return result;
    }

    public static final String FORMAT_OBJECT = "F-JSONTO-OBJ";
    public static final String FORMAT_MAP = "F-JSONTO-MAP";
    public static final String FORMAT_LIST = "F-JSONTO-LIST";
    public static final String FORMAT_GET = "F-GET";
    public static final String TO_JSON = "TO-JSON";

    public static Object forceGetProperty(Object object, String propertyName) {
    
    
        Object result = null;
        try {
    
    
            if (object instanceof Map) {
    
    
                result = ((Map) object).get(propertyName);
            } else {
    
    
                result = getObjValue(object, propertyName, null);
            }
        } catch (Exception e) {
    
    
        }
        return result;
    }

    public static Map<String, Object> toReplaceKeyLow(Map<String, Object> map) {
    
    
        Map re_map = new HashMap();
        if (re_map != null) {
    
    
            Iterator var2 = map.entrySet().iterator();
            while (var2.hasNext()) {
    
    
                Map.Entry<String, Object> entry = (Map.Entry) var2.next();
                re_map.put(underlineToCamel((String) entry.getKey()), map.get(entry.getKey()));
            }
            map.clear();
        }
        return re_map;
    }

    public static String underlineToCamel(String origin) {
    
    
        return stringProcess(
                origin, (prev, c) -> {
    
    
                    if (prev == '_' && Character.isLowerCase(c)) {
    
    
                        return "" + Character.toUpperCase(c);
                    }
                    if (c == '_') {
    
    
                        return "";
                    }
                    return "" + c;
                }
        );
    }

    public static String stringProcess(String origin, BiFunction<Character, Character, String> convertFunc) {
    
    
        if (origin == null || "".equals(origin.trim())) {
    
    
            return "";
        }
        String newOrigin = "0" + origin;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < newOrigin.length() - 1; i++) {
    
    
            char prev = newOrigin.charAt(i);
            char c = newOrigin.charAt(i + 1);
            sb.append(convertFunc.apply(prev, c));
        }
        return sb.toString();
    }

    /**
     * 直接赋属性值
     *
     * @param object
     * @param propertyName
     * @return
     */
    public static void setNameProperty(Object object, String propertyName, Object newValue) throws NoSuchFieldException {
    
    

        Field field = getDeclaredField(object, propertyName);
        boolean accessible = field.isAccessible();
        field.setAccessible(true);
        try {
    
    
            field.set(object, newValue);
        } catch (Exception e) {
    
    
        }
        field.setAccessible(accessible);
    }

    /**
     * 通过set方法赋值
     *
     * @param object
     * @param propertyName
     * @param newValue
     */
    public static void forceSetProperty(Object object, String propertyName, Object newValue) {
    
    
        if (null == object || StringUtils.isEmpty(propertyName)) {
    
    
            return;
        }
        String[] s = propertyName.split("\\.");
        if (null == s) {
    
    
            return;
        }
        for (int i = 0; i < s.length - 1; i++) {
    
    
            object = forceGetProperty(object, s[i]);
        }
        try {
    
    
            if (object instanceof Map) {
    
    
                ((Map) object).put(propertyName, newValue);
            } else {
    
    
                setObjValue(object, underlineToCamel(propertyName), newValue);
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

    public static Object invokePrivateMethod(Object object, String methodName, Object... params)
            throws NoSuchMethodException {
    
    
        Class[] types = new Class[params.length];
        for (int i = 0; i < params.length; i++) {
    
    
            types[i] = params[i].getClass();
        }
        Class clazz = object.getClass();
        Method method = null;
        for (Class superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
    
    
            try {
    
    
                method = superClass.getDeclaredMethod(methodName, types);
                break;
            } catch (NoSuchMethodException e) {
    
    

            }
        }
        if (method == null) {
    
    
            throw new NoSuchMethodException("No Such Method:" + clazz.getSimpleName() + methodName);
        }
        boolean accessible = method.isAccessible();
        method.setAccessible(true);
        Object result = null;
        try {
    
    
            result = method.invoke(object, params);
        } catch (Exception e) {
    
    
        }
        method.setAccessible(accessible);
        return result;
    }

    /**
     * 通过反射动态调用方法
     *
     * @param classpath  类
     * @param methodname 方法名称
     * @param types      [] 方法参数数组
     * @return
     */
    public static Method transferMethoder(String classpath, String methodname, Class types[]) {
    
    
        Class clazz = null;
        try {
    
    
            clazz = Class.forName(classpath);
        } catch (Exception e) {
    
    
        }
        for (Class superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
    
    
            try {
    
    
                return superClass.getMethod(methodname, types);
            } catch (Exception e) {
    
    
            }
        }
        return null;
    }

    /**
     * 通过反射动态调用方法
     *
     * @param obj        类
     * @param methodname 方法名称
     * @param types      [] 方法参数数组
     * @return
     */
    public static Method transferMethoder(Object obj, String methodname, Class types[]) {
    
    
        Class clazz = obj.getClass();
        for (Class superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
    
    
            try {
    
    
                return superClass.getMethod(methodname, types);
            } catch (Exception e) {
    
    
            }
        }
        return null;
    }

    /**
     * 获取对象的属性(不包括继承的)
     *
     * @param obj
     * @return Field[]
     */
    public static Field[] getObjProperty(Object obj) {
    
    
        Class c = obj.getClass();
        Field[] field = c.getDeclaredFields();
        return field;
    }

    /**
     * 只拷贝超类里的数据
     *
     * @param arg0
     * @param arg1
     * @throws Exception
     */
    public static void copySupperPropertys(Object arg0, Object arg1) throws Exception {
    
    
        if (null != arg0 && null != arg1) {
    
    
            Object value = null;
            if (arg1 instanceof Map) {
    
    
                for (String key : ((Map<String, Object>) arg1).keySet()) {
    
    
                    value = BeanUtils.forceGetProperty(arg1, key);
                    BeanUtils.forceSetProperty(arg0, key, value);
                }
            } else {
    
    
                Field[] field = getObjSupperProperty(arg1);
                if (null != field) {
    
    
                    for (int i = 0; i < field.length; i++) {
    
    
                        value = BeanUtils.forceGetProperty(arg1, field[i].getName());
                        BeanUtils.forceSetProperty(arg0, field[i].getName(), value);
                    }
                }
            }
        } else {
    
    
            throw new Exception("参数为空");
        }
    }

    /**
     * 拷贝类里所有的数据
     *
     * @param arg0 dest
     * @param arg1
     * @throws Exception
     */
    public static void copyAllPropertys(Object arg0, Object arg1) throws Exception {
    
    
        if (null != arg0 && null != arg1) {
    
    
            Object value = null;
            if (arg1 instanceof Map) {
    
    
                for (String key : ((Map<String, Object>) arg1).keySet()) {
    
    
                    value = BeanUtils.forceGetProperty(arg1, key);
                    BeanUtils.forceSetProperty(arg0, key, value);
                }
            } else {
    
    
                Field[] field = getObjAllProperty(arg1);
                if (null != field) {
    
    
                    for (int i = 0; i < field.length; i++) {
    
    
                        if ("serialVersionUID".equals(field[i].getName())) {
    
    
                            continue;
                        }
                        value = BeanUtils.forceGetProperty(arg1, field[i].getName());
                        BeanUtils.forceSetProperty(arg0, field[i].getName(), value);
                    }
                }
            }
        } else {
    
    
            throw new Exception("参数为空");
        }
    }

    /**
     * 拷贝的数据(不包括继承的)
     *
     * @param arg0
     * @param arg1
     * @throws Exception
     */
    public static void copyImplPropertys(Object arg0, Object arg1) throws Exception {
    
    
        if (null != arg0 && null != arg1) {
    
    
            Object value = null;
            if (arg1 instanceof Map) {
    
    
                for (String key : ((Map<String, Object>) arg1).keySet()) {
    
    
                    value = BeanUtils.forceGetProperty(arg1, key);
                    BeanUtils.forceSetProperty(arg0, key, value);
                }
            } else {
    
    
                Field[] field = getObjProperty(arg1);
                if (null != field) {
    
    
                    for (int i = 0; i < field.length; i++) {
    
    
                        value = BeanUtils.forceGetProperty(arg1, field[i].getName());
                        BeanUtils.forceSetProperty(arg0, field[i].getName(), value);
                    }
                }
            }
        } else {
    
    
            throw new Exception("参数为空");
        }
    }

    public static String checkImplNull(Object arg0, Map<String, String> notcl) {
    
    
        if (null == arg0) {
    
    
            return "null";
        }
        Object value = null;
        String msg = "";
        if (arg0 instanceof Map) {
    
    
            for (String key : ((Map<String, Object>) arg0).keySet()) {
    
    
                if ("serialVersionUID".equals(key) || notcl.containsKey(key)) {
    
    
                    continue;
                }
                value = BeanUtils.forceGetProperty(arg0, key);
                if (null == value) {
    
    
                    msg += key + " is null ";
                } else if (value instanceof String) {
    
    
                    if (StringUtils.isEmpty(value.toString())) {
    
    
                        msg += key + " is null ";
                    }
                }
            }
        } else {
    
    
            Field[] field = getObjProperty(arg0);
            if (null != field) {
    
    
                for (int i = 0; i < field.length; i++) {
    
    
                    if ("serialVersionUID".equals(field[i].getName()) || notcl.containsKey(field[i].getName())) {
    
    
                        continue;
                    }
                    value = BeanUtils.forceGetProperty(arg0, field[i].getName());
                    if (null == value) {
    
    
                        msg += field[i].getName() + " is null ";
                    } else if (value instanceof String) {
    
    
                        if (StringUtils.isEmpty(value.toString())) {
    
    
                            msg += field[i].getName() + " is null ";
                        }
                    }
                }
            }
        }
        return msg;
    }

    /**
     * 获取对象祖先的属性
     *
     * @param obj
     * @return Field[]
     */
    public static Field[] getObjSupperProperty(Object obj) {
    
    
        Class c = obj.getClass();
        Class supper = c.getSuperclass();
        List<Field> list = new ArrayList<Field>();
        if (null != supper) {
    
    
            for (Class superClass = supper; superClass != Object.class; superClass = superClass.getSuperclass()) {
    
    
                Field[] fieldchild = superClass.getDeclaredFields();
                if (null != fieldchild) {
    
    
                    for (Field field2 : fieldchild) {
    
    
                        list.add(field2);
                    }
                }
            }
        }
        Field[] field = new Field[list.size()];
        field = list.toArray(field);
        return field;
    }

    /**
     * 获取对象祖先的属性,不包括supperbean
     *
     * @param obj
     * @return Field[]
     */
    public static Field[] getObjOpSupperProperty(Object obj) {
    
    
        Class c = obj.getClass();
        Class supper = c.getSuperclass();
        List<Field> list = new ArrayList<Field>();
        if (null != supper) {
    
    
            for (Class superClass = supper; superClass != Object.class; superClass = superClass.getSuperclass()) {
    
    
                Field[] fieldchild = superClass.getDeclaredFields();
                if (null != fieldchild) {
    
    
                    for (Field field2 : fieldchild) {
    
    
                        list.add(field2);
                    }
                }
            }
        }
        Field[] field = new Field[list.size()];
        field = list.toArray(field);
        return field;
    }

    /**
     * 获取对象所有的属性(包括继承的)
     *
     * @param obj
     * @return Field[]
     */
    public static Field[] getObjAllProperty(Object obj) {
    
    
        List<Field> list = new ArrayList<Field>();
        for (Class superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
    
    
            Field[] fieldchild = superClass.getDeclaredFields();
            if (null != fieldchild) {
    
    
                for (Field field2 : fieldchild) {
    
    
                    list.add(field2);
                }
            }
        }
        Field[] field = new Field[list.size()];
        field = list.toArray(field);
        return field;
    }

    /**
     * 获取对象所有的属性(包括继承的),不包括supperbean
     *
     * @param obj
     * @return Field[]
     */
    public static Field[] getObjAllOpProperty(Object obj) {
    
    
        List<Field> list = new ArrayList<Field>();
        for (Class superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
    
    
            Field[] fieldchild = superClass.getDeclaredFields();
            if (null != fieldchild) {
    
    
                for (Field field2 : fieldchild) {
    
    
                    list.add(field2);
                }
            }
        }
        Field[] field = new Field[list.size()];
        field = list.toArray(field);
        return field;
    }

    /**
     * 获取对应的名称的get方法
     *
     * @param proName
     * @return
     */
    public static String getProNameMethod(String proName) {
    
    
        String methodName = "";
        if (StringUtils.isNotEmpty(proName)) {
    
    
            methodName = "get" + getFirstUpper(proName);
        }
        return methodName;
    }

    /**
     * 获取对应的名称的set方法
     *
     * @param proName
     * @return
     */
    public static String getProSetNameMethod(String proName) {
    
    
        String methodName = "";
        if (StringUtils.isNotEmpty(proName)) {
    
    
            methodName = "set" + getFirstUpper(proName);
        }
        return methodName;
    }

    /**
     * 获取对象里对应的属性值(通过get方法)
     *
     * @param obj
     * @param name
     * @param defObj 默认值
     * @return
     */
    public static Object getObjValue(Object obj, String name, Object defObj) {
    
    
        Object valueObj = null;
        String methodName = getProNameMethod(name);
        Method method = transferMethoder(obj, methodName, new Class[0]);
        if (null != method) {
    
    
            try {
    
    
                valueObj = method.invoke(obj);
                if (null == valueObj) {
    
    
                    valueObj = defObj;
                }
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
        }
        return valueObj;
    }

    /**
     * 赋值对象里对应的属性值(通过set方法)
     *
     * @param obj
     * @param name
     * @param defObj 值
     * @return
     */
    public static void setObjValue(Object obj, String name, Object defObj) {
    
    
        String methodName = getProSetNameMethod(name);
        try {
    
    
            Field field = getDeclaredField(obj, name);
            if (null == field) {
    
    
                return;
            }
            Class fclass = field.getType();
            Object valueobj = getValueByType(fclass, defObj);
            Class[] types = {
    
    fclass};
            Method method = transferMethoder(obj, methodName, types);
            if (null != method) {
    
    
                method.invoke(obj, valueobj);
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

    /**
     * @param cls
     * @param defObj
     * @return
     */
    public static Object getValueByType(Class cls, Object defObj) {
    
    
        Object obj = defObj;
        if (cls == null) {
    
    
            return obj;
        }
        String className = cls.getName();
        if (null == className) {
    
    
            return obj;
        }
        if (className.indexOf("[") == 0) {
    
    
            return obj;
        } else if (null != defObj && defObj.getClass().getName().equals(className)) {
    
    
            return obj;
        } else {
    
    
            if (className.indexOf("String") >= 0) {
    
    
                if (null == defObj) {
    
    
                    obj = null;
                } else {
    
    
                    obj = defObj + "";
                }
            } else if (className.indexOf("int") >= 0) {
    
    
                if (null == defObj || StringUtils.isEmpty(String.valueOf(defObj))) {
    
    
                    defObj = "0";
                }
                obj = Long.valueOf(String.valueOf(defObj)).intValue();
            } else if (className.indexOf("Long") >= 0 || className.indexOf("long") >= 0) {
    
    
                if (null == defObj || StringUtils.isEmpty(String.valueOf(defObj))) {
    
    
                    defObj = "0";
                }
                obj = Long.valueOf(String.valueOf(defObj));
            } else if (className.indexOf("Number") >= 0 || className.indexOf("number") >= 0) {
    
    
                if (null == defObj || StringUtils.isEmpty(String.valueOf(defObj))) {
    
    
                    defObj = "0";
                }
                obj = Long.valueOf(String.valueOf(defObj));
            } else if (className.indexOf("Double") >= 0) {
    
    
                if (null == defObj || StringUtils.isEmpty(String.valueOf(defObj))) {
    
    
                    defObj = "0";
                }
                obj = Double.valueOf(String.valueOf(defObj));
            } else if (className.indexOf("double") >= 0) {
    
    
                if (null == defObj || StringUtils.isEmpty(String.valueOf(defObj))) {
    
    
                    defObj = "0";
                }
                obj = Double.valueOf(String.valueOf(defObj));
            } else if (className.indexOf("Date") >= 0) {
    
    
                if (null != defObj && StringUtils.isNotEmpty(String.valueOf(defObj))) {
    
    
                    if (String.valueOf(defObj).length() > 10) {
    
    
                        obj = DateUtils.getDateToString(String.valueOf(defObj), DateUtils.DATETIMESHOWFORMAT);
                    } else {
    
    
                        obj = DateUtils.getDateToString(String.valueOf(defObj), DateUtils.DATESHOWFORMAT);
                    }
                    if (obj == null) {
    
    
                        obj = defObj;
                    }
                }
            } else if (className.indexOf("Integer") >= 0) {
    
    
                if (null == defObj || StringUtils.isEmpty(String.valueOf(defObj))) {
    
    
                    defObj = "0";
                }
                obj = Integer.valueOf(String.valueOf(defObj));
            } else if (className.indexOf("boolean") >= 0) {
    
    
                if (null == defObj || StringUtils.isEmpty(String.valueOf(defObj))) {
    
    
                    defObj = "false";
                }
                if ("true".equals(String.valueOf(defObj))) {
    
    
                    obj = true;
                } else {
    
    
                    obj = false;
                }
            } else if (className.indexOf("Boolean") >= 0) {
    
    
                if (null == defObj || StringUtils.isEmpty(String.valueOf(defObj))) {
    
    
                    defObj = "false";
                }
                if ("true".equals(String.valueOf(defObj))) {
    
    
                    obj = true;
                } else {
    
    
                    obj = false;
                }
            } else if (cls.isEnum()) {
    
    
                obj = Enum.valueOf(cls, defObj.toString());
            } else if (className.indexOf("BigDecimal") >= 0) {
    
    
                if (null == defObj || StringUtils.isEmpty(String.valueOf(defObj))) {
    
    
                    //obj = BigDecimal.ZERO;
                } else {
    
    
                    obj = new BigDecimal(String.valueOf(defObj));
                }
            } else if (className.indexOf("Short") >= 0) {
    
    
                if (null == defObj || StringUtils.isEmpty(String.valueOf(defObj))) {
    
    
                    defObj = "0";
                }
                obj = Short.valueOf(String.valueOf(defObj));
            }
        }
        return obj;
    }

    /**
     * 赋值对象里对应的属性值(通过set方法) defObj固定式string,要转换
     *
     * @param obj
     * @param name
     * @param defObj 值
     * @return
     */
    public static void setObjValue(Object obj, String name, String defObj) {
    
    
        String methodName = getProSetNameMethod(name);
        try {
    
    
            Field field = getDeclaredField(obj, name);
            Class fclass = field.getType();
            Class[] types = {
    
    fclass};
            Method method = transferMethoder(obj, methodName, types);
            if (null != method) {
    
    
                method.invoke(obj, getStringToType(fclass, defObj));
            }
        } catch (Exception e) {
    
    
        }
    }

    public static Object getObject(Object obj, String name, String defObj) {
    
    
        String methodName = getProSetNameMethod(name);
        try {
    
    
            Field field = getDeclaredField(obj, name);
            Class fclass = field.getType();
            Class[] types = {
    
    fclass};
            return getStringToType(fclass, defObj);
        } catch (Exception e) {
    
    
        }
        return null;
    }

    public static String getObjectHql(Object obj, String name, List<Object> paramlist, Object value) {
    
    
        String methodName = getProSetNameMethod(name);
        try {
    
    
            Field field = getDeclaredField(obj, name);
            Class fclass = field.getType();
            Class[] types = {
    
    fclass};
            return getStringToHql(fclass, name, paramlist, value);
        } catch (Exception e) {
    
    
        }
        return null;
    }

    /**
     * 把string 转化成对应的类型
     *
     * @param typeClass
     * @param value
     * @return
     */
    public static Object getStringToType(Class typeClass, String value) {
    
    
        Object obj = null;
        if (typeClass.equals(String.class)) {
    
    
            if (null == value || StringUtils.isEmpty(value)) {
    
    
                obj = "";
            } else {
    
    
                obj = String.valueOf(value);
            }
        } else if (typeClass.equals(Double.class)) {
    
    
            if (null == value || StringUtils.isEmpty(value)) {
    
    
                obj = 0D;
            } else {
    
    
                obj = Double.valueOf(value);
            }
        } else if (typeClass.equals(Integer.class)) {
    
    
            if (null == value || StringUtils.isEmpty(value)) {
    
    
                obj = 0;
            } else {
    
    
                obj = Integer.valueOf(value);
            }
        } else if (typeClass.equals(Date.class)) {
    
    
            if (null == value || StringUtils.isEmpty(value)) {
    
    
                obj = null;
            } else {
    
    
                obj = DateUtils.getDateToString(value, DateUtils.DATETIMESHOWFORMAT);
            }
        } else if (typeClass.equals(Long.class)) {
    
    
            if (null == value || StringUtils.isEmpty(value)) {
    
    
                obj = 0L;
            } else {
    
    
                obj = Long.valueOf(value);
            }
        } else if (typeClass.equals(BigDecimal.class)) {
    
    
            if (null == value || StringUtils.isEmpty(value)) {
    
    
                //obj = BigDecimal.ZERO;
            } else {
    
    
                obj = new BigDecimal(value);
            }
        } else {
    
    
            obj = 0;
        }
        return obj;
    }

    @SuppressWarnings("deprecation")
    public static String getStringToHql(Class typeClass, String name, List<Object> paramlist, Object value) {
    
    
        String obj = null;
        if (typeClass.equals(String.class)) {
    
    
            obj = "'--'";
            paramlist.add(null == value || "".equals(value) ? "--" : value);
        } else if (typeClass.equals(Double.class)) {
    
    
            obj = "0";
            paramlist.add(null == value || "".equals(value) ? 0D : value);
        } else if (typeClass.equals(Integer.class)) {
    
    
            obj = "0";
            paramlist.add(null == value || "".equals(value) ? 0 : value);
        } else if (typeClass.equals(Date.class)) {
    
    
            obj = "to_date('1991.01.01','yyyy.mm.dd')";
            paramlist.add(null == value || "".equals(value) ? new Date("1991.01.01") : value);
        } else if (typeClass.equals(Long.class)) {
    
    
            obj = "0";
            paramlist.add(null == value || "".equals(value) ? 0L : value);
        } else {
    
    
            obj = "0";
            paramlist.add(null == value || "".equals(value) ? 0 : value);
        }
        return obj;
    }

    public static <T> T copyAllPropertysNotNull(T arg0, Object arg1) throws Exception {
    
    
        if (null != arg0 && null != arg1) {
    
    
            Object value = null;
            if (arg1 instanceof Map) {
    
    
                for (String key : ((Map<String, Object>) arg1).keySet()) {
    
    
                    value = BeanUtils.forceGetProperty(arg1, key);
                    if (value == null) {
    
    
                        continue;
                    }
                    BeanUtils.forceSetProperty(arg0, key, value);
                }
            } else {
    
    
                Field[] field = getObjAllProperty(arg1);
                if (null != field) {
    
    
                    for (int i = 0; i < field.length; i++) {
    
    
                        value = BeanUtils.forceGetProperty(arg1, field[i].getName());
                        if (value == null) {
    
    
                            continue;
                        }
                        BeanUtils.forceSetProperty(arg0, field[i].getName(), value);
                    }
                }
            }
        } else {
    
    
            throw new Exception("参数为空");
        }
        return arg0;
    }

    private static List<Field> getFieldList(Class clazz, List<Field> fieldList) {
    
    
        Field[] fields = clazz.getDeclaredFields();
        fieldList.addAll(Arrays.asList(fields));
        Field[] pFields = clazz.getSuperclass().getDeclaredFields();
        if (pFields != null && pFields.length > 0) {
    
    
            fieldList.addAll(Arrays.asList(pFields));
            getFieldList(clazz.getSuperclass(), fieldList);
        } else {
    
    
            return fieldList;
        }
        return fieldList;
    }

    public static String getFirstUpper(String str) {
    
    
        String newStr = "";
        if (str.length() > 0) {
    
    
            newStr = str.substring(0, 1).toUpperCase() + str.substring(1, str.length());
        }
        return newStr;
    }
}

DateUtils类:时间工具类

package com.example.exceldemo.utils;


import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * 时间工具类
 * @author qzz
 */
public class DateUtils {
    
    
    /**
     * Format:yyyy-MM-dd
     */
    public static final String DATESHOWFORMAT = "yyyy-MM-dd";

    /**
     * Format:yyyy-MM-dd HH:mm:ss
     */
    public static final String DATETIMESHOWFORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * 日期格式化(String转换为Date)
     *
     * @param dateStr
     *            日期字符串
     * @param patten
     *            处理结果日期的显示格式,如:"YYYY-MM-DD"
     * @return
     */
    public static Date getDateToString(String dateStr, String patten) {
    
    
        if (StringUtils.isEmpty(dateStr)) {
    
    
            return null;
        }
        SimpleDateFormat formatter = new SimpleDateFormat(patten,Locale.CHINA);
        try {
    
    
            return formatter.parse(dateStr);
        } catch (ParseException e) {
    
    
            e.printStackTrace();
        }
        return null;
    }
}

1.5 浏览器测试

在浏览器中输入:http://localhost:8083/student/exportExcel,然后键盘回车,你将会看到,浏览器左下方,会弹出一个excel下载窗口,这就意味着已经导出excel成功了。

在这里插入图片描述

等待下载完成,我们打开excel文件,可以检查一下你代码中所设置的文件标题,字段名,字段长度,文件名等是否都设置成功了。

导出excel文件打开后实际效果如下:

在这里插入图片描述
可以看到,上方截图已经证明导出方法完全正确,所设置的内容都设置上了,比如每个字段的长度、日期格式化、性别转换,就是按代码所设置的属性来进行展示的。

2.Excel导出(一对多数据)

2.1 定义一个导出的集合

一个课程对应一个老师、一个课程对应N个学生

(1)课程的实体

package com.example.exceldemo.excel;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
import cn.afterturn.easypoi.excel.annotation.ExcelEntity;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * 课程
 * @author qzz
 */
@Data
@ExcelTarget("courseExcel")
public class CourseExcel implements Serializable {
    
    

    private static final long serialVersionUID = 1L;

    /**
     * @Excel 作用在一个filed上面,对列的描述
     * @param name 列名
     * @param orderNum 下标,从0开始。
     * @param needMerge 是否需要合并
     */
    @Excel(name = "课程姓名", width = 30,needMerge = true, orderNum = "1")
    private String name;

    /**
     * 老师主键
     */
    @ExcelEntity(id="absent")
    private TeacherExcel teacherExcel;

    /**
     * 学生列表
     */
    @ExcelCollection(name="学生", orderNum = "3")
    private List<StudentExcel> studentExcelList;
}

说明:

@ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理
 
@ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段
 
@ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示
 
@Excel 中 needMerge:是否需要合并

(2)老师的实体

package com.example.exceldemo.excel;

import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;

import java.io.Serializable;

/**
 * 老师
 * @author qzz
 */
@Data
public class TeacherExcel implements Serializable {
    
    

    private static final long serialVersionUID = 1L;

    /**
     * @Excel 作用在一个filed上面,对列的描述
     * @param name 列名
     * @param orderNum 下标,从0开始。
     */
    @Excel(name = "主讲老师_major,代课老师_absent",needMerge = true, width = 20,orderNum = "1")
    private String name;
}

这里一对多导出的实体就创建好了。下面来实现一对多导出代码。

2.2 在控制器类中添加一个导出方法

    /**
     * 导出(一对多)
     * @param name
     */
    @RequestMapping("/exportExcel")
    public void exportExcel(@RequestParam(name = "name",required = false) String name,HttpServletResponse response){
    
    
        try {
    
    
            CourseRequestJson requestJson = new CourseRequestJson();
            if(StringUtils.isNotEmpty(name)){
    
    
                requestJson.setName(name);
            }
            //1.从数据库查询到数据(一对多查询)
            List<CourseVo> list =courseService.getCourseExportList(requestJson);
            //2.导出时的excel名称
            String dateString = String.valueOf(System.currentTimeMillis());
            String fileName = "课程学生信息表" + dateString;
            //3.查看结果集转成导出vo(转成对应的类型;要不然会报错)
            List<CourseExcel> CourseExcelList = new ListUtils<CourseExcel>().copyProperties(list,CourseExcel.class);
            //4.工具类导出excel
            ExcelUtils.exportExcel(CourseExcelList,CourseExcel.class,fileName,new ExportParams("计算机一班","课程学生"),response);
        } catch (IOException e) {
    
    
        }
    }

2.3 一对多查询

 List<CourseVo> list =courseService.getCourseExportList(requestJson);

CourseVo实体如下:

package com.example.exceldemo.dto;

import com.example.exceldemo.excel.StudentExcel;
import com.example.exceldemo.excel.TeacherExcel;
import lombok.Data;
import java.util.List;

/**
 * 课程
 * @author qzz
 */
@Data
public class CourseVo{
    
    

    /**
     * 课程id
     */
    private Integer id;

    /**
     * 课程姓名
     */
    private String name;

    /**
     * 老师
     */
    private TeacherExcel teacherExcel;

    /**
     * 学生列表
     */
    private List<StudentExcel> studentExcelList;
}

CourseMapper创建查询方法:

public interface CourseMapper extends MyMapper<Course> {
    
    

    /**
     * 获取课程导出列表
     * @param CourseRequestJson
     * @return
     */
    List<CourseVo> getCourseExportList(CourseRequestJson CourseRequestJson);

    /**
     * 根据课程id获取学生列表信息
     * @param courseId
     * @return
     */
    List<StudentExcel> getStudentListById(@Param("id") Integer courseId);
}

借助于 association标签(1对1)、collection标签(1对多)实现查询效果:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.exceldemo.dao.CourseMapper">

    <resultMap id="BaseResultMap_1" type="com.example.exceldemo.dto.CourseVo">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>

        <!--association(1对1) 这个标签对应BaseResultMap_1中的teacherExcel成员变量的属性-->
        <association property="teacherExcel" javaType="com.example.exceldemo.excel.TeacherExcel">
            <result property="name" column="teacher_name"></result>
        </association>

        <!--collection(1对多) 代表集合-->
        <collection property="studentExcelList" column="id" ofType="com.example.exceldemo.excel.StudentExcel" select="com.example.exceldemo.dao.CourseMapper.getStudentListById" >
        </collection>
    </resultMap>
    <!--获取课程导出列表-->
    <select id="getCourseExportList" resultMap="BaseResultMap_1">
        select c.id,
               c.`name`,
               t.`name` as teacher_name
        from t_course c
        LEFT JOIN t_teacher t on t.id = c.teacher_id
        where 1=1
        <if test="name!=null and ''!=name">
            and c.`name` like concat('%',#{name},'%')
        </if>
    </select>

    <!--获取课程导出列表-->
    <select id="getStudentListById" resultType="com.example.exceldemo.excel.StudentExcel">
        select s1.id,s1.name,s1.sex,s1.birthday,s1.registration_date as registrationDate
        from t_course_student c1
        INNER JOIN t_student s1 on s1.id = c1.student_id
        where course_id=#{id}
    </select>
</mapper>

2.4 浏览器测试

在浏览器中输入:http://localhost:8083/course/exportExcel?name=,然后键盘回车,你将会看到,浏览器左下方,会弹出一个excel下载窗口,这就意味着已经导出excel成功了。
在这里插入图片描述
excel实现效果如下:

在这里插入图片描述

3.含图片的Excel导出

在日常运作中不可避免的会遇到图片的导入导出,这里提供了两种类型的图片导出方式:

3.1 方式1:从file读取(type = 2,imageType=1)

@Excel(name = "公司LOGO", type = 2 ,width = 40 , height = 20,imageType = 1)
private String companyLogo;

注意:
type =2 表示该字段类型为图片,imageType=1 (默认可以不填),表示从file读取,字段类型是个字符串类型

可以用相对路径也可以用绝对路径,绝对路径优先依次获取

3.2 方式2:从数据库或者已经读取完毕(type = 2,imageType=2)

@Excel(name = "公司LOGO", type = 2 ,width = 40 , height = 20,imageType = 2)
private byte[] companyLogo;

注意:
type =2 表示该字段类型为图片,imageType=2 ,表示从数据库或者已经读取完毕,字段类型是个字节数组
直接使用同时,image 类型的cell最好设置好宽和高,会百分百缩放到cell那么大,不是原尺寸。

3.3 代码示例:以方式1为例

easypoi依赖、application配置上面的导出介绍过了,不再累赘。

3.3.1 实体类

package com.example.exceldemo.excel;

import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import java.io.Serializable;

/**
 * 公司
 * @author qzz
 */
@Data
public class CompanyExcel implements Serializable {
    
    

    /**
     * 公司名称
     */
    @Excel(name = "公司名称")
    private String name;

    /**
     * width和height是导出是图片的宽度和高度
     * type:导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本
     * imageType 导出类型;1:从file读取;2:是从数据库中读取,默认是文件;同样导入也是一样的
     * savePath:保存的路径(右击保存图片的文件夹,选Copy Path就行,这里是存在static下的imgs中)
     */
    @Excel(name = "公司Logo", width = 40, height = 20, type = 2, savePath = "F:\\company")
    private String logo;

    /**
     * 公司地址
     */
    @Excel(name = "公司地址", width = 60)
    private String address;
}

3.3.2 本地图片地址映射

package com.example.exceldemo.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 配置访问自定义的资源访问路径
 * @author Administrator
 *
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    
    

	@Value("${upload.dir}")
	private String filePath;

	/**
	 *  添加静态资源映射路径,images,css、js等都放在classpath下的static中
	 * @param registry
	 */
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
    
    

		/**
		 *  addResourceHandler 指的是对外暴露的访问路径
		 *  addResourceLocations 指的是文件配置的目录
		 */
		//文件上传路径映射
		registry.addResourceHandler("/company/**").addResourceLocations("file:"+filePath);
	}
}

3.3.2 在控制器类中添加一个导出方法

CompanyController:


    /**
     * 导出excel,含图片
     * @param response
     */
    @RequestMapping("/exportExcel")
    public void exportExcel(HttpServletResponse response){
    
    
        try {
    
    
            //1.查询出要导出的数据(图片路径为上传图片全路径)
            List<Company> companyList = companyService.findAll();
            List<CompanyExcel> companyExcelList = new ListUtils<CompanyExcel>().copyProperties(companyList, CompanyExcel.class);
            //2.导出时的excel名称
            String dateString = String.valueOf(System.currentTimeMillis());
            String fileName = "公司信息" + dateString;
            //3.工具类导出Excel
            ExportParams params = new ExportParams();
            params.setTitle("公司信息列表");
            params.setSheetName("公司信息");
            //需要设置type=ExcelType.HSSF,不然图片不显示
            params.setType(ExcelType.HSSF);
            ExcelUtils.exportExcel(companyExcelList, CompanyExcel.class,fileName,params,response);
        }catch (Exception e){
    
    

        }
    }

注意: 需要设置ExcelType.HSSF,不然图片不显示

3.3.2 浏览器测试

在浏览器中输入:http://localhost:8083/company/exportExcel,然后键盘回车,你将会看到,浏览器左下方,会弹出一个excel下载窗口,这就意味着已经导出excel成功了。
在这里插入图片描述

excel实现效果如下:

在这里插入图片描述

4.含图片的Excel导入

easypoi依赖、application.yml配置同上。

4.1 实体类

同上面含图片的Excel导出。

4.2 本地图片地址映射

同上面含图片的Excel导出。

4.3 新建要上传的excel文件

在这里插入图片描述

4.4 在控制器类中添加一个导出方法

CompanyController:

    /**
     * 批量导入,含图片
     * @param file
     * @return
     */
    @RequestMapping("/upload")
    public Result importExcel(@RequestParam("file") MultipartFile file,HttpServletRequest request){
    
    
       try{
    
    
           String originalFileName = file.getOriginalFilename();
           //excel导入
           List<CompanyExcel> companyExcelList = ExcelUtils.importExcel(file,1,1,CompanyExcel.class);
           //调用getImgName方法获取图片名
           List<Company> companyList = new ListUtils<Company>().copyProperties(companyExcelList,Company.class);
           //图片转存
           saveImage(request,companyList);
           //调用方法将数据保存到数据库
           companyService.addBatchCompany(companyList);
           return Result.success("上传成功:"+originalFileName);
       }catch (Exception e){
    
    
           e.printStackTrace();
           return Result.fail("上传失败");
       }
    }

注意:
excel文件中有标题并占用一行,所以setTitleRows设置为1。表头也占用一行,所以setHeadRows设置为1;
在这里插入图片描述

application.yml 中配置图片上传路径

upload:
  dir: F:\images\company\

图片转存:将图片存储到本地磁盘中

@Value("${upload.dir}")
private String filePath;
/**
 * 文件转存
 * @param companyList
 */
private void saveImage(HttpServletRequest request, List<Company> companyList) {
    
    
    //遍历每一条数据
    for (Company company : companyList) {
    
    
        if (StringUtils.isNotEmpty(company.getLogo())) {
    
    
            try {
    
    
                //获取到暂存的文件
                File tmpFile = new File(company.getLogo());
                FileInputStream fileInputStream = new FileInputStream(tmpFile);
                //转换为 multipartFile 类
                MultipartFile multipartFile = new MockMultipartFile("file", tmpFile.getName(), "text/plain", IOUtils.toByteArray(fileInputStream));
                //获取当前的日期,按日期归档
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
                String format = sdf.format(new Date());
                //获取到本地磁盘的路径,先建立路径
                File file = new File(filePath + format);
                if (!file.isDirectory()) {
    
    
                    file.mkdirs();
                }
                //初始文件名
                String originName = tmpFile.getName();
                //后缀名
                String suffix = originName.substring(originName.lastIndexOf("."));
                //存加密后的uuid+后缀作为存到path里的文件名
                String fileName = UUID.randomUUID() + suffix;
                File dest = new File(file.getAbsoluteFile() + File.separator + fileName);
                String filePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/company/" + format + fileName;
                multipartFile.transferTo(dest);
                company.setLogo(filePath);
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

4.5 postman测试excel导入接口

第一步:先将url填写完整,然后参数传入,选择Body-->form-data以数据表格的方式提交
然后参数填写你固定的参数名,参数类型选择file而不是默认的text文本,其value选择你刚才创建好的excel导入文件,选择添加即可。

具体演示如下:

在这里插入图片描述
第二步:点击Send,请求接口。查看接口结果返回。
在这里插入图片描述
控制台sq执行日志如下:
在这里插入图片描述
excel导入成功!!!

四、完整代码

点击此处进行下载

猜你喜欢

转载自blog.csdn.net/qq_26383975/article/details/126717784
今日推荐