SpringBoot 3.x嵌入式容器调优与SSL证书自动热更新实战
2026 年了如果你还在用“改配置 - 重启应用 - 半夜被叫起来”这套流程处理证书过期问题那真的有必要看看这章内容。SpringBoot 3.x 的嵌入式容器早就不是当年那个“帮你省个 Tomcat 安装”的毛坯房了尤其在 HTTPS 证书管理这件事上完全能实现“证书到期自动换、服务全程不重启”。这篇文章我会从两个大的方向拆开揉碎讲清楚一是嵌入式容器在 SpringBoot 3.x 里到底有哪些值得调优的旋钮二是如何利用 SpringBoot 3.x 的证书管理机制把 SSL 证书的加载、更新、切换做成一个完全自动化的闭环顺便把过程中容易踩的坑全部列出来。1. 项目概述与核心痛点拆解先把这个场景捋清楚。标题里问的是“2026 年了你还在为证书到期重启服务器头疼”——这句话看似调侃实际上戳中了很多团队的运维痛点。一年前我接手过一个内部系统的维护证书有效期三个月每次到期前一周就得发邮件提醒然后挑个凌晨低峰期改 keystore 文件、重启服务、验证端口全程十五分钟起步。这个流程的问题不只是麻烦更在于它藏着一个巨大的风险重启窗口。如果你管理的服务链路很长前端有负载均衡、网关、网关后面还有一堆业务实例每个实例都要单独更新证书并重启那每次证书轮换就是一次小型的发布演练。更别提某些实例的 JVM 启动时间达到几十秒甚至几分钟在高并发场景下重启导致的流量抖动是实打实的损失。1.1 问题的本质证书加载与容器生命周期耦合为什么传统方案里换证书必须重启因为在 SpringBoot 2.x 以及更早的版本中SSL 证书是在容器启动阶段一次性加载进 JVM 的。Tomcat 在初始化 Connector 的时候读取 keystore 文件并创建 SSLContext 对象而 Java 的 SSLContext 一旦初始化完成内部持有的密钥和信任链就固定下来了。所以问题的本质是你希望证书更新这件事不要绑定容器的启动过程但旧架构里这两者强耦合。2026 年的今天SpringBoot 3.x 已经提供了一套跟以前完全不同的解决思路但很多开发者还停留在“SSL 配置就是写几个 server.ssl.* 属性”的认知阶段自然不知道还有更优雅的玩法。1.2 SpringBoot 3.x 给出的新玩法SpringBoot 3.x 最关键的改动之一是引入了SSL Bundle的概念。官方文档上把它定义为“一组可复用的 SSL 配置材料”简单理解就是把证书、私钥、信任库打包成一个统一的抽象应用程序和容器都可以通过这个抽象来加载 SSL 信息。这个抽象的价值在于它支持运行时动态刷新。只要你的 Bundle 实现在证书变化时能返回新的 SSLContextTomcat 的 Connector 就能在不重启 JVM 的情况下切换到新证书。由此证书轮换从“重启发布”变成了“文件落地自动生效”整个过程对用户无感对业务无干扰。这就引出了本文的两个核心主题第一SpringBoot 3.x 嵌入式容器的性能与连接优化第二面向自动化运维的 SSL 证书热更新方案。2. 嵌入式容器的选型与核心参数优化SpringBoot 3.x 默认使用 Tomcat 作为嵌入式容器同时支持切换 Jetty 和 Undertow。从我的实践经验来看绝大多数业务系统用默认的 Tomcat 就已经够用切换容器带来的收益往往被改造成本和踩坑成本抵消。与其纠结换容器不如把默认容器吃透。2.1 Tomcat 线程模型与现代硬件的匹配Tomcat 的线程模型是基于 BIO/NIO 的事件驱动模型在 SpringBoot 3.x 中默认使用 NIO。所谓 NIO简单类比就是餐厅服务员不再一对一地盯着每一个顾客线程而是同时观察所有顾客的行动谁挥手需要服务他就过去处理一下。这个模型在现代机器上CPU 普遍 8 核以上、内存 16G 以上的配置空间非常大。我见过不少项目上线前根本没调过线程池参数全部走默认值结果在流量峰值来临的时候线程池迅速被占满请求开始在 accept 队列里排队响应时间直线飙升。2.2 线程池参数的动态计算与最佳实践先看一组我常用的配置参考server: tomcat: threads: max: 400 min-spare: 20 max-connections: 10000 accept-count: 200 connection-timeout: 20000这几个参数的含义和调优思路拆解如下threads.max控制最大工作线程数。经典的经验公式是 CPU 核心数 × 2 1但这只适用于纯计算型任务。对于大多数 IO 密集型的 Web 应用数据库查询、外部 API 调用、磁盘读写线程池可以适当放大。以 8 核 CPU 的机器为例300500 是一个比较安全的区间。超过 500 后就不要再加了太多线程反而会导致 CPU 频繁切换上下文吞吐量不升反降。threads.min-spare是常驻空闲线程数可以理解成服务员的最低排班量。设太低会导致流量骤增时线程创建延迟设太高则浪费内存。2050 之间是实践中折中的选择。max-connections与accept-count需要一起看。前者是连接器同时接受的 TCP 连接数上限后者是连接排队等待的队列长度。这就像餐厅的等位区max-connections 是店内能坐下的桌数accept-count 是门口排队等候的凳子数。队列排满了以后再来的人直接进不去连接被拒绝。这两个值的搭配逻辑是“容器能处理的数量 缓冲区数量”一般 max-connections 设置在预期最高并发数的 1.5 倍左右accept-count 在 100500 之间视业务容忍度调整。2.3 启用 HTTP/2 与响应压缩白捡的性能提升SpringBoot 3.x 支持在 HTTPS 协议上启用 HTTP/2不需要额外引入依赖只需要一个开关server: http2: enabled: trueHTTP/2 带来的核心提升是多路复用同一个 TCP 连接上可以并发传输多个请求解决了 HTTP/1.1 的连接队头阻塞问题。如果你的前端页面引用了大量静态资源这个开关能显著减少页面加载的总耗时。另一个低成本的优化是响应体压缩。SpringBoot 内置了压缩过滤器配置范例如下server: compression: enabled: true min-response-size: 1024 mime-types: application/json, application/xml, text/html, text/plain注意min-response-size的含义响应体小于 1KB 时不压缩避免对过小的响应做压缩反而消耗 CPU。在生产环境我遇到过一种情况开了压缩之后JSON 接口的响应时间反而变慢了排查发现是响应体本身就几十字节压缩和解压的开销远大于传输节省的时间所以这个阈值设置很重要。2.4 连接超时与 KeepAlive 的取舍connection-timeout指的是等待接收 HTTP 请求的超时时间默认 60 秒。如果你的服务端主要处理浏览器请求建议把这个值下调到 20 秒因为现代浏览器很少会保持一个空闲 TCP 连接超过 20 秒不发送请求设置太长只会白白占用连接名额。关于 KeepAlive 的底层参数SpringBoot 暴露的配置项有限如果需要微调需要自定义TomcatConnectorCustomizer。我在生产环境中用过的方法是通过实现这个接口来调整 keepAliveTimeout这属于深水区的操作普通场景用默认值足够了。3. SSL 证书自动化更新从原理到方案现在进入重头戏。先铺垫一下为什么之前 SSL 证书不能用“改文件”的方式直接生效再讲 SpringBoot 3.x 为什么能做到这个问题。3.1 传统 SSL 配置的致命伤在 2.x 时代配置 SSL 大概长这样server: port: 8443 ssl: key-store: classpath:keystore.p12 key-store-password: changeit key-store-type: PKCS12这段配置在 SpringBoot 应用启动时会被AbstractSslContextBuilder读取构建出一个SslContext。这个 SslContext 一旦放入 Tomcat 的连接器除非重启整个连接器也就是重启应用否则不会重新加载。这就产生了一个运维上的死结证书到期后你必须重启。哪怕你用自动化脚本去 renew 证书、替换 keystore 文件应用本身不自知只有重启才能触发它重新读取文件。3.2 SSL BundleSpringBoot 3.x 的解决方案SpringBoot 3.x 引入的SslBundle是一个接口它描述了存储在应用中的 SSL 材料证书、私钥、信任库并提供了获取这些材料的方法。为了让容器能够使用这个 Bundle需要把它注册到SslBundles注册中心。在 SpringBoot 启动过程中Tomcat 的自动配置会检查注册中心里的server.ssl.bundle属性指定名称的 Bundle然后通过这个 Bundle 构建SSLHostConfig最终用于创建 SSLContext。这个流程与 2.x 最大的区别是Bundle 本身是可以替换的。你可以在运行期向注册中心注册一个新的 Bundle 实例或者让你已有的 Bundle 内部逻辑动态返回不同的 SSLContext。更令人振奋的是Tomcat 在每次建立新 SSL 连接时都会从当前的 SSLContext 获取参数。只要我们把 Bundle 指向的 SSLContext 换了新连接会立刻使用新证书已建立的旧连接则继续沿用旧证书直到会话结束。这个特性就是无重启更新证书的底层支撑。3.3 方案设计ACME 自动续期 应用层热刷新结合当前主流的运维实践完整方案可以拆成三层第一层证书自动获取与续期。使用 ACME 协议的客户端以公益性的 Lets Encrypt 服务为代表定期自动为你的域名续期证书证书文件落盘到指定目录。整个过程中不需要人工干预。第二层静态文件监控触发。SpringBoot 应用内部启动一个定时任务每隔一段时间或者使用文件监控 API 检查证书文件是否存在变更比对文件的修改时间戳或内容哈希。第三层动态刷新 SSLContext。检测到证书文件变化后重新加载 KeyStore构建新的 SSLContext把它封装进一个新的 Bundle替换掉注册中心里原有的 Bundle。新的 SSL 连接立刻切换到新证书。这就是一个从证书获取、自动续期、应用热加载的完整闭环。你只需要第一次部署时处理一次之后证书接近到期时全部自动完成不再有重启窗口。4. 实操环节完整实现无重启 SSL 热更新纸上谈兵没有意义这一节我在本地环境完整跑过一遍按照下面的顺序带你实现。我用的开发环境是 SpringBoot 3.2.5、JDK 17理论上 3.x 全系列通用。4.1 第一步准备证书文件与基础配置本地测试直接生成自签名证书即可。需要分别生成一个旧的 keyStore 和一个新的 keyStore用于模拟“证书到期更新”的场景。# 生成旧证书有效期 1 天 keytool -genkeypair -alias server -keyalg RSA -keysize 2048 \ -storetype PKCS12 -keystore server-old.p12 \ -storepass changeit -validity 1 # 生成新证书有效期 1 天模拟更新后的证书 keytool -genkeypair -alias server -keyalg RSA -keysize 2048 \ -storetype PKCS12 -keystore server-new.p12 \ -storepass changeit -validity 1keytool是 JDK 自带命令生成的是 PKCS12 格式的 keystore 文件SpringBoot 原生支持这种格式。实际生产环境建议直接用 PEM 格式证书加上私钥减少格式转换环节。基础的 application.yml 配置如下server: port: 8443 ssl: bundle: server tomcat: threads: max: 200 min-spare: 10这里只指定了 bundle 的名称具体的证书信息后续通过代码动态注入。4.2 第二步自定义 SslBundle 实现类核心逻辑都在这个类里。我们要实现SslBundle接口同时内部维护一个委托对象。当证书刷新时我们重新构建委托对象从而让getManagers()等接口返回新的 SSL 管理器。import org.springframework.boot.ssl.SslBundle; import org.springframework.boot.ssl.SslManagerBundle; import org.springframework.boot.ssl.SslStoreBundle; public class ReloadableSslBundle implements SslBundle { private final Object lock new Object(); private volatile SslBundle delegate; public ReloadableSslBundle(KeyStore keyStore, char[] keyPassword) throws Exception { this.delegate createBundle(keyStore, keyPassword); } private SslBundle createBundle(KeyStore keyStore, char[] keyPassword) throws Exception { SslStoreBundle stores new SslStoreBundle() { Override public KeyStore getKeyStore() { return keyStore; } Override public KeyStore getTrustStore() { return null; } }; SslManagerBundle managers SslManagerBundle.from( keyStore, keyPassword, (KeyStore) null ); return new SimpleSslBundle(stores, managers, TLS); } public void refresh(KeyStore newKeyStore, char[] keyPassword) throws Exception { SslBundle newBundle createBundle(newKeyStore, keyPassword); synchronized (lock) { this.delegate newBundle; } } Override public String getProtocol() { return delegate.getProtocol(); } Override public SslStoreBundle getStores() { return delegate.getStores(); } Override public SslManagerBundle getManagers() { return delegate.getManagers(); } }注意rel上的volatile关键字它保证了在多线程环境下读取字段时能立刻看到最新值。Tomcat 建立新连接时会调用getManagers()而这个调用正好发生在volatile字段的读路径上所以一旦我们替换了delegate下次新连接就会使用新证书。4.3 第三步注册 Bundle 到 SpringBoot 容器要让 SpringBoot 在启动时识别这个自定义 Bundle需要实现SslBundleRegistrar。import org.springframework.boot.ssl.SslBundleRegistrar; import org.springframework.boot.ssl.SslBundles; import org.springframework.context.annotation.Configuration; Configuration public class SslBundleConfig implements SslBundleRegistrar { private final ReloadableSslBundle bundle; public SslBundleConfig(ReloadableSslBundle bundle) { this.bundle bundle; } Override public void registerBundles(SslBundles sslBundles) { sslBundles.registerBundle(server, bundle); } }同时把ReloadableSslBundle声明为一个 Spring Bean方便后续定时刷新任务直接调用它。Bean public ReloadableSslBundle reloadableSslBundle() throws Exception { KeyStore ks loadKeyStore(server-old.p12, changeit); return new ReloadableSslBundle(ks, changeit.toCharArray()); } private KeyStore loadKeyStore(String path, String password) throws Exception { InputStream inputStream getClass().getClassLoader().getResourceAsStream(path); KeyStore keyStore KeyStore.getInstance(PKCS12); keyStore.load(inputStream, password.toCharArray()); return keyStore; }到这一步SpringBoot 应用启动时Tomcat 连接器会从注册中心获取名为server的 Bundle。由于这个 Bundle 是自定义的连接器拿到的证书就是我们在构造函数里加载的那份。4.4 第四步定时检查证书文件变化并刷新这是最关键的一步让应用在运行期检测到磁盘上的证书文件变化然后自动刷新 SSLContext。我用一个简单的轮询任务来演示每隔 30 秒检查一次文件哈希import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.util.DigestUtils; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; Component public class SslCertificateRefreshTask { private static final Path KEYSTORE_PATH Paths.get(server-new.p12); private static final String KEYSTORE_PASSWORD changeit; private final ReloadableSslBundle sslBundle; private String lastHash ; public SslCertificateRefreshTask(ReloadableSslBundle sslBundle) { this.sslBundle sslBundle; } Scheduled(fixedDelay 30000) public void checkAndRefreshCertificate() throws Exception { byte[] content Files.readAllBytes(KEYSTORE_PATH); String currentHash DigestUtils.md5DigestAsHex(content); if (lastHash.isEmpty()) { lastHash currentHash; return; } if (!lastHash.equals(currentHash)) { KeyStore newKeyStore KeyStore.getInstance(PKCS12); newKeyStore.load(new ByteArrayInputStream(content), KEYSTORE_PASSWORD.toCharArray()); sslBundle.refresh(newKeyStore, KEYSTORE_PASSWORD.toCharArray()); lastHash currentHash; System.out.println(SSL 证书已热更新新证书将于下一个新连接生效); } } }这段代码的逻辑里有一个地方值得强调只有检测到哈希值发生变化才触发refresh方法。如果证书文件没变频繁刷新不仅浪费资源还可能导致 Tomcat 从新 TLS 握手里拿到相同的内容增加无谓的重计算开销。4.5 第五步启动应用并验证热更新效果启动应用后先用curl看一下当前的证书信息curl -kIv https://localhost:8443 21 | grep subject:你会看到证书的 subject 是旧证书的信息。然后手动把server-new.p12复制到监控路径下这里为了演示可以直接把两个文件做一次内容替换过 30 秒后再执行同一条命令cp server-new.p12 server-current.p12这时再看 curl 输出会发现 subject 已经变成了新证书的信息而整个过程中应用完全没有重启端口没有中断已经建立的 TCP 连接也没有断开。这背后的机制解释一下Tomcat 在处理新 TLS 连接时会调用SSLUtil.getSslContext()来获取当前的 SSLContext。因为我们的SslBundle是动态可变的每次调用getManagers()返回的是最新的 KeyManager 数组所以新连接自动就用了新证书。4.6 实操过程中的完整配置清单为了让你生产环境直接用我把整个方案涉及的配置整理成一个表格环节配置/代码位置说明基础 SSL 属性server.ssl.bundle: server指定使用注册中心里名为 server 的 Bundle自定义 BundleReloadableSslBundle类实现 SslBundle 接口内部维护可替换的委托对象Bundle 注册SslBundleConfig类把自定义 Bundle 注册到注册中心供 Tomcat 引用定时刷新任务SslCertificateRefreshTask类轮询证书文件哈希变更时触发刷新证书文件落盘服务器的固定目录由 ACME 客户端自动更新 PEM/P12 文件启动作业EnableSchedulingBean开启 Spring 定时任务并初始化 Bundle这个方案之所以实用是因为它把所有变更全部收敛到配置文件和定时任务代码里你只需要保证两点第一证书文件落盘到固定的路径第二SpringBoot 应用能读到这个路径并有权访问。之后每一次证书到期应用都会自己完成换证动作。5. 常见问题与排查技巧实录任何方案在落地过程中都会碰到五花八门的问题这里挑几个我在实际部署中遇到的典型案例给你做个参考。5.1 Tomcat 启动时报信任库密码错误现象应用启动失败日志提示“java.io.IOException: Keystore was tampered with, or password was incorrect”。排查这个错误大概率是自定义 Bundle 初始化时读文件用的密码写错了。注意keytool生成 p12 时的-storepass参数以及代码里的load(inputStream, password.toCharArray())参数必须一致。另外还需要确认 KeyStore 类型。如果你的文件是 JKS 格式代码里的KeyStore.getInstance(JKS)就不能写成 PKCS12否则读取必然失败。5.2 热更新以后新连接迟迟不生效现象日志打印了“SSL 证书已热更新”但 curl 查看证书信息还是旧的。排查这个问题通常出在 Bundle 被替换的可见性上。你需要在刷新方法体里确认两点第一delegate字段是否用volatile修饰第二刷新任务是否真的替换了 keyStore 的内容而不是仅仅更改了某个没有实际意义的字段。更隐蔽的原因是Tomcat 可能有自己的 SSLContext 缓存策略。在某些版本中Connector 启动后不会每次都从 Bundle 获取 SSLContext而是使用已经构建好的缓存。遇到这种情况你可以通过自定义TomcatConnectorCustomizer来强制在证书刷新后重新读取 SSLHostConfig。具体做法是在刷新任务里拿到 Connector 的引用重置对应的 SSLHostConfig再调用connector.getProtocolHandler().restart()或者设置sslHostConfig.setSslContext()直接更新内存中的 SSLContext 对象。这个操作比替换 Bundle 更底层也是更直接的兜底方案。5.3 证书文件被 ACL 客户端替换后权限不对现象ACME 客户端每次续期后生成的新证书文件SpringBoot 应用读取时报“Permission denied”。排查这是 Linux 服务器上很常见的坑。ACME 客户端如某开源客户端默认以 root 权限运行生成文件的权限可能是600 root:root而应用以普通用户的身份运行自然没有权限读取。解决办法有两个方向一种是在文件落盘后通过自动化脚本执行chown或chmod调整文件权限另一种是让应用以 root 身份运行不推荐除非你能接受安全风险。我的建议是配置 ACME 客户端的 hooks在证书更新完成后执行一条chmod 644命令。5.4 常见问题速查表问题可能原因解决思路启动时 KeyStore 解析失败文件格式不对或密码错误检查 KeyStore 类型与密码使用 keytool -list 验证文件可用热更新后 HTTPS 握手仍用旧证书SSLContext 缓存未清除确保 volatile 可见性并完成 SSLHostConfig 重置证书文件权限不足文件属主与运行用户不一致在文件更新 hooks 中设置可读权限证书更换后部分浏览器报警链不完整证书链缺中间证书检查 Bundle 的 trustStore 配置补齐中间证书定时任务频繁触发刷新文件内容始终在变化检查是否在同一个文件上重复写入比较哈希值后确认再刷新6. 生产环境落地建议与最佳实践方案跑通了接下来要思考的是怎么在生产环境把它打磨得更加稳定。第一点不要把证书文件放在 classpath 里。开发环境下用 classpath 图省事还能忍受但生产环境要确保证书文件落盘到约定的目录并且这个目录不在应用发布的 jar/war 包里。否则每次发版都会导致证书被覆盖或者被重置引出一个本不该存在的“证书回退”问题。第二点引入中间证书链。我见过很多团队在自签名证书或测试环境里不配置中间证书生产环境直接用公开 CA 签发的证书。这里提醒一句公开 CA 签发的证书链往往包含两到三层如果只配置最底层的叶子证书部分客户端特别是老版本浏览器会报“证书链不完整”。在 SSL Bundle 的实现里除了加载 keyStore还需要把 CA 链的中间证书塞进 trustStore 或 keyStore 的对应别名下。第三点监控与告警一个都不能少。即便有了自动续期和热更新机制你仍然需要有一个监控项去观察证书的实际过期时间。比如每分钟自动执行一次openssl s_client -connect host:port解析返回的证书有效期如果距离到期不足 14 天就触发告警。这样一来就算 ACME 续期失败或者热更新任务失效你也能第一时间发现而不是等到用户报障。第四点集群部署场景要对定时任务做唯一性控制。如果你的应用是多实例部署的不要让每个实例都去执行证书文件的轮询和刷新。假设四台服务器同时发现文件变化、同时构建新的 SSLContext虽然理论上不会有问题但会造成资源浪费且很难排查日志。一种常用的做法是引入分布式锁比如数据库行锁或者中间件分布式锁只让一台实例执行刷新动作然后把新的证书内容通过配置中心或共享存储分发到所有实例。第五点回滚预案。不要在证书切换这件事上把路走到绝境。方案里最好保留一个兜底开关如果自动刷新后出现大规模 TLS 握手失败可以通过外部的配置中心下发一个标志让应用立即回退到备份证书并重启。这个开关平时不用但真的遇到极端问题比如证书文件被误覆盖成空白文件时能救命。我个人在实际运维中还有一个体会定期用生产环境的证书做一次预演。不要等到证书还剩七天的时候才开始测在证书还剩下三十天的时候主动模拟一次“过期替换”把整个自动化的链路完整走一遍。这种预演能提前暴露很多你根本不可能在文档里预见的问题比如某个服务器的时区不对导致定时任务触发时机混乱或者某个环境变量覆盖了配置导致文件路径错误。最后再分享一个小技巧配合 SpringBoot Actuator 暴露 SSL 证书的有效期指标。通过自定义一个 HealthIndicator 或者RestController端点把当前证书的序列号、到期时间、生效时间输出出来让监控系统定期拉取。这样你在 Grafana 面板上就能看到证书的“剩余寿命”曲线再也不用担心哪天一觉醒来发现全站告警。这个操作其实很简单就是从注册中心拿到当前 Bundle 的 KeyStore 再读取证书信息代码量不超过五十行但放在运维同学眼里就是“这个团队真的靠谱”。

