新闻详情

新闻详情

首页 / 资讯中心 / 详情

SpringBoot集成OFDRW:实现PDF与OFD互转及SM2数字签名

发布时间:2026/10/2 15:12:06来源:尧图网络
SpringBoot集成OFDRW:实现PDF与OFD互转及SM2数字签名
1. 这次集成要解决什么问题1.1 OFD 与 PDF 的关系OFD 这个词近两年做电子档案、电子发票、电子合同相关系统的同学应该都不陌生。它是我们国家自主制定的版式文档格式对应国标 GB/T 33190文件后缀一般是.ofd。PDF 大家都很熟国际通用的版式格式但现在很多业务系统收到的票据、公文、存档文件直接就是 OFD尤其是电子发票场景OFD 几乎成了标配。问题也随之而来我的系统里存量 PDF 文件一大堆现在业务新增了 OFD 归档要求我怎么把 PDF 转成 OFD或者说我手里只有 OFD但下游系统只认 PDF怎么转回来还有一个很常见的需求OFD 作为电子凭证要具备法律效力必须做电子签名客户明确要求用国密 SM2 算法签这一步怎么落地这套需求拆开看就是三件事第一在 SpringBoot 项目里引入 ofdrw 库第二实现 PDF 和 OFD 的双向转换第三用 SM2 对 OFD 做数字签名并且能验证签名。本文就是从我实际做过的项目里把这三条链路完整地梳理出来代码可以直接抄坑我都提前帮你踩过了。1.2 为什么选择 ofdrw我当时调研过几条路。第一条是用 PDFBox 解析 PDF自己写 OFD 的 XML 结构和 ZIP 打包逻辑。这属于“从零造轮子”OFD 规范里页面描述、资源文件、扩展名、签名模块这些细节非常多光是把规范啃透就得花两周后面维护成本也高果断放弃。第二条是找商业控件功能确实全但授权费不便宜而且签名、转换这类能力往往耦合在一起我还要申请试用、走采购流程周期太长。最终选了开源的 ofdrw。它是纯 Java 实现模块划分很清楚核心、解析、布局、转换、签名都拆开了我需要哪块引哪块就行。最关键的是它原生支持国密算法族SM2 签名、SM3 摘要这些都是内置能力正好对上客户的要求。社区活跃度也还可以遇到问题基本能在 GitHub 的 issue 里找到答案。选型的时候我还确认了一点ofdrw 的转换不是简单把 PDF 页面截图塞进 OFD而是尽量把 PDF 里的文本资源提取出来重新排版成 OFD 的文本对象。这意味着转出来的文件还有一定“可编辑性”后续检索、复制文本理论上都还有救比纯图片方案强一个档次。1.3 整体实现方案的梳理我在项目里并没有把所有逻辑堆在 Controller 里而是单独拆了三个业务模块pdfOfdConverter负责 PDF 与 OFD 互转内部封装 ofdrw-converter 的能力ofdSignService负责 OFD 的 SM2 签名与验签keyStoreService负责 SM2 密钥对生成和私钥读取。这样做的原因是转换和签名这两个能力虽然都依赖 ofdrw但其实耦合度很低。转换是文档格式层面的操作签名是密码学层面的操作后续如果客户要求换成 RSA 或者 SM4 加密我只需要动签名模块不至于把转换逻辑一起带崩。整个调用链路也很直白用户上传 PDF 文件Spring 接口接收后转成 OFD存到服务器临时目录再调用签名服务完成 SM2 签署最后把签名后的 OFD 返回给前端下载。下面就从环境准备开始一段一段往下走。2. 环境准备与依赖引入2.1 基础运行环境的选择我项目里用的 SpringBoot 是 2.7.xJDK 用的是 8。这里多说一句如果你是新项目完全可以上 SpringBoot 3.x 和 JDK 17但如果你跟我一样是在维护老项目或者客户的生产环境还在用 JDK 8那么 SpringBoot 2.7 JDK 8 是比较稳妥的组合。ofdrw 本身不绑定某个 SpringBoot 版本它就是普通 Maven 依赖所以高低版本都能跑关键是别在 JDK 模块化问题上卡住比如某些旧版本 ofdrw 在 JDK 17 上可能会因为反射访问受限报错这种情况升级到新版 ofdrw 一般就解决了。操作系统方面开发机 Windows、生产机 Linux 会遇到一个典型差异字体。这个放到后面专门说因为它是 PDF 转 OFD 时最容易翻车的地方不是代码逻辑问题而是环境问题。2.2 Maven 依赖引入ofdrw 的依赖不是只有一个 jar它是分模块发布的。为了省事我直接引入聚合包ofdrw-full它会把我需要的 reader、converter、sign、layout 等模块都带进来。另外还需要引入 PDFBoxPDF 解析引擎和 BouncyCastle国密算法支持。我的 pom.xml 大致是这样的dependencies !-- SpringBoot Web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- ofdrw 全家桶 -- dependency groupIdorg.ofdrw/groupId artifactIdofdrw-full/artifactId version1.24.0/version /dependency !-- PDF 解析引擎ofdrw-converter 依赖它 -- dependency groupIdorg.apache.pdfbox/groupId artifactIdpdfbox/artifactId version2.0.27/version /dependency !-- 国密算法支持 -- dependency groupIdorg.bouncycastle/groupId artifactIdbcprov-jdk15on/artifactId version1.70/version /dependency /dependencyofdrw 的版本号一直在迭代1.24.0 是我当时用的版本。如果你用的版本更新个别 API 类名可能有调整比如PdfConverter的构造方式、签名配置项的名称要以官方文档和当前依赖实际编译结果为准。我下面所有代码示例都会基于 1.24.0 写读者对照自己版本稍微调整即可。2.3 工程目录结构我建议按功能把代码拆开不要全塞在 Controller 里面。我的目录结构是src/main/java/com/example/ofddemo/ ├── controller/ │ ├── FileConvertController.java │ └── SignController.java ├── service/ │ ├── PdfOfdConvertService.java │ ├── OfdSignService.java │ └── Sm2KeyService.java ├── config/ │ └── OfdConfig.java └── common/ └── Result.javaOfdConfig里可以定义临时目录路径、字体文件路径、默认签名图片路径等配置。把这些抽成配置的好处是生产环境和开发环境可以靠配置文件切换不用改代码。比如 Linux 服务器上字体路径可能是/usr/share/fontsWindows 上是C:/Windows/Fonts配置化之后换环境就是改一行配置文件的事。3. PDF 转 OFD核心转换链路3.1 转换原理不是截图是重排版PdfConverter背后做的事情可以理解为用 PDFBox 把 PDF 文件解析出来提取每一页的文本、图片、矩形等基础元素再通过 ofdrw 的布局引擎把这些元素在 OFD 页面上重新“画”出来。OFD 本体是一个 ZIP 包里面按规范存放OFD.xml、Document.xml、页面描述文件、资源文件等PdfConverter 自动完成这些文件的组织。所以理论上转换结果是有文本层的可以在阅读器里选中文字、搜索内容。但需要注意它毕竟是“重新排版”PDF 里如果用了非常复杂的布局、特殊字体、嵌入的矢量图转换后和原始 PDF 可能会有像素级差异。这种情况不用慌功能正常只是视觉上略有区别。还有一点如果 PDF 是扫描件里面全是图片根本没有文字那 PdfConverter 提取到的文本层就是空的它能做的就是把图片按页面区域放上去这种方式转出来的 OFD 更像“图片版”但日常业务已经够用。3.2 核心代码实现我用的是一个独立 Service 来封装转换操作import org.ofdrw.converter.pirder.PdfConverter; import java.nio.file.Path; import java.nio.file.Paths; Service public class PdfOfdConvertService { /** * PDF 转 OFD * * param pdfPath 源 PDF 文件路径 * param ofdPath 输出 OFD 文件路径 */ public void pdfToOfd(String pdfPath, String ofdPath) { Path src Paths.get(pdfPath); Path dst Paths.get(ofdPath); try (PdfConverter converter new PdfConverter(src, dst)) { converter.convert(); } catch (Exception e) { throw new RuntimeException(PDF 转 OFD 失败, e); } } }这里有个很容易忽略的细节PdfConverter实现了Closeable所以要用 try-with-resources 包起来否则文件句柄可能没被释放Windows 上多次转换后会出现文件被占用、删除失败的问题。我在第一版就踩过这个坑一直报“另一个程序正在使用此文件”排查了半天才意识到是没关闭资源。如果你需要在转换时候自定义一些行为比如设置转换时使用的字体、调整页面缩放系数、决定是否嵌入图片等可以在转换前通过PdfConverter暴露的属性配置。3.3 字体问题中文乱码的第一个坑PDF 转 OFD 之后中文全变成方块这是很多人第一次跑都会遇到的问题。原因很简单PDF 本身内置了字体信息但 PDFBox 解析出来后我们的转换过程需要把这些文字用“本地字体”在 OFD 中重新渲染。如果转换时系统找不到中文字体文字就显示不出来。ofdrw 提供了一个字体注册机制。我在 Linux 生产服务器上通常扫描/usr/share/fonts目录把系统安装的中文字体注册进去。伪代码如下import org.ofdrw.font.FontRegisterAction; FontRegisterAction.getInstance() .register(SimSun, new File(/usr/share/fonts/chinese/simsun.ttc)) .register(Microsoft YaHei, new File(/usr/share/fonts/chinese/msyh.ttc)) .register(SimHei, new File(/usr/share/fonts/chinese/simhei.ttf)) .register(KaiTi, new File(/usr/share/fonts/chinese/simkai.ttf));但要注意字体版权问题simsun.ttc、msyh.ttc这些微软字体不能随便放到商业服务器上。更稳的做法是使用可商用的开源中文字体比如思源宋体、思源黑体在启动时注册到系统字体目录并把字体路径写入配置文件ofd: fonts: - /data/fonts/SourceHanSansSC-Regular.otf - /data/fonts/SourceHanSerifSC-Regular.otf然后在应用启动时遍历配置路径逐项注册。这样做的好处是以后要加字体只需要往目录里丢文件、改配置不需要重新编译。3.4 把转换能力封装成 Spring 接口真正到业务里不可能直接在本地跑 main 方法。我封装了一个 Controller接收前端上传的文件转换完成后给前端返回下载链接RestController RequestMapping(/api/ofd) public class FileConvertController { Autowired private PdfOfdConvertService convertService; PostMapping(/convert/pdf2ofd) public ResultString pdfToOfd(RequestParam(file) MultipartFile file) throws IOException { // 1. 保存上传文件到临时目录 String tmpDir System.getProperty(java.io.tmpdir); String pdfFileName UUID.randomUUID() .pdf; String ofdFileName UUID.randomUUID() .ofd; Path pdfPath Paths.get(tmpDir, pdfFileName); Path ofdPath Paths.get(tmpDir, ofdFileName); file.transferTo(pdfPath.toFile()); // 2. 调用转换服务 convertService.pdfToOfd(pdfPath.toString(), ofdPath.toString()); // 3. 返回下载地址这里需要自己处理文件下载接口 // 或者直接把文件流写回 Response return Result.success(/api/ofd/download/ ofdFileName); } }临时文件一定要记得清理。我是在下载接口里下载完毕后用Files.deleteIfExists删除或者用定时任务清理超过一定时间的临时文件。如果不管它生产环境跑几天磁盘就满了。还有一个并发问题FontRegisterAction注册字体是全局操作如果项目部署了多实例且每台机器的字体目录不同需要保证每台机器的配置一致。更好的方式是把字体打包进应用内通过 classpath 加载这样多实例就没差异了。4. OFD 转 PDF 与页面渲染4.1 OFD 文件读取与页面渲染OFD 转 PDF 之前我习惯先确认 OFD 本身能不能正常打开、里面有几页。OFDReader是解析入口import org.ofdrw.reader.OFDReader; import java.nio.file.Paths; public int getPageCount(String ofdPath) throws IOException { try (OFDReader reader new OFDReader(Paths.get(ofdPath))) { return reader.getNumberOfPages(); } }利用OFDReader还可以实现“把 OFD 某一页渲染成图片”的能力这在网页预览场景里非常实用。比如 ERP 系统里用户想看 OFD 发票的缩略图不需要前端安装阅读器后端渲染一张 PNG 给前端显示就行import org.ofdrw.reader.OFDReader; import org.ofdrw.reader.ResourceLocator; import javax.imageio.ImageIO; public void renderPageToPng(String ofdPath, int pageIndex, String outputPng) throws Exception { try (OFDReader reader new OFDReader(Paths.get(ofdPath))) { // 使用渲染器把页面绘制到 BufferedImage // ofdrw 提供了 PageRender / ImageMaker 等组件具体类名随版本略有差异 // 大体逻辑是拿到该页的页面对象设置渲染 DPI然后绘制输出 // 下面是一个等价示意 // PageRender render new PageRender(reader, resourceLocator); // BufferedImage image render.render(pageIndex, 2.0); // ImageIO.write(image, png, new File(outputPng)); } }不同版本的类名有差异但核心思路一样通过 reader 拿到页面描述按 DPI 缩放渲染成位图。DPI 一般设 120 到 150 就够浏览器清晰展示太大的话内存占用会成倍上升。4.2 OFD 转 PDF 的实现OFD 转 PDF 可以直接用OFDConverter。核心代码比 PDF 转 OFD 还短import org.ofdrw.converter.OFDConverter; import java.nio.file.Paths; public void ofdToPdf(String ofdPath, String pdfPath) { try { OFDConverter converter new OFDConverter(Paths.get(ofdPath)); converter.convert(Paths.get(pdfPath)); } catch (Exception e) { throw new RuntimeException(OFD 转 PDF 失败, e); } }需要注意OFD 转 PDF 的转换质量取决于 OFD 文件本身的规范程度。正常生成器产生的 OFD 转出来问题不大但市面上有些工具生成的 OFD 不规范比如资源引用路径写错、缺少字体信息转换时可能渲染出空白页。所以我在转换前都会先用OFDReader试读一遍确认文件结构正常再进入转换逻辑。4.3 实际场景与效果评估我这套代码落地后主要支撑了两个场景第一个是文档归集系统。客户下有 PDF 又有 OFD统一入库前都要转成 OFD 归档方便统一用一套阅读器和管理工具。PDF 转 OFD 每天大概跑几千份单文件平均耗时在 1 到 3 秒之间主要是 PDF 文件大小和页面数影响。第二个是报表分发。业务系统里生成的是 OFD 报表但客户的下游供应商系统只支持 PDF 预览于是 OFD 转 PDF 接口就承担了对外分发的能力转换次数不多但每次都要保证高保真。从效果上看文本类、表格类文档转换质量很高基本看不出来是转过的。但设计类 PDF比如带渐变背景、复杂矢量插图的宣传册转换后会有一定的偏差这在项目启动前要和业务方对齐预期别等上线了再扯皮。5. SM2 签署 OFD从密钥到签名5.1 OFD 签名机制拆解OFD 签名这件事搞明白它到底签的是什么比会写代码更重要。OFD 文件本质上是一个 ZIP 包里面有OFD.xml描述文档本身Document.xml描述页面内容还有字体、图片等资源文件。如果这些文件被篡改包的内容就变了签名自然失效。SM2 签名的作用就是对 OFD 包里的关键文件做“完整性保护”。流程大致是把 OFD 包内需要保护的文件取出来分别计算摘要值摘要算法一般用 SM3把摘要和签名者的信息、签名时间等一起打包成签名数据用 SM2 私钥对摘要做签名把签名结果和签名描述文件写回 OFD 包里放到专门的 signatures 目录。用生活化的比喻SM3 是给文件内容生成一个“指纹”SM2 是给这个指纹盖一个“私章”别人只要有你的公钥就能验证私章是不是真的。SM2 本身是国密的椭圆曲线非对称算法性能不算快但很安全在政企场景里是硬性要求。5.2 SM2 密钥对的生成签名之前必须有 SM2 密钥对。我在项目里用的 Hutool 的SmUtil来生成也可以用 BouncyCastle 直接生成。两种方式都贴一下。第一Hutool 方式import cn.hutool.crypto.SmUtil; import cn.hutool.crypto.asymmetric.SM2; // 生成新的随机密钥对 SM2 sm2 SmUtil.sm2(); byte[] privateKey sm2.getD(); // 私钥 byte[] publicKey sm2.getQ(); // 公钥第二原生 BouncyCastle 方式import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.Security; import java.security.spec.ECGenParameterSpec; static { if (Security.getProvider(BC) null) { Security.addProvider(new BouncyCastleProvider()); } } public KeyPair generateSm2KeyPair() throws Exception { KeyPairGenerator kpg KeyPairGenerator.getInstance(EC, BC); ECGenParameterSpec sm2Spec new ECGenParameterSpec(sm2p256v1); kpg.initialize(sm2Spec); return kpg.generateKeyPair(); }生产环境里密钥对一般不会动态生成而是由专门的密钥管理系统保管或者由密码机签发。我这里生成密钥对的目的其实有两个本地开发调试以及给没有 CA 证书的场景提供一对自签密钥完成基本签名链路。密钥的存储方式建议不要明文写在配置里至少做一层 Base64 编码或者加密存储。如果是正式项目一定要对接公司的密钥管理服务。5.3 对 OFD 执行 SM2 签署基于 ofdrw-sign 模块签署流程分三步准备签名者信息、准备签名图片、执行签名。签名图片就是那个红色的“电子印章”圆形图章一般要求是透明背景 PNG。ofdrw 会把印章图片按你指定的位置叠加到 OFD 页面上然后对整页内容和签名信息做签名。下面是核心代码import org.ofdrw.reader.OFDReader; import org.ofdrw.sign.OFDSigner; import org.ofdrw.sign.signature.SignatureConfig; import org.ofdrw.sign.signature.SignatureId; import java.nio.file.Paths; import java.util.Date; public void signOfdWithSm2(String srcOfd, String signedOfd, String sealImgPath, String privateKeyHex) throws Exception { // 1. 读取原始 OFD OFDReader reader new OFDReader(Paths.get(srcOfd)); // 2. 创建签名器指定输出文件 OFDSigner signer new OFDSigner(reader, Paths.get(signedOfd)); // 3. 构造签名配置 SignatureConfig config new SignatureConfig(); config.setUserName(张三); // 签名人姓名 config.setSignatureId(new SignatureId(SIGN_ID_ System.currentTimeMillis())); config.setSignTime(new Date()); // 签名时间 config.setSignatureAlgorithm(SM2); // 签名算法 config.setDigestAlgorithm(SM3); // 摘要算法 config.setPrivateKey(hexToBytes(privateKeyHex)); // SM2 私钥 config.setSignImagePath(Paths.get(sealImgPath)); // 印章图片 config.setPageRange(1); // 在第 1 页显示签章 config.setSignaturePos(120.0, 120.0, 100, 100); // 印章位置与大小 signer.setSignatureConfig(config); signer.sign(); // 执行签名 signer.close(); reader.close(); }这段代码里几个容易写错的地方SignatureId要保证唯一如果你在同一个 OFD 上追加多个签名ID 重复会导致验签工具无法区分两个签名。我习惯用时间戳拼一个随机串。setPageRange指定签章显示到哪一页setSignaturePos是签章区域的位置。如果位置坐标算不准签章会跑到页面外面去。这个只能靠调试可以先渲染出没有签章的 OFD 的页面图片量一下想要放置印章的坐标再填进去。签名算法和摘要算法别混了。SM2 是签名算法SM3 是摘要算法两者搭配使用是国密签名最标准的组合。如果你把摘要算法写成 SM2签名时会直接报错。5.4 签名验证确保签名真的有效签名完成不是结束必须验证一次。ofdrw 的验签代码大概是这样import org.ofdrw.sign.verify.OFDVerify; public boolean verifySignedOfd(String signedOfd) throws Exception { OFDVerify verify new OFDVerify(); boolean result verify.doVerify(Paths.get(signedOfd)); verify.close(); return result; }要注意验签结果“通过”只代表签名数据和文件内容匹配、文件自生成后没有被篡改并不等于签名人的身份可信。要确认“签名的人确实是他”还需要把公钥证书纳入验证体系。我项目里后续接入 CA 证书后验签逻辑会先验证证书是否由可信 CA 签发再验证签名值。如果你没有证书体系只能达到“完整性验证”这个级别这个边界要对业务方说清楚。实际业务中客户给的测试样例经常会包含两个 OFD一个原始未签名文件一个签名后文件。对比查看时你会发现这两个文件大小不一样签名后的明显变大因为 OFD 包里增加了签名描述文件和对应的签名模块。6. 常见问题与避坑指南6.1 问题排查速查表我做这个项目时踩过不少坑下面用表格整理一下最容易遇到的几类问题现象根本原因解决方案PDF 转 OFD 后中文全是方块服务器缺少可注册的中文字体安装开源中文字体并注册到 FontRegisterAction转换过程中报文件被占用未正确关闭 PdfConverter / OFDReader全程使用 try-with-resources 或 finally 中 close转大文件时内存溢出默认堆内存不足或 PDF 图片过多调大 JVM 内存分页处理必要时临时转成低分辨率图片OFD 转 PDF 后页面空白OFD 源文件本身不规范资源缺失先 OFDReader 试读检查原始文件是否损坏签名后 OFD 打不开签名时 OFD 文件被其他线程修改或签名信息不完整确认无误后再签名避免并发写同一文件验签失败私钥与验签公钥不一致或签名过程中文件被篡改核对公私钥对应关系确保签名时文件干净印章图片没有显示签章坐标越界或图片格式不是透明 PNG调整 setSignaturePos 坐标检查图片格式6.2 工程化落地时的几个建议除了查表修问题我强烈建议把三件事做在前面能省掉后面一半的麻烦。第一统一文件存储。转换前后的文件都走统一的存储接口不要直接散落在系统临时目录里。我后来把文件存储切换到 MinIOSpringBoot 里只需要把 service 的读写方法改成调用 MinIO 的 SDK 就行。这样不管是本地上传、还是后续做文件管理、分布式部署都不用改核心转换逻辑。第二做好任务异步化。PDF 转 OFD 和 OFD 签名都是相对耗时的 IO 操作如果请求量大同步接口很容易把 Tomcat 线程池打满。建议用线程池或者消息队列把转换任务异步化前端先拿到“处理中”状态完了再回调通知。我当时因为时间紧没做异步后来高峰期接口响应时间飙到几十秒才回头改的。第三版本锁定。ofdrw 的 API 迭代比较快升级版本前一定要看 release notes把转换和签名的回归用例都跑一遍。我遇到过一次从 1.17 升到 1.24PdfConverter的包名变了全项目所有 import 都得改还好当时及时做了排查不然后果很酸爽。最后再分享一个小技巧如果你的生产环境上没法轻易装中文字体可以把字体文件放到项目的resources/fonts目录然后在应用启动时通过 classpath 路径加载并注册。这样构建出来的 jar 包自带字体不管部署到哪台机器都能保证转换效果一致这个方案我目前在多个项目里用下来都很稳。以上内容为个人实际项目中的经验总结具体 API 名称以所选 ofdrw 版本为准。如果你也在整合 PDF、OFD 转换和国密签名链路希望这篇记录能帮你少走几步弯路。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

双室平衡容器原理与工业汽包水位精准测量 2026/10/2 19:22:58

双室平衡容器原理与工业汽包水位精准测量

1. 什么是双室平衡容器:工业液位测量里那个“不说话但特别靠谱”的老伙计双室平衡容器,这名字听起来像某种实验室里的精密玻璃器皿,其实它压根儿不玻璃,也不娇气,而是锅炉房、化工厂、热电厂这些地方常年蹲守在汽包水位…

阅读更多 →
条件概率从直觉到应用:P(A|B)、P(AB)、P(B)关系精讲 2026/10/2 19:22:58

条件概率从直觉到应用:P(A|B)、P(AB)、P(B)关系精讲

1. 条件概率到底在解决什么问题很多人第一次接触条件概率的时候,公式背得滚瓜烂熟,一遇到具体题目就懵。我自己当年学这块内容也是同样的感受——P(A|B) 这个符号看起来简单,但真要解释清楚它和 P(AB)、P(B) 之间的关系,不少人脑子…

阅读更多 →
Jev 模型如何让 Agent 开发提速:TypeSafe AI 与并发实战 2026/10/2 19:22:57

Jev 模型如何让 Agent 开发提速:TypeSafe AI 与并发实战

1. 从 Jev 的爆火说起:Agent 开发到底卡在哪 最近技术圈里聊得最多的一个词就是 Jev。不管是在做 AI Agent 的群里,还是在各种开发者社区,到处都能看到有人在问 Jev 模型怎么申请、Jev 本地部署怎么做、Jev 在 Codex 里怎么用。我身边好几个做…

阅读更多 →
工厂车间无线覆盖项目方案:勘测、AP选型与验收避坑指南 2026/10/2 19:22:57

工厂车间无线覆盖项目方案:勘测、AP选型与验收避坑指南

简介:工厂车间无线覆盖项目方案是一份面向网络工程师、IT项目人员和企业信息化管理者的完整设计方案,针对车间跨距大、扫码移动终端难以稳定接入的痛点,规划了覆盖三个车间的WLAN无线网络。压缩包包含1个docx格式文档,整体约240KB…

阅读更多 →
Linux中文字体显示异常的根源与fontconfig深度配置 2026/10/2 19:22:57

Linux中文字体显示异常的根源与fontconfig深度配置

1. 项目概述:为什么Linux终端和GUI界面总显示方块?这根本不是“字体缺失”那么简单你刚装好CentOS、Ubuntu或者Debian,打开终端敲ls,一切正常;可一运行vim编辑中文文件,或者用gedit打开一个带中文的txt&…

阅读更多 →
Java实现双色球大乐透随机选号:从抽样算法到工具类封装 2026/10/2 19:22:50

Java实现双色球大乐透随机选号:从抽样算法到工具类封装

很多 Java 初学者都有这个困惑:单看数组、集合、循环、异常都懂,但真要独立写一个像样的项目,就不知道从哪里下手。我一直推荐一个被低估的练手项目——双色球&大乐透随机选号生成器。它规则清晰、边界明确,却能自然牵扯出随机…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