如何解決EasyExcel導(dǎo)出文件LocalDateTime報(bào)錯(cuò)問題
解決EasyExcel導(dǎo)出文件LocalDateTime報(bào)錯(cuò)
問題引出
我在參與一個(gè)項(xiàng)目的時(shí)候接觸到數(shù)據(jù)表格導(dǎo)出為Excel表格的需求,但是在導(dǎo)出的時(shí)候會(huì)出現(xiàn)報(bào)錯(cuò)
Cannot find ‘Converter’ support class LocalDateTime
原因是我需要導(dǎo)出的實(shí)體類中存在 LocalDateTime 類型的屬性,而又恰巧 EasyExcel 不支持 LocalDate 和 LocalDateTime 接收數(shù)據(jù),啊人生。
解決方案
在尋找了多篇文章之后,在下面對(duì)這個(gè)問題進(jìn)行總結(jié),既然默認(rèn)不支持我使用這個(gè)類型,那就殺出一條路來(lái)。
首先先來(lái)看報(bào)的錯(cuò)誤提示:
Cannot find ‘Converter’ support class LocalDateTime
明顯可以看出來(lái)是找不到 LocalDateTime 的一個(gè) Converter,那么這個(gè)所謂的 Converter 到底是個(gè)什么東西呢?既然他缺少這個(gè)東西我們能不能給他自己弄一個(gè)上去呢?說干就干?。ㄆ鋵?shí)解決方法也真就是這個(gè))
自定義Converter
Converter 在這里其實(shí)是一個(gè)字段轉(zhuǎn)換器,在 EasyExcel 中擔(dān)任將Java屬性轉(zhuǎn)換成Excel表格中合法數(shù)據(jù)的一個(gè)小東西。
由于EasyExcel自己沒有我們需要的 LocalDateTime 的字段轉(zhuǎn)換器,那我們就自己搞一個(gè)出來(lái)。
在 config 包下新建一個(gè)自定義的字段轉(zhuǎn)換器 LocalDateTimeConverter 。
package edu.lingnan.rili.converter; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.property.ExcelContentProperty; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; /** * @author xBaozi * @version 1.0 * @classname LocalDateTimeConverter * @description EasyExcel LocalDateTime轉(zhuǎn)換器 * @date 2022/3/19 2:17 */ public class LocalDateTimeConverter implements Converter<LocalDateTime> { private static final String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss"; @Override public Class<LocalDateTime> supportJavaTypeKey() { return LocalDateTime.class; } @Override public CellDataTypeEnum supportExcelTypeKey() { return CellDataTypeEnum.STRING; } @Override public LocalDateTime convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return LocalDateTime.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern(DEFAULT_PATTERN)); } @Override public CellData<String> convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return new CellData<>(value.format(DateTimeFormatter.ofPattern(DEFAULT_PATTERN))); } }
引用 LocalDateTimeConverter
既然這東西是本來(lái)沒有然后我們自己弄出來(lái)的,那肯定要告訴程序:**誒!這里我給你生了個(gè)崽,要記得領(lǐng)回去??!**所以,我們?cè)谠拘枰獙?dǎo)出的 LocalDateTime 類型中的 @ExcelProperty
注解中引入自定義的字段轉(zhuǎn)換器。
同時(shí)要加上一個(gè)JsonFormat的格式化注解,將該屬性轉(zhuǎn)換成 json格式,這里要注意的就是要導(dǎo)入一下阿里巴巴的 fastjson Maven坐標(biāo)了。
@ExcelProperty(value = "操作時(shí)間", index = 8, converter = LocalDateTimeConverter.class) @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss") @ApiModelProperty("操作時(shí)間") private LocalDateTime operationTime;
<!-- fastjson的Maven坐標(biāo) --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.73</version> </dependency>
好啦!到這里我們遇到的問題就已經(jīng)解決了呀!雖然說前期剛遇到這個(gè)問題的時(shí)候一直在被折磨,但是卻是一個(gè)很好的一個(gè)提升機(jī)會(huì),沒點(diǎn)兒bug,怎么能保得住頭發(fā)呢是吧。
EasyExcel導(dǎo)出問題
報(bào)錯(cuò)信息?。?!
錯(cuò)誤一:
com.alibaba.excel.exception.ExcelAnalysisException: java.lang.NoClassDefFoundError: Could not initialize class net.sf.cglib.beans.BeanMap$Generator
com.alibaba.excel.exception.ExcelAnalysisException: java.lang.VerifyError: class net.sf.cglib.core.DebuggingClassWriter overrides final method visit.(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V
上面兩種報(bào)錯(cuò)?。?!都是一個(gè)原因,各種查詢之后,說是版本沖突,這種就很頭疼
經(jīng)過排查,我在pom中將單元測(cè)試的依賴注解之后,導(dǎo)入就正常了
錯(cuò)誤二:
com.alibaba.excel.exception.ExcelDataConvertException: Can not find 'Converter' support
原因:默認(rèn)只能轉(zhuǎn)換BigDecimal、Bolean、Byte[]、btye[]、Byte、Date、Double、File、Float、InputStream、Integer、Long、Short、URL幾種類型,== 所以必須自己手動(dòng)編寫一個(gè)轉(zhuǎn)換類==
我原本得實(shí)體類:用的數(shù)據(jù)類型是:LocalDateTime,不能自動(dòng)轉(zhuǎn)換
修改后:自己編輯了一個(gè)轉(zhuǎn)換類LocalDateConverter
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ExcelProperty(value="時(shí)間",index = 10,converter = LocalDateConverter.class) @ColumnWidth(25) private LocalDateTime turnoutTime;
LocalDateConverter
import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.property.ExcelContentProperty; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class LocalDateConverter implements Converter<LocalDateTime> { @Override public Class<LocalDateTime> supportJavaTypeKey() { return LocalDateTime.class; } @Override public CellDataTypeEnum supportExcelTypeKey() { return CellDataTypeEnum.STRING; } @Override public LocalDateTime convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception { return LocalDateTime.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); } @Override public CellData convertToExcelData(LocalDateTime localDate, ExcelContentProperty excelContentProperty , GlobalConfiguration globalConfiguration) throws Exception { return new CellData<>(localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); } }
一般情況下應(yīng)該是解決了?。?!
但是部署后問題還是一樣!!也不知道為什么沒有生效。
于是乎,經(jīng)過不斷得嘗試,還是報(bào)一樣得錯(cuò),無(wú)奈之下我只能在:EasyExcel寫入數(shù)據(jù)之前得到list集合循環(huán)遍歷,然后逐個(gè)用字符串進(jìn)行時(shí)間轉(zhuǎn)換
實(shí)體類更改:用一個(gè)String字符來(lái)代替LocalDateTime 來(lái)寫入Excel
代碼
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ExcelIgnore // @ExcelProperty(value="時(shí)間",index = 10,converter = LocalDateConverter.class) private LocalDateTime turnoutTime; @ExcelProperty(value="時(shí)間",index = 10) private String turnoutTimeString;
邏輯層更改
List<Student> stus= (List<Student>) studentService.listByIds(student.getIds()); log.info("stuss數(shù)據(jù)條數(shù):{}",stus.size()); List<Student> list = JSON.parseArray(JSON.toJSONString(stus), Student.class); for (Student stu: list) { //類型的判斷 String sex="男"; if (stu.getSex() == 1) { sex="男"; } else if (stu.getSex() == 2) { sex="女"; } stu.setSexName(sex); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); //將LocalDateTime轉(zhuǎn)換String stu.setTurnoutTimeString(stu.getTurnoutTime().format(formatter)); } excelWriter.write(list, sheet); excelWriter.finish();
最后到這里再進(jìn)行運(yùn)行,就沒什么問題了,只是可能有些性能的消耗,畢竟要是數(shù)據(jù)量大,10w+的數(shù)據(jù),這種情況有待考量,至于轉(zhuǎn)換類不生效的問題后期發(fā)現(xiàn)了再更吧,有知道的伙計(jì)們也分享一下唄?。。ㄆ婀值氖俏以谧⒔饫锩婕拥胕ndex = 10得序號(hào)和 @ColumnWidth(25)都沒有生效,當(dāng)然類型的轉(zhuǎn)換類也沒有生效?。。。?/p>
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot集成Milvus實(shí)現(xiàn)數(shù)據(jù)增刪改查功能
milvus支持的語(yǔ)言比較多,支持python, Java, Go,node等開發(fā)語(yǔ)言,本文主要介紹如何使用Java語(yǔ)言,采用springboot框架集成和調(diào)用Milvus數(shù)據(jù)庫(kù),這篇文章主要介紹了SpringBoot集成Milvus,實(shí)現(xiàn)數(shù)據(jù)增刪改查,需要的朋友可以參考下2025-04-04SpringBoot使用Sa-Token實(shí)現(xiàn)路徑攔截和特定接口放行
這篇文章主要介紹了SpringBoot使用Sa-Token實(shí)現(xiàn)路徑攔截和特定接口放行,文中通過代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-06-06JavaWeb實(shí)現(xiàn)顯示mysql數(shù)據(jù)庫(kù)數(shù)據(jù)
MySQL是最流行的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),在WEB應(yīng)用方面MySQL是最好的。本文將利用JavaWeb實(shí)現(xiàn)顯示mysql數(shù)據(jù)庫(kù)數(shù)據(jù)功能,需要的可以參考一下2022-03-03永久解決 Intellij idea 報(bào)錯(cuò):Error :java 不支持發(fā)行版本5的問題
這篇文章主要介紹了永久解決 Intellij idea 報(bào)錯(cuò):Error :java 不支持發(fā)行版本5的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02Spring中@PropertySource和@Value注解詳解
這篇文章主要介紹了Spring中@PropertySource和@Value注解詳解,@PropertySource注解可以方便和靈活的向Spring的環(huán)境容器(org.springframework.core.env.Environment Environment)中注入一些屬性,這些屬性可以在Bean中使用,需要的朋友可以參考下2023-11-11Java設(shè)計(jì)模式之原型模式詳細(xì)解讀
這篇文章主要介紹了Java設(shè)計(jì)模式之原型模式詳細(xì)解讀,原型模式屬于創(chuàng)建型設(shè)計(jì)模式,用于創(chuàng)建重復(fù)的對(duì)象,且同時(shí)又保證了性能,該設(shè)計(jì)模式的好處是將對(duì)象的創(chuàng)建與調(diào)用方分離,需要的朋友可以參考下2023-12-12