跳到主要内容

迁移指南:从 FastExcel 迁移到 Apache Fesod (Incubating)

概述​

本指南为从 cn.idev FastExcel 迁移到 Apache Fesod (Incubating) 提供全面的迁移路线。Apache Fesod (Incubating) 是该项目的演进版本,现已成为 Apache 软件基金会(孵化中)的一部分,提供同样的高性能 Excel 处理能力,并具有更强的社区支持和长期可持续性。

为什么要迁移?​

  • Apache 软件基金会支持:Apache Fesod (Incubating) 现已成为 Apache 软件基金会的一部分,确保长期维护和社区驱动的开发
  • 无缝过渡:API 几乎完全相同,只需最少的代码更改
  • 统一品牌:在 Apache Fesod (Incubating) 下统一的命名规范
  • 持续创新:在 Apache 治理下获得未来的增强和功能
  • 向后兼容:暂时保留已废弃的别名(FastExcel)以便逐步迁移

迁移范围​

本次迁移主要涉及:

  1. 更新 Maven/Gradle 依赖
  2. 将已废弃的类名替换为 FesodSheet
  3. 更新包导入
  4. 通过全面测试验证功能

核心 API、注解和处理逻辑保持不变,确保低风险的迁移路径。


迁移步骤​

步骤 1:更新依赖​

将现有依赖替换为 Apache Fesod (Incubating):

来源GroupIdArtifactId版本
cn.idev FastExcelcn.idev.excelfastexcel1.3.0
Apache Fesod (Incubating) ✅org.apache.fesodfesod-sheet2.0.2-incubating+

Maven 配置:

修改前:

<dependency>
<groupId>cn.idev.excel</groupId>
<artifactId>fastexcel</artifactId>
<version>1.3.0</version>
</dependency>

修改后:

<dependency>
<groupId>org.apache.fesod</groupId>
<artifactId>fesod-sheet</artifactId>
<version>2.0.2-incubating</version>
</dependency>

Gradle 配置:

修改前:

implementation 'cn.idev.excel:fastexcel:1.3.0'

修改后:

implementation 'org.apache.fesod:fesod-sheet:2.0.2-incubating'

注意: fesod-sheet 模块是 Excel/CSV 处理的核心模块。它会自动引入必要的依赖(fesod-common 和 fesod-shaded)。

步骤 2:更新包导入​

更新所有 import 语句以使用新的 Apache Fesod (Incubating) 包结构。

核心入口类替换:

修改前修改后
import cn.idev.excel.FastExcel;import org.apache.fesod.sheet.FastExcel;
import cn.idev.excel.FastExcelFactory;import org.apache.fesod.sheet.FastExcelFactory;
import cn.idev.excel.ExcelWriter;import org.apache.fesod.sheet.ExcelWriter;
import cn.idev.excel.ExcelReader;import org.apache.fesod.sheet.ExcelReader;

注意: 在此阶段之后,FastExcel.read(...) 和 FastExcelFactory.writerSheet(...) 依然可以编译通过,它们会解析到 Fesod 中带有 @Deprecated 标记的桥接类。 在 “步骤 3” 中我们会将它们彻底替换为规范的 FesodSheet 类。

读取 API 替换:

修改前修改后
import cn.idev.excel.read.listener.ReadListener;import org.apache.fesod.sheet.read.listener.ReadListener;
import cn.idev.excel.read.listener.PageReadListener;import org.apache.fesod.sheet.read.listener.PageReadListener;
import cn.idev.excel.read.metadata.ReadSheet;import org.apache.fesod.sheet.read.metadata.ReadSheet;
import cn.idev.excel.read.metadata.ReadWorkbook;import org.apache.fesod.sheet.read.metadata.ReadWorkbook;
import cn.idev.excel.read.metadata.ReadBasicParameter;import org.apache.fesod.sheet.read.metadata.ReadBasicParameter;
import cn.idev.excel.read.builder.ExcelReaderBuilder;import org.apache.fesod.sheet.read.builder.ExcelReaderBuilder;
import cn.idev.excel.read.builder.ExcelReaderSheetBuilder;import org.apache.fesod.sheet.read.builder.ExcelReaderSheetBuilder;
import cn.idev.excel.context.AnalysisContext;import org.apache.fesod.sheet.context.AnalysisContext;
import cn.idev.excel.event.SyncReadListener;import org.apache.fesod.sheet.event.SyncReadListener;

写入 API 替换:

