范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

SpringStarter快速实现Excel导入导出的方法

  自我介绍IT 果果
  一个普通的技术宅,欢迎点赞、关注和转发,请多关照。入门和安装简介
  为了满足项目中快速实现 excel 导入导出的功能,将 excel 开源工具 easypoi 整合成 spring-boot-starter 的方式,在做到对 easypoi 无侵入的同时减少了一些重复代码。例如: 增强了 easypoi 对于字段值重复校验的功能; 提升了字典转换的便捷性和效率; 增加了字段之间联动转换的功能;
  这些场景也是我在平时项目上经常会用到的功能点,为了避免重复造轮子,减少冗余代码,所以写了一个 easypoix-spring-boot-starter 扩展 jar 包。 安装在你的 maven 项目中引用 maven 依赖      com.itguoguo     easypoix-spring-boot-starter     1.0.0.RELEASE 在你的 spring boot 项目配置文件中加入字典前缀(可选) itguoguo.easypoix.dictPrefix=basic:dict:工具spring-boot-starter
  SpringBoot 核心就是几个注解:SpringBootConfiguration、EnableAutoConfiguration、ComponentScan ,依赖这几个注解完成了所谓自动装配的功能,这个自动装配说简单点就是把你需要的 Bean 注入到 Spring 容器里面。(SpringBootApplication 启动类上的注解,只是简单的组合了 SpringBootConfiguration、EnableAutoConfiguration、ComponentScan 几个注解,避免开发者一个一个的去加)。
  SpringBoot 程序在启动过程中会解析 SpringBootConfiguration、EnableAutoConfiguration、ComponentScan 三个注解 : SpringBootConfiguration:包含了 Configuration 注解,实现配置文件 ComponentScan:指定扫描范围 EnableAutoConfiguration:通过源码可以知道,该注解使用 Import 引入了 AutoConfigurationImportSelector 类,而 AutoConfigurationImportSelector 类通过 SpringFactortisLoader 加载了所有 jar 包的 MATE-INF 文件夹下面的 spring.factories 文件,spring.factories 包含了所有需要装配的 XXXConfiguration 类的全限定名。XXXConfiguration 类包含了实例化该类需要的信息,比如说如果这是个数据源 Configuration 类,那么就应该有数据库驱动、用户名、密码等等信息。
  Spring Boot 在启动的时候会干这几件事情 : Spring Boot 在启动时会去依赖的 Starter 包中寻找 resources/META-INF/spring.factories 文件,然后根据文件中配置的 Jar 包去扫描项目所依赖的 Jar 包。 根据 spring.factories 配置加载 AutoConfigure 类 根据 @Conditional 注解的条件,进行自动配置并将 Bean 注入 Spring Context
  总结 : SpringBoot 并没有想象那么神秘,就是这么几件事情:
  1.提供了一个配置类,该配置类定义了我们需要的对象的实例化过程;
  2.提供了一个 spring.factories 文件,包含了配置类的全限定名;
  3.将配置类和 spring.factories 文件打包为一个启动器 starter;
  4.程序启动时通过加载 starter.jar 包的 spring.factories 文件信息,然后通过反射实例化文件里面的类。easypoi
  独特的功能 基于注解的导入导出,修改注解就可以修改 Excel 支持常用的样式自定义 基于 map 可以灵活定义的表头字段 支持一对多的导出,导入 支持模板的导出,一些常见的标签,自定义标签 支持 HTML/Excel 转换,如果模板还不能满足用户的变态需求,请用这个功能 支持 word 的导出,支持图片,Excel
  使用 1.easypoi 父包–作用大家都懂得 2.easypoi-annotation 基础注解包,作用于实体对象上,拆分后方便 maven 多工程的依赖管理 3.easypoi-base 导入导出的工具包,可以完成 Excel 导出,导入,Word 的导出,Excel 的导出功能 4.easypoi-web 耦合了 spring-mvc 基于 AbstractView,极大的简化 spring-mvc 下的导出功能 5.sax 导入使用 xercesImpl 这个包(这个包可能造成奇怪的问题哈),word 导出使用 poi-scratchpad,都作为可选包了
  Maven 坐标      cn.afterturn     easypoi-base     4.1.0       cn.afterturn     easypoi-web     4.1.0       cn.afterturn     easypoi-annotation     4.1.0 
  使用场景
  我们的目标是尽可能使用一个工具类方法就能实现简单的导出和导入 Excel 的功能,以下列出了几个常见的场景供参考。 简单导出 Excel实现步骤
  新建一个导出实体模型,@ExcelFileAttr 注解提供导出 Excel 的文件名,@Excel 注解提供表头的字段,其中 name 属性是字段名称,dict 属性是字典的关键字常量 @Data @ExcelFileAttr(fileName = "导出.xls") public class ExportPersonExcelModal implements Serializable {     @Excel(name = "姓名")     private String name;     @Excel(name = "性别", dict = DICT_XB)     private String sex;     @Excel(name = "民族", dict = DICT_MZ)     private String mz; }
  使用工具类 EasyPoiUtil 的 exportExcel 方法即可实现 excel 导出功能,只需要传递两个参数 。 Excel 数据列表 HttpServletResponse 输出流 EasyPoiUtil.exportExcel(list, response);比较 EasyPoi 和 EasyPoiX
  相对于 EasyPoi 官方的导出方式,EasyPoiX 对于导出时字典的处理更加方便,不需要额外提供
  IExcelDictHandler 实现,EasyPoi 的 IExcelDictHandler 接口两个实现方法如下: /**  * 从值翻译到名称  * @param dict  字典 Key  * @param obj   对象  * @param name  属性名称  * @param value 属性值  * @return  */ public String toName(String dict, Object obj, String name, Object value);  /**  * 从名称翻译到值  * @param dict  字典 Key  * @param obj   对象  * @param name  属性名称  * @param value 属性值  * @return  */ public String toValue(String dict, Object obj, String name, Object value);
  toName 方法用于导出时字典值到字典名称的转换;toValue 方法用于导入时字典名称到字典值的转换。如果使用 EasyPoi,则多个字典公用一个 IExcelDictHandler 接口时需要多个 if-else 判断,并且在 Excel 导入导出时重复查询同一个字典时会有效率问题,另外在项目中多个字典的查询接口往往是同一个方法,所以显得代码重复不美观。
  为了解决以上问题,EasyPoiX 在导出时提供了字典转换的默认字典转换接口,且不需要在工具类中传参指定(如果有特殊要求也可以指定自定义的字典转换接口)。那么问题来了,字典的取值方法在哪里定义呢?EasyPoiX 提供了一个@ExcelDictDataType 注解和一个 ExcelDictDataService 接口,代码示例如下: @ExcelDictDataType({DICT_XB, DICT_MZ, DICT_COMMUNITY}) @Component public class BasicDictDataService implements ExcelDictDataService {     public static final String DICT_XB = "XB";     public static final String DICT_MZ = "MZ";      @Override     public Map getData(DataParam params) {         // 获取字典值的实现代码         // 不论是字典的名称转值还是值转名称,都会从这里取值         // 返回的 Map 类型,key 是字典值,value 是字典名称         return map;     } }IExcelDictHandler 接口,要在导出方法里显示的传参;ExcelDictDataService 接口不需要显示传参,因为@ExcelDictDataType 注解已经标注当前类就是字典取值的实现类,注解的 value()属性里配置的是字典的 key,可以提供多个字典的 key,所以 ExcelDictDataService 接口可以满足多个字典的取值。 IExcelDictHandler 接口需要正反向两个转换方法;ExcelDictDataService 接口只需要实现一个字典取值方法。 IExcelDictHandler 接口需要在实现方法中加入多个 if-else,并且在 Excel 导入导出时频繁调用 toName 和 toValue 方法会导致效率问题;ExcelDictDataService 接口不需要通过 if-else 判断,且每次取值都会先从本地缓存中查询,如果缓存没有才会进行真正的查询调用。在一次请求结束之后,会清除这些缓存以免造成内存不足。 大数据导出 Excel实现步骤
  使用工具类 EasyPoiUtil 的 exportBigExcel 方法即可实现 excel 大数据导出功能,传参: 实体模型 Class IExcelExportServer 接口。可以使用默认接口实现类 DefaultBigExcelExportServer,构造方法需要提供一个分页查询的 lamda 表达式 分页查询的条件参数,Object 类型 HttpServletResponse 输出流 DefaultBigExcelExportServer ser = new DefaultBigExcelExportServer((queryParams, page) -> findPage(queryParams, page)); EasyPoiUtil.exportBigExcel(ExportPersonExcelModal.class, ser, param, response);比较 EasyPoi 和 EasyPoiX
  EasyPoi 需要实现 IExcelExportServer 接口,EasyPoiX 不需要实现,而是传递一个 DefaultBigExcelExportServer 对象,构造对象时提供一个分页查询的 lamda 表达式
  或者叫分页查询方法。这样的好处是不需要为每一个 Excel 都单独新建一个 IExcelExportServer 接口实现类。 /**  * 导出数据接口  */ public interface IExcelExportServer {     /**      * 查询数据接口      * @param queryParams 查询条件      * @param page        当前页数从 1 开始      * @return      */     public List selectListForExcelExport(Object queryParams, int page); }导入 Excel
  导入 Excel 场景相对于导出场景要复杂一些,除了调用工具类的导入方法和字典转换取值实现以外,还额外增加了两个场景 :1、数据校验;2、数据处理。这两个场景都不是导入时的必选步骤,但都很常见。下面就对这两个场景详细说明一下。 数据校验
  EasyPoi 提供了一个数据校验接口 IExcelVerifyHandler /**  * 导入校验接口  * @author JueYue  *  2014 年 6 月 23 日 下午 11:08:21  */ public interface IExcelVerifyHandler {     /**      * 导入校验方法      * @param obj      *            当前对象      * @return      */     public ExcelVerifyHandlerResult verifyHandler(T obj); }
  EasyPoiX 对其进行了一个小优化,增加了数据重复的校验功能,比如导入人员名单时,出现了相同的身份证号会提示后面出现的那个身份证号重复。使用方法也很简单,只需要继承一个 DefaultExcelVerifyHandler 类即可,示例代码如下: @Component public class ImportPersonExcelVerifyHandler extends DefaultExcelVerifyHandler {     @Override     public ExcelVerifyHandlerResult verifyHandler(ImportPersonExcelModal obj) {         Set idCards = getRepeatTmp("idCard");         if (idCards.contains(obj.getIdCard())) {             return new ExcelVerifyHandlerResult(false, "证件号重复");         }         idCards.add(obj.getIdCard());         return new ExcelVerifyHandlerResult(true);     } }
  这里要特别指出一下,返回的 ExcelVerifyHandlerResult 类型构造时如果 success 参数传 true 就表示校验通过;如果传 false,就会在导入方法返回的导入数据中校验不通过的那个元素中,errorMsg 设置为校验错误的提示信息。所以导入的实体类需要继承 ImportExcelModel 类。 public class ImportExcelModel implements Serializable, IExcelDataModel, IExcelModel {     /**      * 行号      */     private int rowNum;     /**      * 错误消息      */     @Excel(name = "错误信息")     private String errorMsg;      @Override     public int getRowNum() {         return rowNum;     }     @Override     public void setRowNum(int rowNum) {         this.rowNum = rowNum;     }     @Override     public String getErrorMsg() {         return errorMsg;     }     @Override     public void setErrorMsg(String errorMsg) {         this.errorMsg = errorMsg;     } }数据处理
  数据处理的场景其实和数据字典的场景非常相似 ,都是需要对 excel 数据做一些转换操作。但是他们的 不同点 在于数据字典更偏向于转换全局唯一的常量,所以@Excel 注解里的 dict 属性在不同 Excel 实体里都是共用的;而数据处理是在数据字典转换操作完成以后进行的,因为数据处理的字段在转换时可能会用到当前 Excel 行的其他字段,包括转换后的字典值。
  举个例子,比如导入的 excel 行数据多个字段之间存在联动查询的关系,就需要自定义数据处理了。例如导入的一行字段里有小区和楼栋,小区名称和小区 id 的转换不需要依赖其他字段,但是楼栋名称和楼栋 id 的转换是需要根据小区 id 查询的,虽然同样可以通过字典方式转换,但是最好还是在字典转换之后,数据处理的步骤再转换更安全。
  此外,字典转换做不到同一个关键字在不同实体里,使用不同的转换逻辑,因为字典的含义本身就是全局唯一的。而数据处理转换可以做到同一个关键字在不同实体里,使用不同的转换实现。下面用 EasyPoi 和 EasyPoiX 的两种代码实现来更加详细的介绍他们的区别。 EasyPoi 的数据处理
  EasyPoi 提供了默认数据处理器虚类 ExcelDataHandlerDefaultImpl public abstract class ExcelDataHandlerDefaultImpl implements IExcelDataHandler {     /**      * 需要处理的字段      */     private String[] needHandlerFields;      // 省略部分代码.....      @Override     public Object importHandler(T obj, String name, Object value) {         return value;     }     @Override     public Object exportHandler(T obj, String name, Object value) {         return value;     }     @Override     public void setNeedHandlerFields(String[] needHandlerFields) {         this.needHandlerFields = needHandlerFields;     } }setNeedHandlerFields 方法用来指定哪些字段需要处理,参数是一个字符串数组,每个元素对应的是 Excel 实体里@Excel 注解的 name 属性,即 Excel 的表头名称 importHandler 接口可以重写为我们需要的转换逻辑,默认是返回原始 value,即不转换字段 exportHandler 接口可以重写为我们需要的转换逻辑,默认是返回原始 value,即不转换字段
  现在,继承 ExcelDataHandlerDefaultImpl 类就可以实现数据处理了 @Component public class PersonExcelDataHandler extends ExcelDataHandlerDefaultImpl {     @PostConstruct     public void init() {         setNeedHandlerFields(new String[]{"小区", "楼栋"});     }          @Override     public Object importHandler(ImportPersonExcelModal obj, String name, Object value) {         if(Objects.isNull(value)){             return value;         }         if(name.equals("楼栋")){             //根据 obj.getCommunityId() 和 obj.getBuildingName(),查询楼栋 id 			return 楼栋 id;         }         return value;     }      @Override     public Object exportHandler(ImportPersonExcelModal obj, String name, Object value) {         if(Objects.isNull(value)){             return value;         }         if(name.equals("楼栋")){             //根据 obj.getCommunityId() 和 obj.getBuildingId(),查询楼栋名称 			return 楼栋名称;         }         return value;     } }EasyPoiX 的数据处理
  EasyPoiX 封装了一个 SimpleExcelDataHandler 虚类,继承这个虚类就可以免去手动调用 setNeedHandlerFields 方法的麻烦。
  另外,SimpleExcelDataHandler 默认提供了 importHandler 和 exportHandler 两个接口的实现,同字典转换一样,只需要提供一个 getData 接口的实现,提供待处理数据的取值逻辑即可。 @Component @ExcelHandleDataType(clazz = ImportPersonExcelModal.class, value = {BUILDING_NAME, UNIT_NAME}) public class PersonExcelDataHandler extends SimpleExcelDataHandler {     public static final String BUILDING_NAME = "楼栋";     public static final String UNIT_NAME = "单元";          @Override     public Map getData(DataParam params) {         switch (params.getDict()) {             case BUILDING_NAME:                 return getBuildingData(params);             case UNIT_NAME:                 return getUnitData(params);             default:                 return null;         }     }      private Map getBuildingData(DataParam params) {         Object row = params.getRow();         String communityId = BeanUtil.getProperty(row, "communityId");         //返回楼栋键值对,key 是楼栋 id,value 是楼栋名称     }      private Map getUnitData(DataParam params) {         Object row = params.getRow();         String buildingId = BeanUtil.getProperty(row, "buildingId");         //返回单元键值对,key 是单元 id,value 是单元名称     }  }
  DataParam.java @Data @Accessors(chain = true) public class DataParam {     private String dict;     private String key;     private Object row; }
  如果实际业务不需要默认的数据处理实现,也可以在继承 SimpleExcelDataHandler 虚类之后,重写 importHandler 和 exportHandler 接口,就像 EasyPoi 的数据处理方式一样,这样更加灵活。 总结
  EasyPoiX 是为了能够快速导入导出 Excel,而对 EasyPoi 进行的一个无侵入的二次封装,同时利用了 spring-boot-starter 的原理,使其在 spring-boot 项目中可以以 jar 模块的形式复用 EasyPoiX 的功能。如果有小伙伴在实际的使用中遇到了其他场景,也可以联系我。
  我叫  IT果果 ,下面有我的联系方式,谢谢! 请联系我IT 果果
  一个普通的技术宅,欢迎点赞、关注和转发,请多关照。
  以上场景都有对应的测试代码示例,如果想更进一步了解请访问地址:
  https://gitee.com/chenzhaoplus/easypoix-spring-boot-starter
  https://github.com/chenzhaoplus/easypoix-spring-boot-starter
  https://blog.csdn.net/cz285933169?spm=1010.2135.3001.5421
春季,多给孩子吃8道健脑补脑食物,天然叶酸高,常吃身体棒春季早晚温差大,气候比较干燥,尤其是家里有孩子的,学习用脑多,日常饮食上要加强营养,建议多给孩子吃健脑补脑食物,天然叶酸高,常吃学习好,身体棒!豆类豆类蛋白质和氨基酸含量高,以谷氨育儿先育已,做情绪稳定的父母有多重要你有没有在育儿方面有那么一瞬间突然崩溃的一刻,丧偶式的育儿方式,让你觉得十分不爽四,自己一个人承包了所有孩子的衣食住行,学习和家务,而另一半整天在外奔波忙碌,晚上很晚回来,早上又说春天湿气重,家有孩子饮食要注意,多吃这5样,千万别不当回事春天最显著的特点就是,温差大湿寒重。特别是4月的天气,对饮食就更讲究了。黄帝内经提倡春夏养阳的饮食原则,适当地吃一些温补助阳的食物。尤其是家里有孩子的朋友,建议春天饮食别太随意,多极致轮换绝对底蕴广东用最悲壮的方式,站着结束赛季底蕴,敬意。半决赛第三战,二飞莱多之后周队也无法出战,逼迫杜指导和广东队在背水一战再次祭出极致轮换。汤杰和王薪凯这样特点鲜明但平日不敢重用的球员早早替补登场,并在半场用坚决的执行力不愧是状元!爱德华兹季后赛首秀轰346创队史第1人客场开门红北京时间4月17日,202122赛季NBA季后赛迎来首个比赛日。在一次关键西部对决中,森林狼队客场挑战灰熊队。在附加赛中,森林狼队主场109104击败快船队,以西部第7身份进入季后欠薪7千万!创中国足坛最高纪录,90后女老板回应一定还钱作为前中超黑马,贵州队已经解散了,本来,该队要征战中甲,但放弃资格。现在,前贵州球员杨挺透露,贵州队累计欠薪7千万人民币,平均每人两三百万,创下中国足坛有报道拖欠薪水情况以来的最高莎士比亚最经典的10句话,识透人性,说透人生人们都说,一千个人眼中,有一千个哈姆雷特。可一千个哈姆雷特,也无法缔造出一个莎士比亚。几百年来,莎士比亚在每个时代都会受到无数天才的追捧。歌德为他着迷我读到他的第一页,就使我这一生老爸天天带女儿瞎玩,孩子上学后专注力超群,方法简单易学老爸天天带女儿瞎玩,孩子上学后专注力超群方法简单易学前天中午午休时,收到了女儿班主任老师发来的信息,点开一看是一段女儿在幼儿园午休的视频,只见其他孩子乱哄哄的,有的在躺着,有的孩子孩子头上的旋代表什么?与智商和性格有关吗?医生告诉你答案儿童的身体特征以及生命体征是根据自行体内的潜在性血型基因突变以及潜在性遗传基因所决定的一种临床特性,体内的基因突变是通过父母的血型传导以及父母潜在性的性格和疾病遗传因素转化而来的一冰雪运动对孩子生长发育有益医生担心寒气没有科学依据2022北京冬奥会掀起中国冰雪运动热潮,越来越多家长带着孩子尝试冰雪运动。对此,湖北省人民医院(武汉大学人民医院)运动医学与关节损伤科主任李皓桓表示,青少年积极参与冰雪运动,能锻炼严父慈母和严母慈父,哪种对孩子更好?跟想象不一样文媛妈育儿日记原创,欢迎个人转发和分享在教育孩子的问题上,中国家长习惯于一个唱红脸一个唱白脸,在爸爸妈妈之中,总要有一个人打巴掌,一个人给甜枣。而大部分的家庭模式都是男主外女主内,
在大厂做程序员两年半,我终于学会了IT互联网的发展带给我们很多快乐,也放大了焦虑,即便是程序员也不例外!他们抓住了互联网的红利,可谓名利兼收。那么问题来了,长期做程序员,会失去什么?盘点了字节阿里腾讯网易四个大厂程花开中国春色锦绣央视网消息(新闻联播)大江南北,鲜花盛开。从城市到乡村,处处春色锦绣,人们纷纷走出家门,感受美好生活。鲜花美景入城中。在广东佛山,五彩缤纷的花海里,大花海棠天竺葵等上百种鲜花盛开。看颜值的时代,文具是例外!这样选购文具才安全!江苏省中小学幼儿园已经基本开学很多家长都会给孩子准备上学所需的文具面对五花八门的文具用品家长该如何给孩子挑选?挑选文具时应该注意什么?江苏市场监管部门给出了消费提示首先,白度太高的广州老字号凸显三大消费撬动力广州国资系统正推动老字号焕新发展提质升级。图为陈李济博物馆大厅。南方日报记者吴伟洪摄2023年开年,广州市提出三个一万亿支撑全市地区生产总值突破3万亿元的年度目标。全年固定资产投资惠民县优生优育知识讲座走进孙武街道活动大众网海报新闻记者段峰通讯员张鹏鹏纪晓阳滨州报道为增强广大妇女孕期保健意识,预防孕产期的各种常见病多发病,提高生育质量和健康保障水平。2月15日,孙武街道社区卫生服务中心联合滨州市只打了3分钟,直接被弃用!为湖人出工出力,你不该落得如此下场湖人队的朗尼沃克,正在逐渐丧失教练组的信任。今天对阵鹈鹕,他只在垃圾时间打了3分20秒,出手4次得到4分。这是朗尼沃克连续第三场比赛上场时间少于15分钟,本赛季首次出现。而二月份之2023芜湖航空马拉松将于3月26日鸣枪开跑大皖新闻讯2月15日,2023芜湖航空马拉松新闻发布会在国家体育总局北京体育馆隆重召开。中国田径女子800米著名运动员王春雨,安徽芜湖联合飞机公司董事长田刚印,作为赛事特聘形象大使中国足协官方2月15日3月5日提交准入材料,最强阵容踢杯赛北京时间2月15日,中国足协在官网发布中国足球协会关于开展2023赛季中超中甲和中乙联赛俱乐部准入工作的通知,要求各俱乐部2月15日至3月5日提交准入材料,此外要求各获得20232消化不良肠胃不适?如何应对节后后遗症?试试这样(转自运动四川)每逢佳节胖三斤,春节期间每一顿都少不了大鱼大肉,那么如何在节后通过科学的运动和饮食调整,减轻肠胃负担,恢复健康生活呢?壹饮食调节1清淡饮食节后要调整为清淡饮食,荤素斯诺克威尔士公开赛袁思俊庞俊旭挺进16强中新社北京2月16日电在北京时间16日晨结束的2023年斯诺克威尔士公开赛正赛第3日赛事中,两名中国00后小将袁思俊和庞俊旭挺进16强。另一名中国选手田鹏飞也在64进32的比赛中顺车迷定期盛宴,速度与激情10发布三分钟预告片!看到下面这个镜头,你想起了什么?对!速度与激情的第10作要来了。速10将在今年5月13日在北美首映,在首张海报里,唐老大手握经典的十字架项链,似乎在低头祈祷。速9里上太空飙车的设定