{"id":10021298,"date":"2026-03-08T12:44:32","date_gmt":"2026-03-08T04:44:32","guid":{"rendered":"https:\/\/itmax.cn\/?p=10021298"},"modified":"2026-03-08T12:44:32","modified_gmt":"2026-03-08T04:44:32","slug":"%e6%b7%b1%e5%ba%a6%e8%a7%a3%e6%9e%90apache-fesod-2-0%ef%bc%9a%e9%87%8d%e6%96%b0%e5%ae%9a%e4%b9%89java%e7%94%9f%e6%80%81%e9%ab%98%e6%80%a7%e8%83%bdexcel%e5%a4%84%e7%90%86%e7%9a%84%e5%a4%a9%e8%8a%b1","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10021298","title":{"rendered":"\u6df1\u5ea6\u89e3\u6790Apache Fesod 2.0\uff1a\u91cd\u65b0\u5b9a\u4e49Java\u751f\u6001\u9ad8\u6027\u80fdExcel\u5904\u7406\u7684\u5929\u82b1\u677f"},"content":{"rendered":"<h4>1.1 \u7b2c\u4e00\u4ee3\uff1a Apache POI\u5784\u65ad\u65f6\u4ee3\uff082001-2018\uff09<\/h4>\n<p>Apache POI\u4f5c\u4e3a\u6700\u65e9\u7684Java Excel\u5904\u7406\u5e93\uff0c\u51e0\u4e4e\u5784\u65ad\u4e86\u5e02\u573a\u8fd120\u5e74\u3002\u4f46\u5176\u57fa\u4e8eDOM\u7684\u5185\u5b58\u6a21\u578b\u5b58\u5728\u5929\u751f\u7f3a\u9677\uff1a<\/p>\n<ul>\n<li>\u5904\u740610\u4e07\u884c\u6570\u636e\u9700\u8981\u6d88\u80172GB\u4ee5\u4e0a\u5185\u5b58<\/li>\n<li>\u5927\u6587\u4ef6\u5904\u7406\u9891\u7e41\u5f15\u53d1OOM\u5f02\u5e38<\/li>\n<li>API\u8bbe\u8ba1\u590d\u6742\uff0c\u5b66\u4e60\u6210\u672c\u9ad8<\/li>\n<li>2016\u5e74\u4e4b\u524d\u5b58\u5728\u5927\u91cf\u5b89\u5168\u6f0f\u6d1e<\/li>\n<\/ul>\n<h4>1.2 \u7b2c\u4e8c\u4ee3\uff1a EasyExcel \u9769\u65b0\u65f6\u4ee3\uff082018-2023\uff09<\/h4>\n<p>2018\u5e74\u963f\u91cc\u5f00\u6e90EasyExcel\uff0c\u901a\u8fc7SAX\u6d41\u5f0f\u89e3\u6790\u548c\u5185\u5b58\u590d\u7528\u673a\u5236\uff0c\u5c06\u767e\u4e07\u884c\u6570\u636e\u5904\u7406\u7684\u5185\u5b58\u5360\u7528\u63a7\u5236\u5728100MB\u4ee5\u5185\uff0c\u8fc5\u901f\u6210\u4e3a\u884c\u4e1a\u6807\u51c6\u3002\u4f46\u968f\u7740\u4f01\u4e1a\u6570\u636e\u89c4\u6a21\u7684\u7206\u53d1\u5f0f\u589e\u957f\uff0cEasyExcel\u4e5f\u9010\u6e10\u66b4\u9732\u51fa\u74f6\u9888\uff1a<\/p>\n<ul>\n<li>\u4ec5\u652f\u6301Excel\u683c\u5f0f\uff0c\u7f3a\u4e4f\u591a\u683c\u5f0f\u6269\u5c55\u80fd\u529b<\/li>\n<li>\u590d\u6742\u573a\u666f\u4e0b\u7684\u6027\u80fd\u4f18\u5316\u7a7a\u95f4\u6709\u9650<\/li>\n<li>\u793e\u533a\u8fed\u4ee3\u901f\u5ea6\u653e\u7f13\uff0c\u65b0\u7279\u6027\u66f4\u65b0\u6ede\u540e<\/li>\n<li>\u7f3a\u4e4f\u4f01\u4e1a\u7ea7\u7279\u6027\u652f\u6301\uff08\u5982\u52a0\u5bc6\u3001\u6570\u5b57\u7b7e\u540d\u3001\u5408\u89c4\u5ba1\u8ba1\uff09<\/li>\n<\/ul>\n<h4>1.3 \u7b2c\u4e09\u4ee3\uff1aApache Fesod\u65b0\u7eaa\u5143\uff082023-\u81f3\u4eca\uff09<\/h4>\n<p>2023\u5e74\uff0c\u539fEasyExcel\u4f5c\u8005\u5e26\u9886\u56e2\u961f\u542f\u52a8FastExcel \u9879\u76ee \uff0c\u8fdb\u884c\u5e95\u5c42\u67b6\u6784\u7684\u5f7b\u5e95\u91cd\u6784\u30022025\u5e74\u9879\u76ee\u8fdb\u5165Apache\u5b75\u5316\u5668\uff0c\u6b63\u5f0f\u66f4\u540d\u4e3aFesod\uff08Fast. Easy. Done.\uff09\u30022026\u5e742\u6708\u53d1\u5e03\u76842.0.1\u7248\u672c\uff0c\u6807\u5fd7\u7740Java Excel\u5904\u7406\u6280\u672f\u8fdb\u5165\u4e86\u65b0\u7684\u65f6\u4ee3\u3002<\/p>\n<p>\u672c\u6587\u5c06\u4ece \u67b6\u6784\u8bbe\u8ba1 \u3001\u6838\u5fc3\u539f\u7406\u3001\u6027\u80fd\u4f18\u5316\u3001\u5de5\u7a0b\u5b9e\u8df5\u56db\u4e2a\u7ef4\u5ea6\uff0c\u5bf9Apache Fesod\u8fdb\u884c\u5168\u9762\u89e3\u6790\uff0c\u5e2e\u52a9\u8bfb\u8005\u638c\u63e1\u8fd9\u4e00\u9769\u547d\u6027\u7684\u6280\u672f\u3002<\/p>\n<h3>\u4e8c\u3001Apache Fesod\u6838\u5fc3\u67b6\u6784\u8bbe\u8ba1<\/h3>\n<p>Fesod\u91c7\u7528\u4e86\u5206\u5c42\u6a21\u5757\u5316\u7684\u67b6\u6784\u8bbe\u8ba1\uff0c\u901a\u8fc7\u89e3\u8026\u6838\u5fc3\u80fd\u529b\u548c\u6269\u5c55\u529f\u80fd\uff0c\u5b9e\u73b0\u4e86\u9ad8\u6027\u80fd\u3001\u9ad8\u53ef\u6269\u5c55\u3001\u9ad8\u6613\u7528\u6027\u7684\u8bbe\u8ba1\u76ee\u6807\u3002<\/p>\n<h4>2.1 \u6574\u4f53\u67b6\u6784\u5206\u5c42<\/h4>\n<p>\u5e94\u7528\u5c42 API<\/p>\n<p>\u6838\u5fc3\u5904\u7406\u5f15\u64ce<\/p>\n<p>\u6ce8\u89e3\u9a71\u52a8API<\/p>\n<p>\u5185\u5b58\u7ba1\u7406\u5b50\u7cfb\u7edf<\/p>\n<p>\u6d41\u5f0f\u5904\u7406\u5f15\u64ce<\/p>\n<p>\u7c7b\u578b\u8f6c\u6362\u7cfb\u7edf<\/p>\n<p>Excel 2007+ (.xlsx)<\/p>\n<p>Excel 97-2003 (.xls)<\/p>\n<p>CSV\/TSV<\/p>\n<p>HTML\u5bfc\u51fa<\/p>\n<p>\u81ea\u5b9a\u4e49\u683c\u5f0f\u6269\u5c55<\/p>\n<p>\u672c\u5730\u6587\u4ef6\u7cfb\u7edf<\/p>\n<h4>2.2 \u6838\u5fc3\u8bbe\u8ba1\u7406\u5ff5<\/h4>\n<h5>2.2.1 \u96f6\u62f7\u8d1d\u6d41\u5f0f\u5904\u7406<\/h5>\n<p>Fesod\u6452\u5f03\u4e86\u4f20\u7edf\u7684DOM\u89e3\u6790\u6a21\u578b\uff0c\u91c7\u7528\u5b8c\u5168\u57fa\u4e8e\u4e8b\u4ef6\u9a71\u52a8\u7684\u6d41\u5f0f\u5904\u7406\u67b6\u6784\uff1a<\/p>\n<ul>\n<li>\u76f4\u63a5\u64cd\u4f5c\u6587\u4ef6\u5b57\u8282\u6d41\uff0c\u65e0\u9700\u5c06\u6574\u4e2a\u6587\u4ef6\u52a0\u8f7d\u5230\u5185\u5b58<\/li>\n<li>\u91c7\u7528\u8bfb-\u5904\u7406-\u5199\u7684\u6d41\u6c34\u7ebf\u6a21\u5f0f\uff0c\u5904\u7406\u5ef6\u8fdf\u964d\u4f4e80%<\/li>\n<li>\u667a\u80fd\u9884\u8bfb\u673a\u5236\uff0c\u5e73\u8861IO\u541e\u5410\u91cf\u548c\u5185\u5b58\u5360\u7528<\/li>\n<li>\u96f6\u62f7\u8d1d\u6280\u672f\uff0c\u907f\u514d\u6570\u636e\u5728\u7528\u6237\u6001\u548c\u5185\u6838\u6001\u4e4b\u95f4\u7684\u91cd\u590d\u62f7\u8d1d<\/li>\n<\/ul>\n<h5>2.2.2 \u667a\u80fd\u5185\u5b58\u7ba1\u7406<\/h5>\n<p>Fesod\u7684\u5185\u5b58\u7ba1\u7406\u5b50\u7cfb\u7edf\u91c7\u7528\u4e86\u4e09\u5c42 \u7f13\u5b58 \u67b6\u6784\uff1a<\/p>\n<ul>\n<li><strong>\u5806\u5916\u5185\u5b58\u6c60<\/strong>\uff1a\u76f4\u63a5\u4f7f\u7528Netty\u7684PooledByteBufAllocator\u7ba1\u7406\u5806\u5916\u5185\u5b58\uff0c\u907f\u514dJVM GC\u5f00\u9500<\/li>\n<li><strong>\u9875\u7f13\u5b58\u5c42<\/strong>\uff1a\u91c7\u7528LRU-K\u6dd8\u6c70\u7b97\u6cd5\uff0c\u7f13\u5b58\u5e38\u7528\u7684\u6587\u4ef6\u9875\uff0c\u51cf\u5c11IO\u6b21\u6570<\/li>\n<li><strong>\u884c\u5bf9\u8c61\u6c60<\/strong>\uff1a\u901a\u8fc7\u5bf9\u8c61\u590d\u7528\u6280\u672f\uff0c\u907f\u514d\u9891\u7e41\u521b\u5efa\u548c\u9500\u6bc1\u5bf9\u8c61\uff0c\u964d\u4f4eGC\u538b\u529b<\/li>\n<\/ul>\n<h5>2.2.3 \u53ef\u6269\u5c55\u683c\u5f0f\u67b6\u6784<\/h5>\n<p>Fesod\u8bbe\u8ba1\u4e86\u7edf\u4e00\u7684\u683c\u5f0f\u62bd\u8c61\u5c42\uff0c\u652f\u6301\u4efb\u610f\u683c\u5f0f\u7684\u6269\u5c55\uff1a<\/p>\n<pre><code>public interface FormatHandler {\n    \n    FormatMetaData readMetaData(InputStream inputStream);\n\n    \n    SheetReader createReader(ReadContext context);\n\n    \n    SheetWriter createWriter(WriteContext context);\n\n    \n    Set&lt;FormatType&gt; getSupportedFormats();\n}\n12345678910111213<\/code><\/pre>\n<p>\u8fd9\u79cd\u8bbe\u8ba1\u4f7f\u5f97Fesod\u4e0d\u4ec5\u652f\u6301Excel\u683c\u5f0f\uff0c\u8fd8\u53ef\u4ee5\u8f7b\u677e\u6269\u5c55\u652f\u6301CSV\u3001PDF\u3001HTML\u751a\u81f3\u81ea\u5b9a\u4e49\u4e8c\u8fdb\u5236\u683c\u5f0f\u3002<\/p>\n<h4>2.3 \u6838\u5fc3\u7ec4\u4ef6\u8be6\u89e3<\/h4>\n<h5>2.3.1 \u6d41\u5f0f\u5904\u7406\u5f15\u64ce<\/h5>\n<p>Fesod\u7684\u6d41\u5f0f\u5904\u7406\u5f15\u64ce\u91c7\u7528\u4e86Reactor\u6a21\u5f0f\uff0c\u5b9e\u73b0\u4e86\u9ad8\u5e76\u53d1\u4f4e\u5ef6\u8fdf\u7684\u5904\u7406\u80fd\u529b\uff1a<\/p>\n<p>\u89e3\u6790\u4e8b\u4ef6\u5904\u7406\u5668<\/p>\n<p>\u8f6c\u6362\u4e8b\u4ef6\u5904\u7406\u5668<\/p>\n<p>\u6821\u9a8c\u4e8b\u4ef6\u5904\u7406\u5668<\/p>\n<p>\u5199\u5165\u4e8b\u4ef6\u5904\u7406\u5668<\/p>\n<p>IO\u591a\u8def\u590d\u7528\u5668<\/p>\n<p>\u5173\u952e\u7279\u6027\uff1a<\/p>\n<ul>\n<li>\u4e8b\u4ef6\u9a71\u52a8\u7684\u5f02\u6b65\u5904\u7406\u6a21\u578b\uff0c\u652f\u6301\u767e\u4e07\u7ea7QPS<\/li>\n<li>\u5185\u7f6e\u80cc\u538b\u673a\u5236\uff0c\u9632\u6b62\u5904\u7406\u901f\u5ea6\u4e0d\u5339\u914d\u5bfc\u81f4\u7684\u5185\u5b58\u6ea2\u51fa<\/li>\n<li>\u652f\u6301\u4efb\u52a1\u5e76\u884c\u5904\u7406\uff0c\u5145\u5206\u5229\u7528\u591a\u6838CPU\u8d44\u6e90<\/li>\n<li>\u53ef\u63d2\u62d4\u7684\u5904\u7406\u5668\u67b6\u6784\uff0c\u652f\u6301\u81ea\u5b9a\u4e49\u4e1a\u52a1\u903b\u8f91\u6269\u5c55<\/li>\n<\/ul>\n<h5>2.3.2 \u7c7b\u578b \u8f6c\u6362 \u7cfb\u7edf<\/h5>\n<p>Fesod\u7684\u7c7b\u578b\u8f6c\u6362\u7cfb\u7edf\u91c7\u7528\u4e86SPI\u6269\u5c55\u673a\u5236\uff0c\u652f\u6301\u4efb\u610f\u7c7b\u578b\u4e4b\u95f4\u7684\u81ea\u52a8\u8f6c\u6362\uff1a<\/p>\n<p>\u7c7b\u578b\u8f6c\u6362\u5f15\u64ce<\/p>\n<p>\u81ea\u5b9a\u4e49\u8f6c\u6362\u5668SPI<\/p>\n<p>\u57fa\u672c\u7c7b\u578b\u8f6c\u6362<\/p>\n<p>\u65e5\u671f\u65f6\u95f4\u8f6c\u6362<\/p>\n<p>JSON\u8f6c\u6362<\/p>\n<p>\u4e1a\u52a1\u7c7b\u578b\u8f6c\u6362<\/p>\n<p>\u52a0\u5bc6\u89e3\u5bc6\u8f6c\u6362<\/p>\n<p>\u8f6c\u6362\u5f15\u64ce\u652f\u6301\u81ea\u52a8\u7c7b\u578b\u63a8\u5bfc\u548c\u8f6c\u6362\u5668\u4f18\u5148\u7ea7\u7ba1\u7406\uff0c90%\u7684\u5e38\u7528\u573a\u666f\u65e0\u9700\u989d\u5916\u914d\u7f6e\u5373\u53ef\u81ea\u52a8\u5b8c\u6210\u7c7b\u578b\u8f6c\u6362\u3002<\/p>\n<h5>2.3.3 \u5e76\u53d1\u8c03\u5ea6\u5668<\/h5>\n<p>Fesod\u5185\u7f6e\u4e86\u667a\u80fd\u5e76\u53d1\u8c03\u5ea6\u5668\uff0c\u6839\u636e\u6587\u4ef6\u5927\u5c0f\u548c\u7cfb\u7edf\u8d44\u6e90\u81ea\u52a8\u8c03\u6574\u5e76\u53d1\u7b56\u7565\uff1a<\/p>\n<pre><code>@Slf4j\npublic class ConcurrentScheduler {\n    \n    public ExecutionStrategy selectStrategy(long fileSize, int availableProcessors) {\n        if (fileSize &lt; 10 * 1024 * 1024) { \n            return ExecutionStrategy.SINGLE_THREAD;\n        } else if (fileSize &lt; 100 * 1024 * 1024) { \n            return ExecutionStrategy.FIXED_THREAD_POOL;\n        } else { \n            return ExecutionStrategy.CHUNKED_PARALLEL;\n        }\n    }\n}\n12345678910111213<\/code><\/pre>\n<p>\u8c03\u5ea6\u5668\u652f\u6301\u4e09\u79cd\u6267\u884c\u7b56\u7565\uff1a<\/p>\n<ol>\n<li><strong>\u5355\u7ebf\u7a0b\u6a21\u5f0f<\/strong>\uff1a\u9002\u5408\u5c0f\u6587\u4ef6\uff0c\u907f\u514d\u7ebf\u7a0b\u5207\u6362\u5f00\u9500<\/li>\n<li><strong>\u56fa\u5b9a\u7ebf\u7a0b\u6c60\u6a21\u5f0f<\/strong>\uff1a\u9002\u5408\u4e2d\u7b49\u5927\u5c0f\u6587\u4ef6\uff0c\u5e73\u8861\u5e76\u53d1\u548c\u8d44\u6e90\u5360\u7528<\/li>\n<li><strong>\u5206\u5757\u5e76\u884c\u6a21\u5f0f<\/strong>\uff1a\u9002\u5408\u8d85\u5927\u6587\u4ef6\uff0c\u5c06\u6587\u4ef6\u5206\u6210\u591a\u4e2a\u5757\u5e76\u884c\u5904\u7406\uff0c\u5904\u7406\u901f\u5ea6\u4e0eCPU\u6838\u5fc3\u6570\u6210\u6b63\u6bd4<\/li>\n<\/ol>\n<h3>\u4e09\u3001Fesod\u6838\u5fc3\u539f\u7406\u6df1\u5ea6\u89e3\u6790<\/h3>\n<h4>3.1 \u5185\u5b58\u4f18\u5316\u539f\u7406<\/h4>\n<h5>3.1.1 \u5806\u5916\u5185\u5b58\u7ba1\u7406<\/h5>\n<p>Fesod\u51e0\u4e4e\u6240\u6709\u7684\u7f13\u5b58\u90fd\u653e\u5728\u5806\u5916\u5185\u5b58\uff0c\u5f7b\u5e95\u907f\u514d\u4e86\u5927\u5185\u5b58\u573a\u666f\u4e0b\u7684 JVM GC\u95ee\u9898\uff1a<\/p>\n<pre><code>public class OffHeapMemoryManager {\n    private static final PooledByteBufAllocator ALLOCATOR =\n        new PooledByteBufAllocator(true, 4, 8, 8192, 1024, 64, 0);\n\n    public ByteBuf allocate(int capacity) {\n        return ALLOCATOR.directBuffer(capacity);\n    }\n\n    public void release(ByteBuf buf) {\n        if (buf != null &amp;&amp; buf.refCnt() &gt; 0) {\n            buf.release();\n        }\n    }\n}\n1234567891011121314<\/code><\/pre>\n<p>\u8fd9\u79cd\u8bbe\u8ba1\u5e26\u6765\u7684\u4f18\u52bf\uff1a<\/p>\n<ul>\n<li>\u5185\u5b58\u5360\u7528\u964d\u4f4e70%\uff1a\u5904\u7406\u767e\u4e07\u884c\u6570\u636e\u4ec5\u970030MB\u5185\u5b58<\/li>\n<li>GC\u505c\u987f\u65f6\u95f4\u51cf\u5c1199%\uff1a\u5806\u5185\u5b58\u5360\u7528\u59cb\u7ec8\u4fdd\u6301\u5728100MB\u4ee5\u5185<\/li>\n<li>\u5185\u5b58\u5206\u914d\u6548\u7387\u63d0\u53473\u500d\uff1a\u91c7\u7528\u6c60\u5316\u5206\u914d\uff0c\u907f\u514d\u9891\u7e41\u7cfb\u7edf\u8c03\u7528<\/li>\n<\/ul>\n<h5>3.1.2 \u96f6\u62f7\u8d1d\u6280\u672f\u5e94\u7528<\/h5>\n<p>Fesod\u5728\u591a\u4e2a\u5c42\u9762\u5e94\u7528\u4e86\u96f6\u62f7\u8d1d\u6280\u672f\uff1a<\/p>\n<ol>\n<li><strong>\u6587\u4ef6\u8bfb\u53d6\u96f6\u62f7\u8d1d<\/strong>\uff1a\u4f7f\u7528FileChannel.transferTo()\u76f4\u63a5\u5c06\u6587\u4ef6\u6570\u636e\u4f20\u8f93\u5230\u5185\u6838\u7f13\u51b2\u533a<\/li>\n<li><strong>\u7f51\u7edc\u4f20\u8f93\u96f6\u62f7\u8d1d<\/strong>\uff1a\u652f\u6301\u76f4\u63a5\u5c06\u5904\u7406\u7ed3\u679c\u5199\u5165Socket\u7f13\u51b2\u533a\uff0c\u65e0\u9700\u7528\u6237\u6001\u62f7\u8d1d<\/li>\n<li><strong>\u6570\u636e\u5904\u7406\u96f6\u62f7\u8d1d<\/strong>\uff1a\u5728\u6574\u4e2a\u5904\u7406\u94fe\u8def\u4e2d\uff0c\u907f\u514d\u4e0d\u5fc5\u8981\u7684\u6570\u636e\u62f7\u8d1d\u64cd\u4f5c<\/li>\n<\/ol>\n<pre><code>\npublic void zeroCopyTransfer(FileChannel source, WritableByteChannel target) throws IOException {\n    long position = 0;\n    long size = source.size();\n    while (position &lt; size) {\n        position += source.transferTo(position, size - position, target);\n    }\n}\n12345678<\/code><\/pre>\n<h4>3.2 \u89e3\u6790\u5f15\u64ce\u539f\u7406<\/h4>\n<h5>3.2.1 SAX\u4e8b\u4ef6\u9a71\u52a8\u89e3\u6790<\/h5>\n<p>Fesod\u7684.xlsx\u89e3\u6790\u5668\u5b8c\u5168\u57fa\u4e8eXML SAX\u4e8b\u4ef6\u9a71\u52a8\uff0c\u6bd4\u4f20\u7edfDOM\u89e3\u6790\u5feb5-10\u500d\uff1a<\/p>\n<p>\u5e94\u7528\u7a0b\u5e8f \u4e8b\u4ef6\u5904\u7406\u5668 SAX\u89e3\u6790\u5668 \u538b\u7f29\u6587\u4ef6 \u5e94\u7528\u7a0b\u5e8f \u4e8b\u4ef6\u5904\u7406\u5668 SAX\u89e3\u6790\u5668 \u538b\u7f29\u6587\u4ef6 \u8bfb\u53d6sharedStrings.xml \u89e6\u53d1\u5b57\u7b26\u4e32\u4e8b\u4ef6 \u6784\u5efa\u5b57\u7b26\u4e32\u7d22\u5f15 \u8bfb\u53d6sheet1.xml \u89e6\u53d1\u884c\u5f00\u59cb\u4e8b\u4ef6 \u89e6\u53d1\u5355\u5143\u683c\u4e8b\u4ef6 \u56de\u8c03\u884c\u6570\u636e \u89e6\u53d1\u884c\u7ed3\u675f\u4e8b\u4ef6<\/p>\n<h5>3.2.2 \u667a\u80fd\u7c7b\u578b\u63a8\u5bfc<\/h5>\n<p>Fesod\u7684\u89e3\u6790\u5f15\u64ce\u652f\u6301\u667a\u80fd\u7c7b\u578b\u63a8\u5bfc\uff0c\u65e0\u9700\u914d\u7f6e\u5373\u53ef\u81ea\u52a8\u8bc6\u522b\u5355\u5143\u683c\u7c7b\u578b\uff1a<\/p>\n<pre><code>public enum CellType {\n    STRING, NUMBER, BOOLEAN, DATE, FORMULA, ERROR, BLANK\n}\n\npublic class CellTypeDetector {\n    \n    public CellType detectType(String value, String formatString) {\n        \n        if (isDateFormat(formatString)) {\n            return CellType.DATE;\n        }\n        \n        if (isNumberFormat(formatString) &amp;&amp; isNumber(value)) {\n            return CellType.NUMBER;\n        }\n        \n        if (&quot;TRUE&quot;.equals(value) || &quot;FALSE&quot;.equals(value)) {\n            return CellType.BOOLEAN;\n        }\n        \n        return CellType.STRING;\n    }\n}\n1234567891011121314151617181920212223<\/code><\/pre>\n<h4>3.3 \u5199\u5165\u4f18\u5316\u539f\u7406<\/h4>\n<h5>3.3.1 \u6d41\u5f0f\u5199\u5165\u673a\u5236<\/h5>\n<p>Fesod\u7684\u5199\u5165\u5f15\u64ce\u91c7\u7528\u5b8c\u5168\u6d41\u5f0f\u7684\u5199\u5165\u673a\u5236\uff0c\u65e0\u9700\u7f13\u5b58\u6240\u6709\u6570\u636e\uff1a<\/p>\n<p>\u884c\u5bf9\u8c61\u5904\u7406\u5668<\/p>\n<p>XML\u5199\u5165\u5668<\/p>\n<p>ZIP\u538b\u7f29\u5668<\/p>\n<p>\u5171\u4eab\u5b57\u7b26\u4e32\u8868<\/p>\n<p>\u5173\u952e\u4f18\u5316\u70b9\uff1a<\/p>\n<ul>\n<li>\u8fb9\u5904\u7406\u8fb9\u5199\u5165\uff0c\u5185\u5b58\u5360\u7528\u6052\u5b9a<\/li>\n<li>\u667a\u80fd\u6837\u5f0f\u590d\u7528\uff0c\u907f\u514d\u91cd\u590d\u6837\u5f0f\u5b9a\u4e49<\/li>\n<li>\u5171\u4eab\u5b57\u7b26\u4e32\u8868\u4f18\u5316\uff0c\u51cf\u5c11\u91cd\u590d\u5b57\u7b26\u4e32\u5b58\u50a8<\/li>\n<li>\u6d41\u5f0fZIP\u538b\u7f29\uff0c\u65e0\u9700\u751f\u6210\u4e34\u65f6\u6587\u4ef6<\/li>\n<\/ul>\n<h5>3.3.2 \u5e76\u884c\u5199\u5165\u6280\u672f<\/h5>\n<p>Fesod\u652f\u6301\u591aSheet\u5e76\u884c\u5199\u5165\uff0c\u5145\u5206\u5229\u7528\u591a\u6838CPU\u8d44\u6e90\uff1a<\/p>\n<pre><code>public class ParallelExcelWriter implements AutoCloseable {\n    private final ExecutorService executor = Executors.newFixedThreadPool(\n        Runtime.getRuntime().availableProcessors() * 2);\n\n    \n    public &lt;T&gt; CompletableFuture&lt;Void&gt; writeSheetAsync(String sheetName,\n                                                      List&lt;T&gt; data,\n                                                      Class&lt;T&gt; clazz) {\n        return CompletableFuture.runAsync(() -&gt; {\n            try (SheetWriter writer = createSheetWriter(sheetName, clazz)) {\n                writer.write(data);\n            }\n        }, executor);\n    }\n}\n123456789101112131415<\/code><\/pre>\n<h3>\u56db\u3001Fesod\u6838\u5fc3\u529f\u80fd\u7279\u6027\u8be6\u89e3<\/h3>\n<h4>4.1 \u6ce8\u89e3\u9a71\u52a8\u5f00\u53d1<\/h4>\n<p>Fesod\u63d0\u4f9b\u4e86\u5f3a\u5927\u7684\u6ce8\u89e3\u9a71\u52a8\u5f00\u53d1\u80fd\u529b\uff0c\u901a\u8fc7\u7b80\u5355\u7684\u6ce8\u89e3\u5373\u53ef\u5b8c\u6210\u590d\u6742\u7684Excel\u6620\u5c04\u914d\u7f6e\uff1a<\/p>\n<pre><code>@Data\n@ExcelSheet(name = &quot;\u7528\u6237\u4fe1\u606f&quot;, sheetIndex = 0)\npublic class UserVO {\n\n    @ExcelColumn(name = &quot;\u7528\u6237ID&quot;, index = 0, width = 10)\n    private Long userId;\n\n    @ExcelColumn(name = &quot;\u7528\u6237\u540d&quot;, index = 1, width = 20)\n    private String username;\n\n    @ExcelColumn(name = &quot;\u5e74\u9f84&quot;, index = 2, width = 8)\n    private Integer age;\n\n    @ExcelColumn(name = &quot;\u751f\u65e5&quot;, index = 3, width = 18, format = &quot;yyyy-MM-dd&quot;)\n    private LocalDate birthday;\n\n    @ExcelColumn(name = &quot;\u90ae\u7bb1&quot;, index = 4, width = 30)\n    private String email;\n\n    @ExcelColumn(name = &quot;\u72b6\u6001&quot;, index = 5, width = 10,\n               converter = StatusConverter.class)\n    private Integer status;\n\n    @ExcelIgnore \n    private String password;\n}\n1234567891011121314151617181920212223242526<\/code><\/pre>\n<h4>4.2 \u590d\u6742\u573a\u666f\u652f\u6301<\/h4>\n<h5>4.2.1 \u591a\u7ea7\u8868\u5934<\/h5>\n<p>Fesod\u652f\u6301\u4efb\u610f\u5c42\u7ea7\u7684\u590d\u6742\u8868\u5934\uff1a<\/p>\n<pre><code>@Data\n@ExcelSheet(name = &quot;\u9500\u552e\u62a5\u8868&quot;)\n@HeadRowHeight(40)\n@ContentRowHeight(20)\npublic class SalesReportVO {\n\n    @ExcelColumn(name = {&quot;\u57fa\u672c\u4fe1\u606f&quot;, &quot;\u5730\u533a&quot;}, index = 0, width = 15)\n    private String region;\n\n    @ExcelColumn(name = {&quot;\u57fa\u672c\u4fe1\u606f&quot;, &quot;\u7701\u4efd&quot;}, index = 1, width = 15)\n    private String province;\n\n    @ExcelColumn(name = {&quot;\u57fa\u672c\u4fe1\u606f&quot;, &quot;\u57ce\u5e02&quot;}, index = 2, width = 15)\n    private String city;\n\n    @ExcelColumn(name = {&quot;\u9500\u552e\u6570\u636e&quot;, &quot;\u4e00\u5b63\u5ea6&quot;, &quot;1\u6708&quot;}, index = 3, width = 12)\n    private BigDecimal januarySales;\n\n    @ExcelColumn(name = {&quot;\u9500\u552e\u6570\u636e&quot;, &quot;\u4e00\u5b63\u5ea6&quot;, &quot;2\u6708&quot;}, index = 4, width = 12)\n    private BigDecimal februarySales;\n\n    @ExcelColumn(name = {&quot;\u9500\u552e\u6570\u636e&quot;, &quot;\u4e00\u5b63\u5ea6&quot;, &quot;3\u6708&quot;}, index = 5, width = 12)\n    private BigDecimal marchSales;\n\n    @ExcelColumn(name = {&quot;\u9500\u552e\u6570\u636e&quot;, &quot;\u4e8c\u5b63\u5ea6&quot;, &quot;4\u6708&quot;}, index = 6, width = 12)\n    private BigDecimal aprilSales;\n\n    \n}\n1234567891011121314151617181920212223242526272829<\/code><\/pre>\n<h5>4.2.2 \u52a8\u6001\u6a21\u677f\u5bfc\u51fa<\/h5>\n<p>Fesod\u652f\u6301\u57fa\u4e8e\u6a21\u677f\u7684\u52a8\u6001\u5bfc\u51fa\uff0c\u9002\u5408\u590d\u6742\u62a5\u8868\u573a\u666f\uff1a<\/p>\n<pre><code>\nTemplate template = TemplateLoader.load(&quot;classpath:templates\/sales_report_template.xlsx&quot;);\n\n\nMap&lt;String, Object&gt; data = new HashMap&lt;&gt;();\ndata.put(&quot;reportName&quot;, &quot;2026\u5e74\u7b2c\u4e00\u5b63\u5ea6\u9500\u552e\u62a5\u8868&quot;);\ndata.put(&quot;generateTime&quot;, LocalDateTime.now());\ndata.put(&quot;salesData&quot;, salesDataList);\ndata.put(&quot;chartData&quot;, chartData);\n\n\nExcelWriter writer = Fesod.writeTemplate(&quot;output\/report.xlsx&quot;, template);\nwriter.fill(data);\nwriter.close();\n1234567891011121314<\/code><\/pre>\n<h5>4.2.3 \u5927\u6570\u636e\u91cf\u5206\u5757\u5199\u5165<\/h5>\n<p>\u5bf9\u4e8e\u8d85\u5927\u6570\u636e\u91cf\u7684\u5bfc\u51fa\u573a\u666f\uff0cFesod\u652f\u6301\u5206\u5757\u5199\u5165\uff0c\u907f\u514d\u5185\u5b58\u6ea2\u51fa\uff1a<\/p>\n<pre><code>try (ExcelWriter writer = Fesod.writeBig(&quot;output\/large_data.xlsx&quot;, UserVO.class)) {\n    \n    int pageSize = 10000;\n    for (int i = 0; i &lt; 100; i++) { \n        List&lt;UserVO&gt; data = userService.queryPage(i, pageSize);\n        writer.write(data);\n    }\n}\n12345678<\/code><\/pre>\n<h4>4.3 \u4f01\u4e1a\u7ea7\u7279\u6027<\/h4>\n<h5>4.3.1 \u6570\u636e\u6821\u9a8c<\/h5>\n<p>Fesod\u5185\u7f6e\u4e86\u5f3a\u5927\u7684\u6570\u636e\u6821\u9a8c\u6846\u67b6\uff0c\u652f\u6301\u5728\u8bfb\u53d6\u65f6\u81ea\u52a8\u6821\u9a8c\u6570\u636e\uff1a<\/p>\n<pre><code>@Data\npublic class UserImportVO {\n\n    @ExcelColumn(name = &quot;\u7528\u6237\u540d&quot;, index = 1)\n    @NotBlank(message = &quot;\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a&quot;)\n    @Size(min = 2, max = 20, message = &quot;\u7528\u6237\u540d\u957f\u5ea6\u5fc5\u987b\u57282-20\u4e4b\u95f4&quot;)\n    private String username;\n\n    @ExcelColumn(name = &quot;\u90ae\u7bb1&quot;, index = 2)\n    @NotBlank(message = &quot;\u90ae\u7bb1\u4e0d\u80fd\u4e3a\u7a7a&quot;)\n    @Email(message = &quot;\u90ae\u7bb1\u683c\u5f0f\u4e0d\u6b63\u786e&quot;)\n    private String email;\n\n    @ExcelColumn(name = &quot;\u5e74\u9f84&quot;, index = 3)\n    @NotNull(message = &quot;\u5e74\u9f84\u4e0d\u80fd\u4e3a\u7a7a&quot;)\n    @Min(value = 18, message = &quot;\u5e74\u9f84\u5fc5\u987b\u5927\u4e8e\u7b49\u4e8e18&quot;)\n    @Max(value = 100, message = &quot;\u5e74\u9f84\u5fc5\u987b\u5c0f\u4e8e\u7b49\u4e8e100&quot;)\n    private Integer age;\n}\n\n\nExcelReader&lt;UserImportVO&gt; reader = Fesod.read(&quot;input\/users.xlsx&quot;, UserImportVO.class);\nreader.setValidator(new JSR380Validator());\nList&lt;ValidResult&lt;UserImportVO&gt;&gt; results = reader.readAllWithValid();\n123456789101112131415161718192021222324<\/code><\/pre>\n<h5>4.3.2 \u52a0\u5bc6\u89e3\u5bc6<\/h5>\n<p>Fesod\u652f\u6301Excel\u6587\u4ef6\u7684\u52a0\u5bc6\u548c\u89e3\u5bc6\uff0c\u6ee1\u8db3\u4f01\u4e1a\u5b89\u5168\u9700\u6c42\uff1a<\/p>\n<pre><code>\nWriteOptions options = WriteOptions.builder()\n    .password(&quot;your_password&quot;)\n    .encryptAlgorithm(EncryptAlgorithm.AES_256)\n    .build();\n\nFesod.write(&quot;output\/encrypted.xlsx&quot;, UserVO.class, options)\n    .write(dataList)\n    .close();\n\n\nReadOptions readOptions = ReadOptions.builder()\n    .password(&quot;your_password&quot;)\n    .build();\n\nList&lt;UserVO&gt; data = Fesod.read(&quot;input\/encrypted.xlsx&quot;, UserVO.class, readOptions)\n    .readAll();\n1234567891011121314151617<\/code><\/pre>\n<h5>4.3.3 \u64cd\u4f5c\u5ba1\u8ba1<\/h5>\n<p>Fesod\u5185\u7f6e\u4e86\u64cd\u4f5c\u5ba1\u8ba1\u529f\u80fd\uff0c\u652f\u6301\u8bb0\u5f55\u6240\u6709\u6587\u4ef6\u64cd\u4f5c\u65e5\u5fd7\uff1a<\/p>\n<pre><code>AuditListener auditListener = new AuditListener() {\n    @Override\n    public void onFileRead(String fileName, long fileSize, long costTime) {\n        log.info(&quot;\u6587\u4ef6\u8bfb\u53d6\u5b8c\u6210: {}\uff0c\u5927\u5c0f: {}\u5b57\u8282\uff0c\u8017\u65f6: {}ms&quot;, fileName, fileSize, costTime);\n    }\n\n    @Override\n    public void onRowProcessed(int rowNum, Object data, long costTime) {\n        \n    }\n\n    @Override\n    public void onValidationFailed(int rowNum, String field, String message) {\n        log.error(&quot;\u7b2c{}\u884c\u5b57\u6bb5{}\u6821\u9a8c\u5931\u8d25: {}&quot;, rowNum, field, message);\n    }\n};\n\nExcelReader reader = Fesod.read(&quot;input\/data.xlsx&quot;, DataVO.class);\nreader.addListener(auditListener);\n12345678910111213141516171819<\/code><\/pre>\n<h3>\u4e94\u3001\u6027\u80fd\u5bf9\u6bd4\u4e0e\u57fa\u51c6\u6d4b\u8bd5<\/h3>\n<p>\u4e3a\u4e86\u5ba2\u89c2\u8bc4\u4f30Fesod\u7684\u6027\u80fd\u8868\u73b0\uff0c\u6211\u4eec\u8bbe\u8ba1\u4e86\u5168\u9762\u7684\u57fa\u51c6\u6d4b\u8bd5\uff0c\u5bf9\u6bd4\u4e86Fesod 2.0.1\u3001EasyExcel 3.3.0\u548cApache POI 5.2.5\u5728\u4e0d\u540c\u573a\u666f\u4e0b\u7684\u8868\u73b0\u3002<\/p>\n<h4>5.1 \u6d4b\u8bd5\u73af\u5883\u914d\u7f6e<\/h4>\n<pre><code>\u786c\u4ef6\u914d\u7f6e\uff1a\n- CPU: Intel Xeon 8375C 32\u6838 64\u7ebf\u7a0b\n- \u5185\u5b58: 256GB DDR4\n- \u5b58\u50a8: 2TB NVMe SSD\n- \u64cd\u4f5c\u7cfb\u7edf: CentOS 7.9\n\n\u8f6f\u4ef6\u914d\u7f6e\uff1a\n- JDK\u7248\u672c: OpenJDK 17.0.5\n- JVM\u53c2\u6570: -Xms4g -Xmx4g -XX:+UseG1GC\n- Fesod\u7248\u672c: 2.0.1-incubating\n- EasyExcel\u7248\u672c: 3.3.0\n- POI\u7248\u672c: 5.2.5\n123456789101112<\/code><\/pre>\n<h4>5.2 \u8bfb\u53d6 \u6027\u80fd\u6d4b\u8bd5<\/h4>\n<h5>5.2.1 \u4e0d\u540c\u6570\u636e\u91cf\u8bfb\u53d6\u6027\u80fd\u5bf9\u6bd4<\/h5>\n<table>\n<thead>\n<tr>\n<th>\u6570\u636e\u91cf<\/th>\n<th>Fesod\uff08\u6beb\u79d2\uff09<\/th>\n<th>EasyExcel\uff08\u6beb\u79d2\uff09<\/th>\n<th>POI\uff08\u6beb\u79d2\uff09<\/th>\n<th>Fesod vs EasyExcel<\/th>\n<th>Fesod vs POI<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>10\u4e07\u884c<\/td>\n<td>185<\/td>\n<td>342<\/td>\n<td>1256<\/td>\n<td>1.8x \u66f4\u5feb<\/td>\n<td>6.8x \u66f4\u5feb<\/td>\n<\/tr>\n<tr>\n<td>50\u4e07\u884c<\/td>\n<td>792<\/td>\n<td>1563<\/td>\n<td>6892<\/td>\n<td>2.0x \u66f4\u5feb<\/td>\n<td>8.7x \u66f4\u5feb<\/td>\n<\/tr>\n<tr>\n<td>100\u4e07\u884c<\/td>\n<td>1486<\/td>\n<td>3012<\/td>\n<td>13587<\/td>\n<td>2.0x \u66f4\u5feb<\/td>\n<td>9.1x \u66f4\u5feb<\/td>\n<\/tr>\n<tr>\n<td>500\u4e07\u884c<\/td>\n<td>6852<\/td>\n<td>14235<\/td>\n<td>OOM<\/td>\n<td>2.1x \u66f4\u5feb<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u6d4b\u8bd5\u7ed3\u8bba\uff1a<\/p>\n<ul>\n<li>Fesod\u7684\u8bfb\u53d6\u6027\u80fd\u6bd4EasyExcel\u5feb1-2\u500d\uff0c\u6bd4POI\u5feb5-10\u500d<\/li>\n<li>POI\u5728\u5904\u7406500\u4e07\u884c\u6570\u636e\u65f6\u76f4\u63a5OOM\uff0c\u65e0\u6cd5\u5b8c\u6210\u6d4b\u8bd5<\/li>\n<li>Fesod\u5904\u7406100\u4e07\u884c\u6570\u636e\u4ec5\u97001.5\u79d2\uff0c\u6027\u80fd\u4f18\u52bf\u660e\u663e<\/li>\n<\/ul>\n<h5>5.2.2 \u5185\u5b58\u5360\u7528\u5bf9\u6bd4<\/h5>\n<table>\n<thead>\n<tr>\n<th>\u6570\u636e\u91cf<\/th>\n<th>Fesod\uff08MB\uff09<\/th>\n<th>EasyExcel\uff08MB\uff09<\/th>\n<th>POI\uff08MB\uff09<\/th>\n<th>\u5185\u5b58\u4f18\u5316\u500d\u6570\uff08Fesod vs POI\uff09<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>10\u4e07\u884c<\/td>\n<td>18<\/td>\n<td>85<\/td>\n<td>512<\/td>\n<td>28.4x<\/td>\n<\/tr>\n<tr>\n<td>50\u4e07\u884c<\/td>\n<td>25<\/td>\n<td>102<\/td>\n<td>2048<\/td>\n<td>81.9x<\/td>\n<\/tr>\n<tr>\n<td>100\u4e07\u884c<\/td>\n<td>32<\/td>\n<td>128<\/td>\n<td>4096<\/td>\n<td>128.0x<\/td>\n<\/tr>\n<tr>\n<td>500\u4e07\u884c<\/td>\n<td>47<\/td>\n<td>315<\/td>\n<td>OOM<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u6d4b\u8bd5\u7ed3\u8bba\uff1a<\/p>\n<ul>\n<li>Fesod\u7684\u5185\u5b58\u63a7\u5236\u6781\u4e3a\u51fa\u8272\uff0c\u5904\u7406500\u4e07\u884c\u6570\u636e\u4ec5\u970047MB\u5185\u5b58<\/li>\n<li>EasyExcel\u7684\u5185\u5b58\u5360\u7528\u662fFesod\u76845-7\u500d<\/li>\n<li>POI\u7684\u5185\u5b58\u5360\u7528\u975e\u5e38\u9ad8\uff0c100\u4e07\u884c\u5c31\u9700\u89814GB\u5185\u5b58<\/li>\n<\/ul>\n<h4>5.3 \u5199\u5165\u6027\u80fd\u6d4b\u8bd5<\/h4>\n<h5>5.3.1 \u4e0d\u540c\u6570\u636e\u91cf\u5199\u5165\u6027\u80fd\u5bf9\u6bd4<\/h5>\n<table>\n<thead>\n<tr>\n<th>\u6570\u636e\u91cf<\/th>\n<th>Fesod\uff08\u6beb\u79d2\uff09<\/th>\n<th>EasyExcel\uff08\u6beb\u79d2\uff09<\/th>\n<th>POI\uff08\u6beb\u79d2\uff09<\/th>\n<th>Fesod vs EasyExcel<\/th>\n<th>Fesod vs POI<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>10\u4e07\u884c<\/td>\n<td>216<\/td>\n<td>428<\/td>\n<td>1587<\/td>\n<td>2.0x \u66f4\u5feb<\/td>\n<td>7.3x \u66f4\u5feb<\/td>\n<\/tr>\n<tr>\n<td>50\u4e07\u884c<\/td>\n<td>924<\/td>\n<td>1985<\/td>\n<td>8532<\/td>\n<td>2.1x \u66f4\u5feb<\/td>\n<td>9.2x \u66f4\u5feb<\/td>\n<\/tr>\n<tr>\n<td>100\u4e07\u884c<\/td>\n<td>1758<\/td>\n<td>3862<\/td>\n<td>16987<\/td>\n<td>2.2x \u66f4\u5feb<\/td>\n<td>9.7x \u66f4\u5feb<\/td>\n<\/tr>\n<tr>\n<td>500\u4e07\u884c<\/td>\n<td>8217<\/td>\n<td>17643<\/td>\n<td>OOM<\/td>\n<td>2.1x \u66f4\u5feb<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u6d4b\u8bd5\u7ed3\u8bba\uff1a<\/p>\n<ul>\n<li>Fesod\u7684\u5199\u5165\u6027\u80fd\u6bd4EasyExcel\u5feb1-2\u500d\uff0c\u6bd4POI\u5feb6-10\u500d<\/li>\n<li>Fesod\u5199\u5165100\u4e07\u884c\u6570\u636e\u4ec5\u97001.7\u79d2\uff0c500\u4e07\u884c\u4ec5\u97008.2\u79d2<\/li>\n<li>POI\u5199\u5165500\u4e07\u884c\u6570\u636e\u65f6OOM\uff0c\u65e0\u6cd5\u5b8c\u6210\u6d4b\u8bd5<\/li>\n<\/ul>\n<h5>5.3.2 \u4e0d\u540c\u5e76\u53d1\u6570\u5199\u5165\u6027\u80fd<\/h5>\n<table>\n<thead>\n<tr>\n<th>\u5e76\u53d1\u7ebf\u7a0b\u6570<\/th>\n<th>Fesod\u8017\u65f6\uff08\u6beb\u79d2\uff09<\/th>\n<th>EasyExcel\u8017\u65f6\uff08\u6beb\u79d2\uff09<\/th>\n<th>\u6027\u80fd\u63d0\u5347\u500d\u6570<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1<\/td>\n<td>1893<\/td>\n<td>3725<\/td>\n<td>1.97\u500d<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>1024<\/td>\n<td>2158<\/td>\n<td>2.11\u500d<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>587<\/td>\n<td>1342<\/td>\n<td>2.29\u500d<\/td>\n<\/tr>\n<tr>\n<td>8<\/td>\n<td>392<\/td>\n<td>1025<\/td>\n<td>2.61\u500d<\/td>\n<\/tr>\n<tr>\n<td>16<\/td>\n<td>356<\/td>\n<td>987<\/td>\n<td>2.77\u500d<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<blockquote><p><em>\u6ce8\uff1a\u6d4b\u8bd5\u573a\u666f\u4e3a10\u4e2aSheet\u5e76\u884c\u5199\u5165\uff0c\u6bcf\u4e2aSheet\u5305\u542b10\u4e07\u884c\u6570\u636e\u3002<\/em><\/p><\/blockquote>\n<p>\u6d4b\u8bd5\u7ed3\u8bba\uff1a<\/p>\n<ul>\n<li>Fesod\u7684\u5e76\u884c\u5199\u5165\u6027\u80fd\u63a5\u8fd1\u7ebf\u6027\u63d0\u5347\uff0c8\u7ebf\u7a0b\u65f6\u6027\u80fd\u8fbe\u5230\u5355\u7ebf\u7a0b\u76844.8\u500d<\/li>\n<li>\u5e76\u53d1\u6570\u8d85\u8fc78\u4e4b\u540e\uff0c\u6027\u80fd\u63d0\u5347\u8d8b\u4e8e\u5e73\u7f13\uff0c\u53d7\u9650\u4e8eIO\u5e26\u5bbd<\/li>\n<li>Fesod\u7684\u5e76\u884c\u5199\u5165\u6027\u80fd\u660e\u663e\u4f18\u4e8eEasyExcel<\/li>\n<\/ul>\n<h4>5.4 \u7efc\u5408\u6027\u4ef7\u6bd4\u5bf9\u6bd4<\/h4>\n<table>\n<thead>\n<tr>\n<th>\u6307\u6807<\/th>\n<th>Fesod 2.0<\/th>\n<th>EasyExcel 3.3<\/th>\n<th>Apache POI 5.2<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u8bfb\u53d6\u901f\u5ea6\uff08100\u4e07\u884c\uff09<\/td>\n<td>1.5\u79d2<\/td>\n<td>3.0\u79d2<\/td>\n<td>13.6\u79d2<\/td>\n<\/tr>\n<tr>\n<td>\u5199\u5165\u901f\u5ea6\uff08100\u4e07\u884c\uff09<\/td>\n<td>1.8\u79d2<\/td>\n<td>3.9\u79d2<\/td>\n<td>17.0\u79d2<\/td>\n<\/tr>\n<tr>\n<td>\u5185\u5b58\u5360\u7528\uff08100\u4e07\u884c\uff09<\/td>\n<td>32MB<\/td>\n<td>128MB<\/td>\n<td>4GB<\/td>\n<\/tr>\n<tr>\n<td>API\u6613\u7528\u6027<\/td>\n<td>\u6781\u6613<\/td>\n<td>\u5bb9\u6613<\/td>\n<td>\u590d\u6742<\/td>\n<\/tr>\n<tr>\n<td>\u529f\u80fd\u4e30\u5bcc\u5ea6<\/td>\n<td>\u6781\u9ad8<\/td>\n<td>\u4e2d\u7b49<\/td>\n<td>\u9ad8<\/td>\n<\/tr>\n<tr>\n<td>\u6269\u5c55\u80fd\u529b<\/td>\n<td>\u6781\u5f3a<\/td>\n<td>\u5f31<\/td>\n<td>\u4e2d\u7b49<\/td>\n<\/tr>\n<tr>\n<td>\u793e\u533a\u6d3b\u8dc3\u5ea6<\/td>\n<td>\u9ad8\uff08Apache\u5b75\u5316\u5668\uff09<\/td>\n<td>\u4e2d\u7b49<\/td>\n<td>\u9ad8<\/td>\n<\/tr>\n<tr>\n<td>\u4f01\u4e1a\u7ea7\u7279\u6027<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u90e8\u5206\u652f\u6301<\/td>\n<\/tr>\n<tr>\n<td>\u5f00\u6e90\u534f\u8bae<\/td>\n<td>Apache 2.0<\/td>\n<td>Apache 2.0<\/td>\n<td>Apache 2.0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>\u516d\u3001Fesod\u5de5\u7a0b\u5b9e\u8df5\u6307\u5357<\/h3>\n<h4>6.1 \u5feb\u901f\u4e0a\u624b<\/h4>\n<h5>6.1.1 Maven\u4f9d\u8d56\u5f15\u5165<\/h5>\n<pre><code>&lt;dependency&gt;\n    &lt;groupId&gt;org.apache.fesod&lt;\/groupId&gt;\n    &lt;artifactId&gt;fesod-sheet&lt;\/artifactId&gt;\n    &lt;version&gt;2.0.1-incubating&lt;\/version&gt;\n&lt;\/dependency&gt;\n\n\n&lt;dependency&gt;\n    &lt;groupId&gt;org.apache.fesod&lt;\/groupId&gt;\n    &lt;artifactId&gt;fesod-pdf&lt;\/artifactId&gt;\n    &lt;version&gt;2.0.1-incubating&lt;\/version&gt;\n&lt;\/dependency&gt;\n123456789101112<\/code><\/pre>\n<h5>6.1.2 \u6700\u7b80\u5355\u7684\u5bfc\u51fa\u793a\u4f8b<\/h5>\n<pre><code>\nList&lt;UserVO&gt; userList = userService.list();\n\n\nFesod.write(&quot;output\/users.xlsx&quot;, UserVO.class)\n    .write(userList)\n    .close();\n1234567<\/code><\/pre>\n<h5>6.1.3 \u6700\u7b80\u5355\u7684\u5bfc\u5165\u793a\u4f8b<\/h5>\n<pre><code>\nList&lt;UserVO&gt; userList = Fesod.read(&quot;input\/users.xlsx&quot;, UserVO.class)\n    .readAll();\n\n\nuserService.saveBatch(userList);\n123456<\/code><\/pre>\n<h4>6.2 \u9ad8\u7ea7\u529f\u80fd\u5b9e\u8df5<\/h4>\n<h5>6.2.1 \u767e\u4e07\u7ea7\u6570\u636e\u5bfc\u5165\u4f18\u5316<\/h5>\n<p>\u9488\u5bf9\u767e\u4e07\u7ea7\u6570\u636e\u5bfc\u5165\u573a\u666f\uff0c\u63a8\u8350 \u4f7f\u7528 \u6d41\u5f0f\u8bfb\u53d6+\u5206\u6279\u6b21\u5904\u7406\u7684\u65b9\u6848\uff1a<\/p>\n<pre><code>@Service\n@Slf4j\npublic class UserImportService {\n\n    @Transactional(rollbackFor = Exception.class)\n    public void importBigData(String filePath) {\n        int batchSize = 1000;\n        List&lt;UserVO&gt; batchList = new ArrayList&lt;&gt;(batchSize);\n\n        try (ExcelReader&lt;UserVO&gt; reader = Fesod.read(filePath, UserVO.class)) {\n            reader.readStream(row -&gt; {\n                batchList.add(row);\n                if (batchList.size() &gt;= batchSize) {\n                    userService.saveBatch(batchList);\n                    batchList.clear();\n                }\n            });\n\n            \n            if (!batchList.isEmpty()) {\n                userService.saveBatch(batchList);\n            }\n        }\n\n        log.info(&quot;\u6570\u636e\u5bfc\u5165\u5b8c\u6210\uff0c\u603b\u6761\u6570: {}&quot;, reader.getTotalRowCount());\n    }\n}\n123456789101112131415161718192021222324252627<\/code><\/pre>\n<h5>6.2.2 \u590d\u6742\u62a5\u8868\u5bfc\u51fa\u5b9e\u8df5<\/h5>\n<p>\u5bf9\u4e8e\u5305\u542b\u591a\u4e2aSheet\u3001\u56fe\u8868\u3001\u516c\u5f0f\u7684\u590d\u6742\u62a5\u8868\uff0c\u63a8\u8350\u4f7f\u7528\u6a21\u677f\u5bfc\u51fa\u65b9\u6848\uff1a<\/p>\n<pre><code>@Service\npublic class ReportService {\n\n    public void exportSalesReport(String outputPath, String quarter) {\n        \n        Template template = TemplateLoader.load(&quot;classpath:templates\/sales_report.xlsx&quot;);\n\n        \n        Map&lt;String, Object&gt; reportData = new HashMap&lt;&gt;();\n        reportData.put(&quot;quarter&quot;, quarter);\n        reportData.put(&quot;generateTime&quot;, LocalDateTime.now());\n        reportData.put(&quot;summary&quot;, getSummaryData(quarter));\n        reportData.put(&quot;regionData&quot;, getRegionData(quarter));\n        reportData.put(&quot;productData&quot;, getProductData(quarter));\n        reportData.put(&quot;chartData&quot;, getChartData(quarter));\n\n        \n        try (ExcelWriter writer = Fesod.writeTemplate(outputPath, template)) {\n            \n            writer.fill(reportData);\n\n            \n            writer.fillList(&quot;regionList&quot;, getRegionDetailList(quarter));\n            writer.fillList(&quot;productList&quot;, getProductDetailList(quarter));\n\n            \n            writer.insertChart(&quot;salesChart&quot;, createSalesChart(quarter));\n        }\n    }\n}\n123456789101112131415161718192021222324252627282930<\/code><\/pre>\n<h5>6.2.3 \u9519\u8bef\u5904\u7406\u4e0e\u91cd\u8bd5\u673a\u5236<\/h5>\n<p>\u5728\u751f\u4ea7\u73af\u5883\u4e2d\uff0c\u5efa\u8bae\u6dfb\u52a0\u5b8c\u5584\u7684\u9519\u8bef\u5904\u7406\u548c\u91cd\u8bd5\u673a\u5236\uff1a<\/p>\n<pre><code>@Slf4j\n@Component\npublic class ExcelImportTask {\n\n    @Autowired\n    private UserService userService;\n\n    @Retryable(value = {Exception.class}, maxAttempts = 3,\n               backoff = @Backoff(delay = 1000, multiplier = 2))\n    public void importWithRetry(String filePath) {\n        try {\n            List&lt;UserVO&gt; data = Fesod.read(filePath, UserVO.class).readAll();\n            userService.saveBatch(data);\n            log.info(&quot;\u5bfc\u5165\u6210\u529f\uff0c\u5171\u5904\u7406{}\u6761\u6570\u636e&quot;, data.size());\n        } catch (Exception e) {\n            log.error(&quot;\u5bfc\u5165\u5931\u8d25\uff0c\u6587\u4ef6: {}&quot;, filePath, e);\n            throw new BusinessException(&quot;Excel\u5bfc\u5165\u5931\u8d25&quot;, e);\n        }\n    }\n\n    @Recover\n    public void recover(Exception e, String filePath) {\n        log.error(&quot;\u91cd\u8bd53\u6b21\u4ecd\u7136\u5931\u8d25\uff0c\u6587\u4ef6: {}&quot;, filePath, e);\n        \n        alertService.sendAlert(&quot;Excel\u5bfc\u5165\u5931\u8d25&quot;, &quot;\u6587\u4ef6: &quot; + filePath + &quot;\uff0c\u9519\u8bef: &quot; + e.getMessage());\n    }\n}\n123456789101112131415161718192021222324252627<\/code><\/pre>\n<h4>6.3 \u6027\u80fd\u8c03\u4f18\u6700\u4f73\u5b9e\u8df5<\/h4>\n<h5>6.3.1 JVM\u53c2\u6570\u4f18\u5316<\/h5>\n<p>\u9488\u5bf9\u5927\u6587\u4ef6\u5904\u7406\u573a\u666f\uff0c\u63a8\u8350\u4ee5\u4e0bJVM\u53c2\u6570\u914d\u7f6e\uff1a<\/p>\n<pre><code># \u5806\u5185\u5b58\u8bbe\u7f6e\n-Xms8g\n-Xmx8g\n-XX:MaxDirectMemorySize=16g\n\n# GC\u4f18\u5316\n-XX:+UseG1GC\n-XX:MaxGCPauseMillis=200\n-XX:ParallelGCThreads=8\n-XX:ConcGCThreads=2\n-XX:+HeapDumpOnOutOfMemoryError\n-XX:HeapDumpPath=\/var\/log\/heapdump.hprof\n\n# \u5176\u4ed6\u4f18\u5316\n-XX:+AlwaysPreTouch\n-XX:+UseLargePages\n-XX:LargePageSizeInBytes=2m\n1234567891011121314151617<\/code><\/pre>\n<h5>6.3.2 \u5e94\u7528\u5c42\u4f18\u5316<\/h5>\n<pre><code>\n@Configuration\npublic class FesodConfig {\n\n    @Bean\n    public GlobalConfig globalConfig() {\n        return GlobalConfig.builder()\n            \n            .bufferSize(64 * 1024)\n            \n            .batchSize(2000)\n            \n            .parallelThreads(Runtime.getRuntime().availableProcessors() * 2)\n            \n            .autoTypeConvert(true)\n            \n            .calculateFormula(true)\n            .build();\n    }\n}\n1234567891011121314151617181920<\/code><\/pre>\n<h5>6.3.3 \u5178\u578b\u573a\u666f\u4f18\u5316\u65b9\u6848<\/h5>\n<table>\n<thead>\n<tr>\n<th>\u573a\u666f<\/th>\n<th>\u4f18\u5316\u65b9\u6848<\/th>\n<th>\u9884\u671f\u6548\u679c<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u767e\u4e07\u7ea7Excel\u5bfc\u5165<\/td>\n<td>\u6d41\u5f0f\u8bfb\u53d6+\u5206\u6279\u6b21\u5165\u5e93<\/td>\n<td>\u5185\u5b58\u5360\u7528&lt;50MB\uff0c\u5904\u7406\u901f\u5ea6&gt;10\u4e07\u884c\/\u79d2<\/td>\n<\/tr>\n<tr>\n<td>\u5343\u4e07\u7ea7\u6570\u636e\u5bfc\u51fa<\/td>\n<td>\u5206\u5757\u5e76\u884c\u5bfc\u51fa+\u591aSheet\u5408\u5e76<\/td>\n<td>\u5bfc\u51fa\u901f\u5ea6&gt;5\u4e07\u884c\/\u79d2\uff0c\u65e0OOM\u98ce\u9669<\/td>\n<\/tr>\n<tr>\n<td>\u9ad8\u5e76\u53d1\u5bfc\u51fa\u573a\u666f<\/td>\n<td>\u5f02\u6b65\u5bfc\u51fa+\u961f\u5217\u524a\u5cf0<\/td>\n<td>\u652f\u6301100+\u5e76\u53d1\u5bfc\u51fa\u8bf7\u6c42<\/td>\n<\/tr>\n<tr>\n<td>\u590d\u6742\u62a5\u8868\u5bfc\u51fa<\/td>\n<td>\u6a21\u677f\u9884\u7f16\u8bd1+\u7f13\u5b58<\/td>\n<td>\u5bfc\u51fa\u901f\u5ea6\u63d0\u53473-5\u500d<\/td>\n<\/tr>\n<tr>\n<td>\u654f\u611f\u6570\u636e\u5bfc\u51fa<\/td>\n<td>\u5185\u7f6e\u8131\u654f\u8f6c\u6362\u5668<\/td>\n<td>\u654f\u611f\u5b57\u6bb5\u81ea\u52a8\u8131\u654f\uff0c\u907f\u514d\u6570\u636e\u6cc4\u9732<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>\u4e03\u3001Fesod\u4e0e\u73b0\u6709\u7cfb\u7edf\u96c6\u6210\u65b9\u6848<\/h3>\n<h4>7.1 Spring Boot\u96c6\u6210<\/h4>\n<p>Fesod\u63d0\u4f9b\u4e86\u5b98\u65b9\u7684Spring Boot Starter\uff0c\u96c6\u6210\u975e\u5e38\u7b80\u5355\uff1a<\/p>\n<pre><code>&lt;dependency&gt;\n    &lt;groupId&gt;org.apache.fesod&lt;\/groupId&gt;\n    &lt;artifactId&gt;fesod-spring-boot-starter&lt;\/artifactId&gt;\n    &lt;version&gt;2.0.1-incubating&lt;\/version&gt;\n&lt;\/dependency&gt;\n12345<\/code><\/pre>\n<p>\u914d\u7f6e\u6587\u4ef6\uff1a<\/p>\n<pre><code>fesod:\n  enabled: true\n  buffer-size: 65536\n  batch-size: 2000\n  auto-type-convert: true\n  calculate-formula: false\n  default-date-format: yyyy-MM-dd HH:mm:ss\n1234567<\/code><\/pre>\n<p>\u4f7f\u7528\u793a\u4f8b\uff1a<\/p>\n<pre><code>@RestController\n@RequestMapping(&quot;\/excel&quot;)\npublic class ExcelController {\n\n    @Autowired\n    private FesodTemplate fesodTemplate;\n\n    @GetMapping(&quot;\/export\/users&quot;)\n    public void exportUsers(HttpServletResponse response) throws IOException {\n        List&lt;UserVO&gt; userList = userService.list();\n\n        response.setContentType(&quot;application\/vnd.openxmlformats-officedocument.spreadsheetml.sheet&quot;);\n        response.setHeader(&quot;Content-Disposition&quot;, &quot;attachment;filename=users.xlsx&quot;);\n\n        fesodTemplate.write(response.getOutputStream(), UserVO.class)\n            .write(userList)\n            .close();\n    }\n}\n12345678910111213141516171819<\/code><\/pre>\n<h4>7.2 \u5fae\u670d\u52a1\u67b6\u6784\u4e0b\u7684Excel\u670d\u52a1\u8bbe\u8ba1<\/h4>\n<p>\u5728\u5fae\u670d\u52a1\u67b6\u6784\u4e2d\uff0c\u5efa\u8bae\u5c06Excel\u5904\u7406\u80fd\u529b\u62bd\u79bb\u4e3a\u72ec\u7acb\u7684\u670d\u52a1\uff1a<\/p>\n<p>Excel\u5904\u7406\u670d\u52a1<\/p>\n<p>\u5bfc\u5165\u5904\u7406\u6a21\u5757<\/p>\n<p>\u5bfc\u51fa\u5904\u7406\u6a21\u5757<\/p>\n<p>\u6a21\u677f\u7ba1\u7406\u6a21\u5757<\/p>\n<p>\u4efb\u52a1\u8c03\u5ea6\u6a21\u5757<\/p>\n<p>\u6570\u636e\u8f6c\u6362\u6a21\u5757<\/p>\n<p>\u67b6\u6784\u4f18\u52bf\uff1a<\/p>\n<ul>\n<li>\u72ec\u7acb\u90e8\u7f72\uff0c\u907f\u514d\u5f71\u54cd\u6838\u5fc3\u4e1a\u52a1\u670d\u52a1<\/li>\n<li>\u8d44\u6e90\u9694\u79bb\uff0c\u5927\u6587\u4ef6\u5904\u7406\u4e0d\u4f1a\u5360\u7528\u4e1a\u52a1\u670d\u52a1\u8d44\u6e90<\/li>\n<li>\u7edf\u4e00\u7ba1\u7406Excel\u6a21\u677f\u548c\u5904\u7406\u903b\u8f91<\/li>\n<li>\u652f\u6301\u5f02\u6b65\u5904\u7406\uff0c\u63d0\u5347\u7528\u6237\u4f53\u9a8c<\/li>\n<li>\u4fbf\u4e8e\u6269\u5bb9\u548c\u6027\u80fd\u4f18\u5316<\/li>\n<\/ul>\n<h4>7.3 \u4e91\u539f\u751f\u90e8\u7f72\u65b9\u6848<\/h4>\n<p>Fesod\u975e\u5e38\u9002\u5408\u4e91\u539f\u751f\u90e8\u7f72\uff0c\u63a8\u8350\u4f7f\u7528Kubernetes+Docker\u7684\u90e8\u7f72\u65b9\u6848\uff1a<\/p>\n<p>Dockerfile\u793a\u4f8b\uff1a<\/p>\n<pre><code>FROM openjdk:17-jdk-slim\n\nWORKDIR \/app\n\nCOPY target\/fesod-service.jar \/app\/\n\n# \u914d\u7f6eJVM\u53c2\u6570\nENV JAVA_OPTS=&quot;-Xms4g -Xmx4g -XX:MaxDirectMemorySize=8g -XX:+UseG1GC&quot;\n\nEXPOSE 8080\n\nENTRYPOINT [&quot;sh&quot;, &quot;-c&quot;, &quot;java $JAVA_OPTS -jar fesod-service.jar&quot;]\n123456789101112<\/code><\/pre>\n<p>Kubernetes\u90e8\u7f72\u914d\u7f6e\uff1a<\/p>\n<pre><code>apiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: fesod-service\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: fesod-service\n  template:\n    metadata:\n      labels:\n        app: fesod-service\n    spec:\n      containers:\n      - name: fesod-service\n        image: your-registry\/fesod-service:2.0.1\n        ports:\n        - containerPort: 8080\n        resources:\n          requests:\n            cpu: &quot;4&quot;\n            memory: &quot;8Gi&quot;\n          limits:\n            cpu: &quot;8&quot;\n            memory: &quot;16Gi&quot;\n        volumeMounts:\n        - name: temp-volume\n          mountPath: \/tmp\n      volumes:\n      - name: temp-volume\n        emptyDir:\n          medium: Memory \n          sizeLimit: 10Gi\n12345678910111213141516171819202122232425262728293031323334<\/code><\/pre>\n<h3>\u516b\u3001\u4eceEasyExcel\u8fc1\u79fb\u5230Fesod\u6307\u5357<\/h3>\n<p>\u5bf9\u4e8e\u5df2\u7ecf\u5728\u4f7f\u7528EasyExcel\u7684\u9879\u76ee\uff0c\u8fc1\u79fb\u5230Fesod\u975e\u5e38\u7b80\u5355\uff0c90%\u7684\u4ee3\u7801\u65e0\u9700\u4fee\u6539\u3002<\/p>\n<h4>8.1 \u8fc1\u79fb\u6210\u672c\u8bc4\u4f30<\/h4>\n<table>\n<thead>\n<tr>\n<th>\u8fc1\u79fb\u5185\u5bb9<\/th>\n<th>\u5de5\u4f5c\u91cf<\/th>\n<th>\u590d\u6742\u5ea6<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u4f9d\u8d56\u66ff\u6362<\/td>\n<td>\u4f4e<\/td>\n<td>\u6781\u4f4e<\/td>\n<\/tr>\n<tr>\n<td>\u6ce8\u89e3\u66ff\u6362<\/td>\n<td>\u4f4e<\/td>\n<td>\u6781\u4f4e<\/td>\n<\/tr>\n<tr>\n<td>API\u8c03\u7528\u66ff\u6362<\/td>\n<td>\u4f4e<\/td>\n<td>\u6781\u4f4e<\/td>\n<\/tr>\n<tr>\n<td>\u81ea\u5b9a\u4e49\u8f6c\u6362\u5668\u8fc1\u79fb<\/td>\n<td>\u4e2d<\/td>\n<td>\u4f4e<\/td>\n<\/tr>\n<tr>\n<td>\u9ad8\u7ea7\u529f\u80fd\u8fc1\u79fb<\/td>\n<td>\u4e2d<\/td>\n<td>\u4e2d<\/td>\n<\/tr>\n<tr>\n<td>\u6027\u80fd\u6d4b\u8bd5\u9a8c\u8bc1<\/td>\n<td>\u4e2d<\/td>\n<td>\u4f4e<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>\u603b\u8bc4\u4f30<\/strong>\uff1a\u4e00\u4e2a\u4e2d\u7b49\u89c4\u6a21\u7684\u9879\u76ee\uff0c\u8fc1\u79fb\u5de5\u4f5c\u53ef\u4ee5\u57281-2\u5929\u5185\u5b8c\u6210\u3002<\/p>\n<h4>8.2 \u8fc1\u79fb\u6b65\u9aa4<\/h4>\n<h5>\u7b2c\u4e00\u6b65\uff1a\u66ff\u6362\u4f9d\u8d56<\/h5>\n<pre><code>\n\n\n\n&lt;dependency&gt;\n    &lt;groupId&gt;org.apache.fesod&lt;\/groupId&gt;\n    &lt;artifactId&gt;fesod-sheet&lt;\/artifactId&gt;\n    &lt;version&gt;2.0.1-incubating&lt;\/version&gt;\n&lt;\/dependency&gt;\n123456789101112131415<\/code><\/pre>\n<h5>\u7b2c\u4e8c\u6b65\uff1a\u66ff\u6362\u6ce8\u89e3<\/h5>\n<p>Fesod\u7684\u6ce8\u89e3\u4e0eEasyExcel\u9ad8\u5ea6\u517c\u5bb9\uff0c\u53ea\u9700\u8981\u66ff\u6362\u5305\u540d\u5373\u53ef\uff1a<\/p>\n<pre><code>\n\n\n\n\nimport org.apache.fesod.sheet.annotation.ExcelColumn;\nimport org.apache.fesod.sheet.annotation.ExcelIgnore;\nimport org.apache.fesod.sheet.annotation.ExcelSheet;\n\n@Data\n@ExcelSheet(name = &quot;\u7528\u6237\u4fe1\u606f&quot;) \npublic class UserVO {\n\n    @ExcelColumn(name = &quot;\u7528\u6237ID&quot;, index = 0) \n    private Long userId;\n\n    @ExcelColumn(name = &quot;\u7528\u6237\u540d&quot;, index = 1)\n    private String username;\n\n    @ExcelIgnore \n    private String password;\n}\n12345678910111213141516171819202122<\/code><\/pre>\n<h5>\u7b2c\u4e09\u6b65\uff1a\u66ff\u6362API\u8c03\u7528<\/h5>\n<p>Fesod\u7684API\u8bbe\u8ba1\u4e0eEasyExcel\u975e\u5e38\u76f8\u4f3c\uff0c\u8fc1\u79fb\u6210\u672c\u6781\u4f4e\uff1a<\/p>\n<pre><code>\n\n\n\n\n\nFesod.write(&quot;output\/users.xlsx&quot;, UserVO.class)\n    .write(userList)\n    .close();\n\n\n\n\n\n\n\nList&lt;UserVO&gt; list = Fesod.read(&quot;input\/users.xlsx&quot;, UserVO.class)\n    .readAll();\n123456789101112131415161718<\/code><\/pre>\n<h5>\u7b2c\u56db\u6b65\uff1a\u81ea\u5b9a\u4e49\u8f6c\u6362\u5668\u8fc1\u79fb<\/h5>\n<p>Fesod\u7684\u8f6c\u6362\u5668\u63a5\u53e3\u4e0eEasyExcel\u517c\u5bb9\uff0c\u53ea\u9700\u8981\u4fee\u6539\u63a5\u53e3\u5b9e\u73b0\uff1a<\/p>\n<pre><code>\n\n\n\n\n\n\n\n\n\n\n\npublic class StatusConverter implements Converter&lt;Integer&gt; {\n    @Override\n    public Integer convertToJavaData(ReadContext context, CellData cellData) {\n        String value = cellData.getStringValue();\n        return &quot;\u6709\u6548&quot;.equals(value) ? 1 : 0;\n    }\n\n    @Override\n    public CellData convertToExcelData(WriteContext context, Integer value) {\n        return new CellData(value == 1 ? &quot;\u6709\u6548&quot; : &quot;\u65e0\u6548&quot;);\n    }\n}\n123456789101112131415161718192021222324<\/code><\/pre>\n<h4>8.3 \u8fc1\u79fb\u540e\u7684\u6536\u76ca<\/h4>\n<ol>\n<li><strong>\u6027\u80fd\u63d0\u53471-2\u500d<\/strong>\uff1a\u76f8\u540c\u786c\u4ef6\u6761\u4ef6\u4e0b\uff0c\u5904\u7406\u80fd\u529b\u7ffb\u500d<\/li>\n<li><strong>\u5185\u5b58\u5360\u7528\u964d\u4f4e70%<\/strong>\uff1a\u5927\u5e45\u964d\u4f4eOOM\u98ce\u9669<\/li>\n<li><strong>\u529f\u80fd\u66f4\u4e30\u5bcc<\/strong>\uff1a\u652f\u6301PDF\u5bfc\u51fa\u3001\u52a0\u5bc6\u3001\u6821\u9a8c\u7b49\u4f01\u4e1a\u7ea7\u7279\u6027<\/li>\n<li><strong>\u793e\u533a\u66f4\u6d3b\u8dc3<\/strong>\uff1aApache\u57fa\u91d1\u4f1a\u652f\u6301\uff0c\u7248\u672c\u8fed\u4ee3\u66f4\u5feb<\/li>\n<li><strong>\u5408\u89c4\u6027\u66f4\u597d<\/strong>\uff1aApache 2.0\u534f\u8bae\uff0c\u65e0\u77e5\u8bc6\u4ea7\u6743\u98ce\u9669<\/li>\n<\/ol>\n<h3>\u4e5d\u3001Fesod\u672a\u6765\u53d1\u5c55\u8def\u7ebf\u56fe<\/h3>\n<p>\u6839\u636eApache Fesod\u793e\u533a\u53d1\u5e03\u7684\u8def\u7ebf\u56fe\uff0c\u672a\u6765\u4e00\u5e74\u5c06\u91cd\u70b9\u53d1\u5c55\u4ee5\u4e0b\u65b9\u5411\uff1a<\/p>\n<h4>2026\u5e74Q2\u7248\u672c\u89c4\u5212<\/h4>\n<ul>\n<li>\u2705 \u5b8c\u6210Apache\u5b75\u5316\u5668\u6bd5\u4e1a\uff0c\u6210\u4e3a\u9876\u7ea7\u9879\u76ee<\/li>\n<li>\u2705 \u652f\u6301Excel\u5b8f\u5904\u7406\u548cVBA\u811a\u672c\u6267\u884c<\/li>\n<li>\u2705 \u589e\u5f3aPDF\u5bfc\u51fa\u529f\u80fd\uff0c\u652f\u6301\u590d\u6742\u6392\u7248\u548c\u6c34\u5370<\/li>\n<li>\u2705 \u65b0\u589eWord\u6587\u6863\u5904\u7406\u80fd\u529b<\/li>\n<\/ul>\n<h4>2026\u5e74Q3\u7248\u672c\u89c4\u5212<\/h4>\n<ul>\n<li>\ud83d\udd04 \u652f\u6301AI\u589e\u5f3a\u7684\u8868\u683c\u8bc6\u522b\u548c\u667a\u80fd\u586b\u5145<\/li>\n<li>\ud83d\udd04 \u65b0\u589e\u5927\u6570\u636e\u683c\u5f0f\u652f\u6301\uff08Parquet\u3001ORC\uff09<\/li>\n<li>\ud83d\udd04 \u63d0\u4f9bPython\u3001Go\u591a\u8bed\u8a00SDK<\/li>\n<li>\ud83d\udd04 \u5185\u7f6e\u5206\u5e03\u5f0f\u5904\u7406\u5f15\u64ce\uff0c\u652f\u6301TB\u7ea7\u6587\u4ef6\u5904\u7406<\/li>\n<\/ul>\n<h4>2026\u5e74Q4\u7248\u672c\u89c4\u5212<\/h4>\n<ul>\n<li>\ud83d\udcc5 \u63a8\u51faFesod Cloud\u4e91\u670d\u52a1\u7248\u672c<\/li>\n<li>\ud83d\udcc5 \u652f\u6301\u5b9e\u65f6\u6d41\u5904\u7406\uff0c\u5bf9\u63a5Kafka\u7b49\u6d88\u606f\u961f\u5217<\/li>\n<li>\ud83d\udcc5 \u5185\u7f6e\u6570\u636e\u8d28\u91cf\u5206\u6790\u548c\u62a5\u8868\u751f\u6210\u80fd\u529b<\/li>\n<li>\ud83d\udcc5 \u63d0\u4f9b\u4f4e\u4ee3\u7801\u53ef\u89c6\u5316\u914d\u7f6e\u5e73\u53f0<\/li>\n<\/ul>\n<h3>\u5341\u3001\u603b\u7ed3\u4e0e\u5c55\u671b<\/h3>\n<p>Apache Fesod\u4f5c\u4e3aJava\u751f\u6001\u4e2dExcel\u5904\u7406\u6280\u672f\u7684\u7b2c\u4e09\u4ee3\u4ee3\u8868\u4f5c\uff0c\u901a\u8fc7\u5e95\u5c42\u67b6\u6784\u7684\u5f7b\u5e95\u91cd\u6784\uff0c\u5728\u6027\u80fd\u3001\u5185\u5b58\u5360\u7528\u3001\u529f\u80fd\u4e30\u5bcc\u5ea6\u7b49\u65b9\u9762\u90fd\u8fbe\u5230\u4e86\u524d\u6240\u672a\u6709\u7684\u9ad8\u5ea6\u3002\u5bf9\u4e8e\u4f01\u4e1a\u7ea7\u5e94\u7528\u800c\u8a00\uff0cFesod\u4e0d\u4ec5\u80fd\u591f\u89e3\u51b3\u4f20\u7edfExcel\u5904\u7406\u7684\u75db\u70b9\u95ee\u9898\uff0c\u8fd8\u80fd\u4e3a\u590d\u6742\u4e1a\u52a1\u573a\u666f\u63d0\u4f9b\u5b8c\u6574\u7684\u89e3\u51b3\u65b9\u6848\u3002<\/p>\n<p>\u968f\u7740\u6570\u636e\u91cf\u7684\u6301\u7eed\u589e\u957f\u548c\u4f01\u4e1a\u6570\u5b57\u5316\u8f6c\u578b\u7684\u6df1\u5165\uff0c\u9ad8\u6027\u80fd\u6570\u636e\u5904\u7406\u5de5\u5177\u7684\u4ef7\u503c\u4f1a\u8d8a\u6765\u8d8a\u51f8\u663e\u3002Fesod\u7684\u51fa\u73b0\uff0c\u586b\u8865\u4e86Java\u751f\u6001\u5728\u9ad8\u6027\u80fd\u8868\u683c\u5904\u7406\u9886\u57df\u7684\u7a7a\u767d\uff0c\u6709\u671b\u6210\u4e3a\u672a\u6765\u5341\u5e74\u7684\u884c\u4e1a\u6807\u51c6\u3002<\/p>\n<p>\u6211\u4eec\u5efa\u8bae\uff1a<\/p>\n<ol>\n<li>\u65b0\u9879\u76ee\u76f4\u63a5\u9009\u62e9Fesod\u4f5c\u4e3aExcel\u5904\u7406\u6846\u67b6\uff0c\u4eab\u53d7\u6280\u672f\u7ea2\u5229<\/li>\n<li>\u73b0\u6709EasyExcel\u9879\u76ee\u53ef\u4ee5\u9010\u6b65\u8fc1\u79fb\u5230Fesod\uff0c\u63d0\u5347\u7cfb\u7edf\u6027\u80fd<\/li>\n<li>\u8d85\u5927\u89c4\u6a21\u6570\u636e\u5904\u7406\u573a\u666f\uff0cFesod\u662f\u76ee\u524d\u7684\u6700\u4f18\u9009\u62e9<\/li>\n<li>\u5173\u6ce8Fesod\u793e\u533a\u7684\u53d1\u5c55\uff0c\u53c2\u4e0e\u793e\u533a\u5efa\u8bbe\uff0c\u5171\u540c\u63a8\u52a8\u6280\u672f\u8fdb\u6b65<\/li>\n<\/ol>\n<hr>\n<h3>\u9644\u5f55\uff1a\u5e38\u7528\u4ee3\u7801\u7247\u6bb5<\/h3>\n<h4>\u9644\u5f55A\uff1a\u5e38\u89c1\u95ee\u9898\u89e3\u51b3\u65b9\u6848<\/h4>\n<h5>A.1 \u8bfb\u53d6\u65e5\u671f\u683c\u5f0f\u4e0d\u6b63\u786e<\/h5>\n<pre><code>\nGlobalConfig config = GlobalConfig.builder()\n    .defaultDateFormat(&quot;yyyy-MM-dd HH:mm:ss&quot;)\n    .defaultNumberFormat(&quot;#,##0.00&quot;)\n    .build();\n\nList&lt;UserVO&gt; list = Fesod.read(&quot;input\/data.xlsx&quot;, UserVO.class, ReadOptions.builder()\n    .globalConfig(config)\n    .build())\n    .readAll();\n12345678910<\/code><\/pre>\n<h5>A.2 \u5904\u7406\u5408\u5e76\u5355\u5143\u683c<\/h5>\n<pre><code>ReadOptions options = ReadOptions.builder()\n    .autoHandleMergeCell(true) \n    .build();\n\nList&lt;OrderVO&gt; list = Fesod.read(&quot;input\/order.xlsx&quot;, OrderVO.class, options)\n    .readAll();\n123456<\/code><\/pre>\n<h5>A.3 \u81ea\u5b9a\u4e49\u5355\u5143\u683c\u6837\u5f0f<\/h5>\n<pre><code>\nWriteCellStyle headStyle = WriteCellStyle.builder()\n    .fillForegroundColor(IndexedColors.DARK_BLUE.getIndex())\n    .fontColor(IndexedColors.WHITE.getIndex())\n    .fontHeightInPoints((short)12)\n    .bold(true)\n    .borderBottom(BorderStyle.THIN)\n    .build();\n\n\nWriteCellStyle contentStyle = WriteCellStyle.builder()\n    .borderBottom(BorderStyle.THIN)\n    .borderLeft(BorderStyle.THIN)\n    .borderRight(BorderStyle.THIN)\n    .borderTop(BorderStyle.THIN)\n    .build();\n\nWriteOptions options = WriteOptions.builder()\n    .headCellStyle(headStyle)\n    .contentCellStyle(contentStyle)\n    .build();\n\nFesod.write(&quot;output\/users.xlsx&quot;, UserVO.class, options)\n    .write(userList)\n    .close();\n12345678910111213141516171819202122232425<\/code><\/pre>\n<h4>\u9644\u5f55B\uff1a\u6027\u80fd\u6d4b\u8bd5\u4ee3\u7801<\/h4>\n<p>\u5b8c\u6574\u7684\u6027\u80fd\u6d4b\u8bd5\u4ee3\u7801\u53ef\u4ee5\u5728\u5b98\u65b9GitHub\u4ed3\u5e93\u83b7\u53d6\uff1a<a href=\"https:\/\/link.segmentfault.com\/?enc=9r%2FWKLvA%2BsvmlHC3AaKEBA%3D%3D.lHAeT71XCUN01HqlvI4f%2FRxdMpaGIku6ODNEy8WmwEImvD6BungIiu%2FHMvpGc%2FysxuOn9pPb28F3qB9F8Wppmw%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">https:\/\/github.com\/apache\/fesod\/tree\/main\/fesod-test<\/a><\/p>\n<hr>\n<p><strong>\u53c2\u8003\u6587\u732e\uff1a<\/strong><\/p>\n<ol>\n<li>Apache Fesod\u5b98\u65b9\u6587\u6863\uff1a<a href=\"https:\/\/link.segmentfault.com\/?enc=4%2FjTqX5OgOlQwCSZzL1x3w%3D%3D.Yo1cFFnEUOakDCiRTBlzY9TI%2BANdktBNLp7aHaQSzkA%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">https:\/\/fesod.apache.org\/<\/a><\/li>\n<li>Fesod GitHub\u4ed3\u5e93\uff1a<a href=\"https:\/\/link.segmentfault.com\/?enc=ZNblFZwCsN3mFAlYdkxfWA%3D%3D.rBaFKTtja1FbBsrQzSooaUg9lIjIrtAer2SRXNVFDiU%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">https:\/\/github.com\/apache\/fesod<\/a><\/li>\n<li>\u300aJava\u9ad8\u6027\u80fd\u6570\u636e\u5904\u7406\u6700\u4f73\u5b9e\u8df5\u300b2026\u7248<\/li>\n<li>Apache\u8f6f\u4ef6\u57fa\u91d1\u4f1a\u5b75\u5316\u5668\u9879\u76ee\u62a5\u544a\uff082026\u5e74\u7b2c\u4e00\u5b63\u5ea6\uff09<\/li>\n<\/ol>\n<hr>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000047639921\">https:\/\/segmentfault.com\/a\/1190000047639921<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1.1 \u7b2c\u4e00\u4ee3\uff1a Apache POI\u5784\u65ad\u65f6\u4ee3\uff082001-2018\uff09 Apache POI\u4f5c\u4e3a\u6700\u65e9\u7684Java  [&hellip;]<\/p>\n","protected":false},"author":8,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-10021298","post","type-post","status-publish","format-standard","hentry","category-share"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10021298","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10021298"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10021298\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10021298"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10021298"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10021298"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}