修改前修改后
import cn.idev.excel.write.metadata.WriteSheet;import org.apache.fesod.sheet.write.metadata.WriteSheet;
import cn.idev.excel.write.metadata.WriteWorkbook;import org.apache.fesod.sheet.write.metadata.WriteWorkbook;
import cn.idev.excel.write.metadata.WriteTable;import org.apache.fesod.sheet.write.metadata.WriteTable;
import cn.idev.excel.write.metadata.WriteBasicParameter;import org.apache.fesod.sheet.write.metadata.WriteBasicParameter;
import cn.idev.excel.write.builder.ExcelWriterBuilder;import org.apache.fesod.sheet.write.builder.ExcelWriterBuilder;
import cn.idev.excel.write.builder.ExcelWriterSheetBuilder;import org.apache.fesod.sheet.write.builder.ExcelWriterSheetBuilder;
import cn.idev.excel.write.builder.ExcelWriterTableBuilder;import org.apache.fesod.sheet.write.builder.ExcelWriterTableBuilder;

写入拦截器替换:

修改前修改后
import cn.idev.excel.write.handler.WriteHandler;import org.apache.fesod.sheet.write.handler.WriteHandler;
import cn.idev.excel.write.handler.SheetWriteHandler;import org.apache.fesod.sheet.write.handler.SheetWriteHandler;
import cn.idev.excel.write.handler.CellWriteHandler;import org.apache.fesod.sheet.write.handler.CellWriteHandler;
import cn.idev.excel.write.handler.RowWriteHandler;import org.apache.fesod.sheet.write.handler.RowWriteHandler;
import cn.idev.excel.write.handler.WorkbookWriteHandler;import org.apache.fesod.sheet.write.handler.WorkbookWriteHandler;
import cn.idev.excel.write.handler.context.CellWriteHandlerContext;import org.apache.fesod.sheet.write.handler.context.CellWriteHandlerContext;

注解替换:

修改前修改后
import cn.idev.excel.annotation.ExcelProperty;import org.apache.fesod.sheet.annotation.ExcelProperty;
import cn.idev.excel.annotation.ExcelIgnore;import org.apache.fesod.sheet.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.format.DateTimeFormat;import org.apache.fesod.sheet.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.format.NumberFormat;import org.apache.fesod.sheet.annotation.format.NumberFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;import org.apache.fesod.sheet.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.HeadStyle;import org.apache.fesod.sheet.annotation.write.style.HeadStyle;
import cn.idev.excel.annotation.write.style.ContentStyle;import org.apache.fesod.sheet.annotation.write.style.ContentStyle;
import cn.idev.excel.annotation.write.style.HeadFontStyle;import org.apache.fesod.sheet.annotation.write.style.HeadFontStyle;
import cn.idev.excel.annotation.write.style.ContentFontStyle;import org.apache.fesod.sheet.annotation.write.style.ContentFontStyle;
import cn.idev.excel.annotation.write.style.HeadRowHeight;import org.apache.fesod.sheet.annotation.write.style.HeadRowHeight;
import cn.idev.excel.annotation.write.style.ContentRowHeight;import org.apache.fesod.sheet.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.OnceAbsoluteMerge;import org.apache.fesod.sheet.annotation.write.style.OnceAbsoluteMerge;
import cn.idev.excel.annotation.write.style.ContentLoopMerge;import org.apache.fesod.sheet.annotation.write.style.ContentLoopMerge;

转换器替换:

修改前修改后
import cn.idev.excel.converters.Converter;import org.apache.fesod.sheet.converters.Converter;
import cn.idev.excel.converters.AutoConverter;import org.apache.fesod.sheet.converters.AutoConverter;
import cn.idev.excel.converters.ReadConverterContext;import org.apache.fesod.sheet.converters.ReadConverterContext;
import cn.idev.excel.converters.WriteConverterContext;import org.apache.fesod.sheet.converters.WriteConverterContext;

枚举替换:

修改前修改后
import cn.idev.excel.enums.CellDataTypeEnum;import org.apache.fesod.sheet.enums.CellDataTypeEnum;
import cn.idev.excel.enums.CellExtraTypeEnum;import org.apache.fesod.sheet.enums.CellExtraTypeEnum;
import cn.idev.excel.enums.WriteDirectionEnum;import org.apache.fesod.sheet.enums.WriteDirectionEnum;
import cn.idev.excel.enums.poi.HorizontalAlignmentEnum;import org.apache.fesod.sheet.enums.poi.HorizontalAlignmentEnum;
import cn.idev.excel.enums.poi.BorderStyleEnum;import org.apache.fesod.sheet.enums.poi.BorderStyleEnum;
import cn.idev.excel.enums.poi.FillPatternTypeEnum;import org.apache.fesod.sheet.enums.poi.FillPatternTypeEnum;

