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

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
iOS16发热耗电严重?这是原因和解决办法iOS16自发布以来已经收获了23以上的升级率,实际体验下来也有不少变化和新功能。比如照片部分相册默认上锁重复项目,电池百分比显示,锁屏小组件等等。但是不少用户反馈,在升级iOS1仙游拔智齿智齿总发炎但是又不敢拔,有没有什么办法可以预防?1)保持口腔卫生早晚刷牙饭后漱口,每次刷牙时间三分钟,采用巴氏刷牙法。定期到医院由口腔科医生进行洁牙,建议每年1到2次,深度清洗(龈下刮治)12次。每年至少一次口腔检查。在智齿生长进口补贴,是抵消美国加息的有效办法进口补贴,是抵消美国加息的有效办法一个国家人民的生活水平,不是取决于有多少货币,而是取决于有多少物资财富。威廉配第早就提出劳动是财富之父,土地是财富之母,纸币仅仅是财富的记号。物价华为nova10SE曝光,中置打孔直屏设计今年7月,华为带来了全新的nova10系列手机产品。本次nova10系列共有两款产品,nova10以及nova10Pro,其尺寸分别为6。67英寸和6。78英寸。随着这一代华为no女篮世界杯中国已经提前晋级,后两场全输也没关系女篮世界杯正在激烈进行,美国四战全胜,单场轰出145分的破记录比分,震惊球迷!因此,其他球队目标都锁定在冲击亚军,比如中国,比利时,加拿大,澳大利亚等等。积分榜A组三队晋级,一队淘没人买了!苹果公司缩减了iPhone14的生产规模据外媒Macrumors报道,苹果正在缩减新款iPhone14的生产,因为对最新iPhone的需求似乎很低,该iPhone具有与去年iPhone和一年前芯片相同的设计。供应链员工称郭台铭捅刀华为,发表赏饭论,舔美给富士康带来了啥作为全球最大的手机代工厂商,富士康的综合实力十分强大,它在代工市场的地位更是坚不可摧。不过,如果没有苹果公司的支持,富士康可能无法取得今天这一成绩。要知道,富士康的营收主要来自苹果华为少有的性价比千元机,降至1899,1亿主摄鸿蒙OS66W随着华为Mate50系列的出现,华为又站在了风口浪尖,因为定价问题,有不少用户吐槽,4G手机还敢卖这么贵吗?但其实华为有自己的道理,敢与iPhone14系列同期发布,就充分证明华为跌至2119元,骁龙87012GB256GB,这才是两千档真香曲面屏手机经过多年的发展,以及国产手机厂商的兴起,目前曲面屏手机已经越来越便宜,曲面屏不再是高端旗舰的标配了,无论是中端市场,还是千元机市场都有曲面屏手机可选了,目前价格不到三千元的曲面屏手小米造车最新进展密集布局汽车产业链,涉及模拟集成电路车身装备离合器等多个领域小米和数家汽车产业链相关公司的投资合作关系,在短短几天内密集披露。9月16日,荣湃半导体(上海)有限公司发生工商变更,天眼查显示其注册资本增加5。26,从1525。5万元增至160数据库中常用的聚合函数学习oracle也有一段时间了,发现oracle中的函数好多,对于做后台的程序员来说,大把大把的时间还要学习很多其他的新东西,再把这些函数也都记住是不太现实的,所以总结了一下ora
俄乌冲突以来乌政坛最大地震!泽连斯基查内鬼,连发小都炒掉综合环球时报和环球网18日报道,乌克兰总统17日突然宣布炒掉两名高官,这两人分别是总检察长和国家安全局局长,这一举动引发舆论震惊。路透社指出,这是自2月24日俄罗斯对乌克兰开展军事2022最新电影7月18日上新精彩分享外太空的莫扎特(2022)抢先导演陈思诚主演黄渤荣梓杉姚晨范伟黄杨钿甜王一鸣陈思诚贾冰许君聪于洋梅婷黄觉范湉湉郎朗于波萧李臻瑱王宁黄星羱方洲桑平陈昊李泽宇类型喜剧科幻家庭制片国家地对华贸易战还能打下去吗?先给美国经济看看病最近美国媒体频频放风,拜登将很快决定取消对目前约3700亿美元中国输美商品中100亿美元日用品加征的关税,同时继续运用301条款对中国电池半导体等产业发动新的打击。美国政府发起的贸经济内循环之下,深耕西部城市,构建山河万象2022年的经济形势不是太好,这里面很重要的一个影响,就是房地产的发展速度大幅放缓,今年上半年的房地产销售,很多企业都出现了大幅下滑。之所以会这样,除了对经济形势的担忧之外,还有一CCTV5官宣更改直播计划!男篮亚洲杯中国VS印尼男篮亚洲杯小组赛全部结束,中国队在阵容残缺的情况下以2胜1负的战绩进入淘汰赛阶段,今晚中国队将面对东道主印尼队。印尼男篮归化球员马奎斯博尔登在克利夫兰骑士队有过NBA正赛出场记录的今天这一场印尼不能输,中国男篮也输不得本届亚洲杯,对中国男篮来说可谓是困难重重。世界杯预选赛多人因为健康问题无法出战,队内王牌周琦也仅仅赶上了小组赛最后一场。不久前的世预赛后遭遇人员上超出想象的损失,给备赛亚洲杯带来极引发质疑!美国政府拆除华为中兴设备报销计划仍缺30亿美元据路透社报道,美国电信监管机构联邦通信委员会(FCC)上周五告诉国会,该机构需要额外30亿美元来补贴电信运营商从美国网络中移出中国企业华为和中兴通讯的设备,这将使整个拆除和替换(r易建联与家人齐聚美国豪宅,33岁模特娇妻惊艳,儿子都是美国国籍男篮世界杯预选赛正在如火如荼地进行,中国男篮与中国台北澳大利亚和日本队分在了同一个小组。随着小组赛中第三场比赛的结束,中国队以48比71大比分落败澳大利亚。目前中国队已经取得1胜238艘救援船艇参与福景001轮救援正逐步扩大搜救范围中国青年报客户端广州7月3日电(中青报中青网记者林洁)记者刚刚从广东省海上搜救中心获悉,海上风电场项目施工浮吊船福景001轮走锚遇险后,广东省海上搜救中心迅速开展救援行动。7月2日彝族小城退了733对娃娃亲,更难退的是彩礼2016年11月,四川省凉山彝族自治州,新娘和伴娘换上彝族婚礼服装。图文无关。(人民视觉图)一项古老的婚俗,随着当地政府移风易俗的新闻,进入公众视野截至2022年6月27日,四川省张学友回应质疑!发声明表示爱国爱港我以身为中国人感到骄傲早前,香港回归,央视找来很多知名艺人录制视频庆祝这个节日,但张学友的一番言论却遭到大量网友质疑,甚至认为张学友不爱国,但事实真的是这样吗?不提祖国就是不爱国吗?针对张学友的言论,诸