相关新闻

open-code-review:基于Git Diff与LLM Agent的CLI代码审查实践

open-code-review:基于Git Diff与LLM Agent的CLI代码审查实践

1. 这不是又一个“AI代码审查”玩具:open-code-review 是怎么把 Git 差异、CLI 交互和 LLM 推理拧成一股实用绳子的你搜“open-code-review”,大概率会撞上一堆带“AI”“智能”“自动”的宣传页,配着闪烁的蓝色光效和“秒级发现 Bug”的标语…

2026/10/19 4:17:39 阅读更多 →
生产级AI Agent工作流实战:从原型到稳定落地的工程化改造指南

生产级AI Agent工作流实战:从原型到稳定落地的工程化改造指南

带过三个从 Demo 落到线上的 Agent 项目之后,我对“生产级 AI Agent 工作流”这几个字有了完全不同的理解。这个词看上去像是一个技术方案,实际上是一整套关于稳定性、成本、失控风险的系统工程。今天不聊概念,直接讲我是怎么把一条“能用就行…

2026/10/19 4:17:39 阅读更多 →
函数精讲:从定义到递归的全解析

函数精讲:从定义到递归的全解析

, 在第五天的学习笔记中(函数)这个主题是关于函数的问题, 函数可以让代码得到复用, 函数可以接受参数, 函数可以返回结果, 函数可以进行递归操作, 函数还可以是匿名的。一、函数基础这一部分的内容, 第一点就是去搞清楚一个事情, 究竟为什么要使用函数。…