异常与元信息替换:

修改前修改后
import cn.idev.excel.exception.ExcelAnalysisException;import org.apache.fesod.sheet.exception.ExcelAnalysisException;
import cn.idev.excel.exception.ExcelAnalysisStopException;import org.apache.fesod.sheet.exception.ExcelAnalysisStopException;
import cn.idev.excel.exception.ExcelCommonException;import org.apache.fesod.sheet.exception.ExcelCommonException;
import cn.idev.excel.exception.ExcelGenerateException;import org.apache.fesod.sheet.exception.ExcelGenerateException;
import cn.idev.excel.metadata.data.WriteCellData;import org.apache.fesod.sheet.metadata.data.WriteCellData;
import cn.idev.excel.metadata.data.ReadCellData;import org.apache.fesod.sheet.metadata.data.ReadCellData;
import cn.idev.excel.metadata.CellExtra;import org.apache.fesod.sheet.metadata.CellExtra;
import cn.idev.excel.metadata.Head;import org.apache.fesod.sheet.metadata.Head;
import cn.idev.excel.metadata.property.ExcelContentProperty;import org.apache.fesod.sheet.metadata.property.ExcelContentProperty;

通配符兜底替换

在完成上述所有具体替换后,扫描任何剩余的通配符包导入:

修改前修改后
import cn.idev.excel.import org.apache.fesod.sheet.
import org.apache.fesod.excel.import org.apache.fesod.sheet.

注意:通配符规则不适用于 cn.idev.excel.util.* 的导入。这些工具类迁移到了 fesod-common 模块,而不是 org.apache.fesod.sheet —— 请改为更新为 org.apache.fesod.common.util(参见步骤 4)。

步骤 3:重命名入口类(强烈建议)​

FastExcel 和 FastExcelFactory 在 Fesod 中仍然可以编译,但已被标记为 @Deprecated 弃用, 并且将在未来的版本中被移除。请将所有调用点替换为 FesodSheet。

导入替换:

修改前修改后
import org.apache.fesod.sheet.FastExcel;import org.apache.fesod.sheet.FesodSheet;
import org.apache.fesod.sheet.FastExcelFactory;import org.apache.fesod.sheet.FesodSheet;

调用入口类替换 - FastExcel

修改前修改后
FastExcel.read()FesodSheet.read()
FastExcel.write()FesodSheet.write()
FastExcel.writerSheet()FesodSheet.writerSheet()
FastExcel.readSheet()FesodSheet.readSheet()
FastExcel.writerTable()FesodSheet.writerTable()

调用入口类替换 — FastExcelFactory

FastExcel 1.3 曾提供了 FastExcelFactory 作为第二个入口类,其 API 表面完全相同。它的所有静态方法都可以直接映射到 FesodSheet:

修改前修改后
FastExcelFactory.read()FesodSheet.read()
FastExcelFactory.write()FesodSheet.write()
FastExcelFactory.writerSheet()FesodSheet.writerSheet()
FastExcelFactory.readSheet()FesodSheet.readSheet()
FastExcelFactory.writerTable()FesodSheet.writerTable()

类型引用重命名

如果 FastExcel 或 FastExcelFactory 作为类型名称(而不是调用入口)出现,也请重命名它们:

  • 变量类型:FastExcel x = ... → FesodSheet x = ...
  • 类字面量:FastExcel.class → FesodSheet.class

ExcelWriter 和 ExcelReader 无需重命名,保持相同的类名即可。

CGLIB 类名替换(按需执行)

此阶段仅适用于项目中包含在运行时检查或断言生成的 CGLIB 类名的代码,例如在单元测试或特定的序列化逻辑中。 搜索所有 .java 文件中的字符串 ByFastExcelCGLIB。 如果找到,请替换为 ByFesodCGLIB。 在 Fesod 中,命名策略定义在 org.apache.fesod.sheet.util.BeanMapUtils.FesodSheetNamingPolicy 中,其 getTag() 返回 ByFesodCGLIB。 如果没有文件引用 ByFastExcelCGLIB,请直接跳过此步骤。

步骤 4:类名与模块变更(升级时按需检查)​

除了入口类之外,捐赠过程中部分辅助类被重命名或迁移到了其他模块,且 Fesod 还包含一些 FastExcel 1.3 没有的功能。请在代码库中搜索以下名称,仅更新你实际引用到的部分。

已重命名的辅助类​