2026/10/19 4:17:39 阅读更多 →

最新新闻

Open-Code-Review:一套让代码评审真正有效的实践指南

Open-Code-Review:一套让代码评审真正有效的实践指南

我在团队里做code review已经有六七年了,前后经历过几个规模不太一样的研发团队,加起来评审过的 MR 少说也有几千个。说实话,我看到过太多把 code review 做成"形式主义"的团队——大家每天在评论里互相发"LGTM"&#xf…

2026/10/19 4:59:07 阅读更多 →
Youngter-drive逆向实战:UPX脱壳、反调试与多线程混淆还原

Youngter-drive逆向实战:UPX脱壳、反调试与多线程混淆还原

“Youngter-drive”这个题目,我在某平台反复刷了几次。第一次拿到的时候差点被它的壳劝退,真正静下心走完一遍之后,最大的感受是:这道题的价值不在flag本身,而在于它串起了脱壳 -> 反调试识别 -> 代码混淆还原 -…

2026/10/19 4:59:07 阅读更多 →
数字打样+手工精修:ArtCraft让个人工作室做出高完成度工艺品

数字打样+手工精修:ArtCraft让个人工作室做出高完成度工艺品

ArtCraft这个项目名,我第一次看到时还以为是某个独立游戏的代号,后来才反应过来,它其实是我给工作室里那套“数字设计加传统手工”创作流程起的名字。简单说,就是用电脑先把图纸和结构算清楚,再用手工把温度做出来。这…