修改前(FastExcel 1.3.0)修改后(Fesod)
cn.idev.excel.constant.FastExcelConstantsorg.apache.fesod.sheet.constant.FesodSheetConstants
cn.idev.excel.util.FastExcelTempFileCreationStrategyorg.apache.fesod.sheet.util.FesodTempFileCreationStrategy
cn.idev.excel.util.BeanMapUtils.FastExcelNamingPolicyorg.apache.fesod.sheet.util.BeanMapUtils.FesodSheetNamingPolicy

迁移到 fesod-common 的工具类​

以下工具类已从 cn.idev.excel.util 迁移至 org.apache.fesod.common.util。如果你的代码直接引用了它们(例如在自定义转换器或策略中),请更新导入路径。如果你在步骤 2 中执行过通配符替换,请复查这些导入没有被误改为 org.apache.fesod.sheet.util:

类修改前修改后
StringUtilscn.idev.excel.utilorg.apache.fesod.common.util
IoUtilscn.idev.excel.utilorg.apache.fesod.common.util
MapUtilscn.idev.excel.utilorg.apache.fesod.common.util
ListUtilscn.idev.excel.utilorg.apache.fesod.common.util
BooleanUtilscn.idev.excel.utilorg.apache.fesod.common.util
IntUtilscn.idev.excel.utilorg.apache.fesod.common.util
MemberUtilscn.idev.excel.utilorg.apache.fesod.common.util
PositionUtilscn.idev.excel.utilorg.apache.fesod.common.util

Fesod 新增功能​

以下功能在 FastExcel 1.3.0 中不存在。迁移时值得了解,但除非你想使用它们,否则无需任何操作:

  • @FreezePane(org.apache.fesod.sheet.annotation.write.style.FreezePane):类级注解,写入工作表时冻结行和/或列(colSplit、rowSplit、leftmostColumn、topRow)。
  • URL 图片安全(org.apache.fesod.sheet.converters.url):UrlImageFetchPolicy(由 SchemePolicy 和 CidrBlock 构建)为内置的 URL 图片转换器提供 SSRF 防护。默认只允许 http/https 与公网地址;可通过白名单放行私网、主机和 CIDR,并可限制重定向次数(maxRedirects)与图片大小(maxImageBytes)。
  • 字符串图片转换器(org.apache.fesod.sheet.converters.string):StringBase64ImageConverter(base64 值,可选 data: 前缀)与 StringPathnameImageConverter(本地文件路径)将字符串转图片的转换显式化,兼容的 StringImageConverter 仍然保留。
  • HeadBuilder / DefaultHeadBuilder(org.apache.fesod.sheet.metadata):无 Bean 模式下的流式表头构建,例如 FesodSheet.write(pathname).head(builder -> builder.column("ID", 2).columns("User Info", sub -> sub.column("Name").column("Age")))。
  • HeaderMergeStrategy(org.apache.fesod.sheet.enums.HeaderMergeStrategy):显式控制表头合并——NONE、HORIZONTAL_ONLY、VERTICAL_ONLY、FULL_RECTANGLE、AUTO——通过写构建器上的 headerMergeStrategy(...) 设置,取代布尔开关 automaticMergeHead。

迁移策略​

渐进式迁移(推荐)​

利用已废弃的别名类进行分阶段迁移。

阶段 1:仅更新依赖

  • 将 Maven/Gradle 依赖更新为 Apache Fesod (Incubating)
  • 继续使用 FastExcel 类(现为已废弃的别名)
  • 仅更新包导入
  • 运行全面测试以验证兼容性

阶段 2:类名迁移

  • 逐步将已废弃的类替换为 FesodSheet
  • 使用 IDE 重构工具进行批量重命名
  • 逐个模块或逐个功能进行迁移
  • 在整个过程中保持全面的测试覆盖

阶段 3:清理

  • 删除所有对已废弃类的引用
  • 解决废弃警告
  • 更新文档和代码注释

优势:

  • 通过增量更改降低风险
  • 如果出现问题更容易回滚
  • 对正在进行的开发影响最小
  • 允许在每个阶段进行充分测试的时间

总结​

由于高度的 API 兼容性和向后兼容的已废弃别名,从 cn.idev FastExcel 迁移到 Apache Fesod (Incubating) 是一个直接的过程。主要工作涉及更新依赖声明和包导入,几乎不需要或不需要逻辑更改。

渐进式迁移策略得到临时已废弃别名(FastExcel、FastExcelFactory)的支持,允许团队按自己的节奏迁移,同时保持完整功能。

遵循本指南,组织可以无缝过渡到 Apache Fesod (Incubating),并从 Apache 软件基金会生态系统的长期可持续性和社区支持中受益。