2026/10/19 4:59:07 阅读更多 →
OpenEarth-Agent:从工具调用到工具创建的遥感智能分析新范式

OpenEarth-Agent:从工具调用到工具创建的遥感智能分析新范式

1. 项目概述:为什么“能调用工具”还不够干遥感、环境监测这行的人,应该都有过这样的经历:卫星影像数据好不容易拉下来了,结果光是做预处理就耗掉大半天;想算个植被指数,得先查某个波段在第几个位置&#x…

2026/10/19 4:59:07 阅读更多 →
从引导扇区到加载器:自制操作系统Boot阶段实战指南

从引导扇区到加载器:自制操作系统Boot阶段实战指南

1. 从引导扇区到加载器:为什么不能一步到位很多人第一次接触自制操作系统,都会有一个特别朴素的想法:既然 BIOS 会把硬盘第一个扇区(512 字节)加载到内存里执行,那我直接把整个操作系统塞进这 512 字节不就…

2026/10/19 4:59:07 阅读更多 →
存储型XSS后端防御:基于注解与Filter的全量清洗方案

存储型XSS后端防御:基于注解与Filter的全量清洗方案

先说一个我前阵子遇到的真实案例。我们某个管理后台的“个人备注”功能被人塞了一行<script>alert(document.cookie)</script>&#xff0c;当时没有造成实际损失&#xff0c;但这段代码在整个查询页面回显&#xff0c;同事一打开列表&#xff0c;浏览器直接弹窗。查…

2026/10/19 4:58:06 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介&#xff1a;本资源为电源技术方向的学术研究文档&#xff0c;聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略&#xff0c;面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址&#xff1a; https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集&#xff0c;共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →