Spring Boot多环境配置实战:Profile选型、优先级与避坑指南
开发环境跑得好好的一到测试环境就连不上数据库或者本地正常的文件上传到了服务器就切成了绝对路径这类问题我在不同团队见过太多次。根子往往不在代码逻辑而在于Spring Boot多环境配置没有做扎实。配置这个东西你平时感知不到它的存在一旦环境切换它就会变成最折磨人的那一环。Spring Boot的多环境配置说白了就是一件事让同一套代码在不同的运行环境里自动加载各自该用的参数不需要为每个环境单独打一个包也不需要上线前手动改配置。这篇就用一个真实项目里踩过的坑来做引子把多环境配置的方案选型、实操落地、优先级规则和常见问题一次性讲透。适合正在做Java后端、项目从单环境走向多环境、或者已经被配置问题折腾过几次的开发同学参考。1. 为什么多环境配置值得认真做1.1 一个坑了我一周的真实场景先说个具体的例子。某项目早期只有一套环境所有人都直连同一个测试库改代码、联调、验证全挤在一起。后来项目要交付到现场现场环境跟开发环境完全不同数据库地址不一样文件存储路径不一样短信服务商账号不一样甚至日志级别要求也不一样。最开始的做法很朴素——上线前改配置文件。把application.yml里的数据库地址换成现场的把Redis地址换成现场的然后重新打包。听起来不复杂但实际上每次都战战兢兢漏改一个地址就白跑一趟改完忘了哪个参数动过同事问你“昨天改了什么配置”完全答不上来。有一回把现场用的数据库地址误打成了开发环境的地址服务是起来了但连的是开发库数据混乱闹了个大笑话。后面重新梳理的时候发现这类问题根本不是“人不够细心”而是方案没做对。配置被打包进了代码里环境相关的东西和代码逻辑牢牢耦合在一起每一次环境切换都变成了一次高风险手工操作。1.2 多环境配置到底解决什么问题多环境配置要解决的本质上是“同一份代码、不同运行参数”的诉求。代码只有一份构建产物也只有一份但部署到开发环境、测试环境、生产环境时需要加载不同的外部依赖信息。这些信息包括但不限于数据库连接地址、用户名、密码Redis、消息队列的地址和连接池参数第三方服务的接口地址、密钥、Token文件存储的本地路径或对象存储桶名日志级别、监控上报地址线程池大小、超时时间等运行时参数Spring Boot提供的方案是Profile也就是“环境配置档”。你可以为开发环境准备application-dev.yml为测试环境准备application-test.yml为生产环境准备application-prod.yml启动的时候指定激活哪一档框架会自动加载对应的配置。代码不用动打包产物完全一样环境差异全部交给配置来隔离。1.3 方案选型的前提先搞清楚配置的边界多环境配置做起来容易乱是因为很多人没先想清楚“什么配置该按环境区分”。我踩过坑之后总结了一个简单的判断标准只要一个参数在开发、测试、生产三个环境里可能不一样就应该放进环境配置只要所有环境都一样的就放进公共配置。比如线程池的核心线程数开发环境可能设4就够了生产环境可能需要64这种属于环境差异性参数放到profile文件里。而某个接口的超时时间如果三个环境统一要求5秒放在公共配置里即可不用每个配置文件都抄一遍。边界不清晰会导致两个极端一种是把所有配置都塞进公共文件切环境时还得改公共配置另一种是每个环境文件都写一大坨重复内容改一个参数得翻三个文件。这两种我都见过都很难维护。先把配置分类想明白后面做profile才有章法。2. 几种主流配置方案的取舍2.1 方案A多个application-xxx.ymlSpring Profile的基本玩法这是Spring Boot官方推荐的方案也是团队里用得最多的方式。在src/main/resources下按环境拆文件application.yml # 公共配置 application-dev.yml # 开发环境 application-test.yml # 测试环境 application-prod.yml # 生产环境application.yml里放公共内容同时用spring.profiles.active指定默认激活哪个profilespring: profiles: active: dev启动时如果想覆盖通过启动参数或环境变量重新指定即可。比如部署到生产环境时java -jar app.jar --spring.profiles.activeprod这样开发和部署用完全一样的构建产物只是启动时告诉框架加载哪套配置。方案的优点是简单清晰、按文件管理、Spring Boot原生支持没有额外学习成本。缺点是如果环境数量多文件数量会跟着膨胀而且不同环境之间的配置差异散落在多个文件里对比起来有点费劲。2.2 方案BProfile注解从代码层面控制Bean是否加载除了配置文件Spring Boot还支持通过Profile注解控制特定环境才生效的Bean。举个实际场景开发环境没有真实短信服务可以注册一个打日志的假实现生产环境才用真正对接短信网关的实现。Service Profile(dev) public class MockSmsService implements SmsService { Override public void send(String phone, String content) { log.info(【开发环境】模拟发送短信: {} - {}, phone, content); } } Service Profile(prod) public class RealSmsService implements SmsService { Override public void send(String phone, String content) { // 调用真实短信网关 } }两个类实现同一个接口激活dev时注入MockSmsService激活prod时注入RealSmsService调用方Autowired的代码完全不用改。这个方案适合“某个环境是否需要某个组件”的场景和配置文件是互补关系不是替代关系。只决定Bean是否注册不给引用的数据和地址赋值。配置数据还是得靠配置文件来管。Profile也不建议大范围使用用多了Bean的装配关系会变得隐晦新接手的人看半天才明白哪个环境加载了哪个实现。只在确实需要环境差异化逻辑的时候用。2.3 方案CMaven Profile配合Spring Profile构建期环境隔离Maven也有自己的profile机制能在构建阶段针对不同环境做资源替换或差异化编译。有人在Maven里配置dev/release两个profile配合资源过滤打包的时候直接把application.yml里的占位符替换成对应环境的值。profiles profile iddev/id properties spring.profiles.activedev/spring.profiles.active /properties /profile profile idprod/id properties spring.profiles.activeprod/spring.profiles.active /properties /profile /profiles构建时通过-Pdev或-Pprod指定。这个方案的吸引力在于“打出来的包就是某个环境的包”但从我的经验看它恰恰是问题所在——如果你打了一个prod的包然后又想临时在测试环境验证包就没法复用了。多环境配置的初衷就是让构建产物通用在构建期就把环境焊死等于绕了一大圈又回到了原点。Maven Profile可以做但建议只做构建期的工作比如区分JDK版本、打包插件参数等不要拿它来替Spring Profile做环境隔离。环境相关的事情交给Spring Boot的Profile和运行期参数就够了。2.4 我的选型结论组合下来最优解是构建产物走通用打包环境配置走Spring Profile激活方式走运行期参数。具体就是只用一套application-xxx.yml体系Maven那边不做环境区分打包产物只有一份。部署到哪套环境就通过启动参数或环境变量激活对应的profile。开发环境本地启动自然加载dev测试环境由测试运维通过配置中心或者环境变量激活test生产环境由平台侧统一激活prod。这个组合的好处体现在三个地方一是构建产物通用测试环境的包和生产环境的包完全一致杜绝了“发布时打错环境包”的可能二是环境切换的活从开发手里转到了平台或部署脚本手里操作规范化了三是新增环境只需要增加一个application-xxx.yml文件不需要动Maven配置和构建逻辑。3. 实操从单环境到多环境的完整落地3.1 准备三套环境配置假设项目原来只有application.yml现在要拆成dev、test、prod三套。第一步是把公共配置保留在application.yml里环境差异项抽到各自的profile文件。公共配置长这样spring: application: name: user-service jpa: hibernate: ddl-auto: none properties: hibernate: format_sql: true server: port: 8080 logging: level: org.hibernate.SQL: debug这是所有环境都一样的部分应用名、端口、日志格式框架参数。注意我刻意没在公共配置里写数据库地址因为三个环境地址肯定不同。环境配置按维度拆分。开发环境spring: datasource: url: jdbc:mysql://localhost:3306/user_db?useSSLfalse username: root password: root redis: host: 127.0.0.1 port: 6379 logging: level: com.example.user: debug测试环境spring: datasource: url: jdbc:mysql://test-db.internal:3306/user_db_test username: test_user password: test_password redis: host: test-redis.internal port: 6379 logging: level: com.example.user: info生产环境spring: datasource: url: jdbc:mysql://prod-db.internal:3306/user_db_prod username: prod_user password: ${DB_PASSWORD} redis: host: prod-redis.internal port: 6379 logging: level: com.example.user: warn生产环境的数据库密码不能直接明文写在配置文件里我习惯用${DB_PASSWORD}这类占位符由部署平台通过环境变量注入。这样就算配置仓库泄露密码也不会跟着泄露。这个做法的重要性等你经历过一次密码泄露排查就懂了。3.2 怎么激活环境五种方式对比Spring Boot激活profile的方式有好几种适用场景各不相同。方式用法示例适用场景配置文件spring.profiles.active: prod默认激活某个环境命令行参数java -jar app.jar --spring.profiles.activeprod手动启动、临时切换Java系统属性java -Dspring.profiles.activeprod -jar app.jar启动脚本传参环境变量SPRING_PROFILES_ACTIVEprodDocker、K8s、容器化部署启动类硬编码SpringApplication.setAdditionalProfiles(prod)极少用不推荐优先级是命令行参数 Java系统属性 环境变量 配置文件。命令行参数能覆盖环境变量环境变量能覆盖配置文件里的spring.profiles.active。这里有个细节值得注意SPRING_PROFILES_ACTIVE环境变量是Spring Boot专门约定的大小写有讲究你放到Docker或K8s的YAML里也得写这个全大写名字。在容器环境下-D方式不生效因为JVM启动参数和应用启动参数是要分开传的很多人在Dockerfile里把-Dspring.profiles.active和--spring.profiles.active混在一起踩了坑才知道要分开放。3.3 本地开发与打包激活方式的最佳组合先说本地开发。IDE里直接运行Application类时配置文件里如果没设spring.profiles.active默认就是default不会加载任何环境配置。所以我在application.yml里设了默认值spring: profiles: active: dev这样本地一键启动就是开发环境配置不用每次都在IDEA配参数。但这里有个陷阱如果这个默认值不加思考地带到生产环境代码片段里写着active: dev生产环境启动时如果没有其他覆盖就会加载开发库配置后果你想象得到。所以规范做法是配置文件里给默认环境部署时通过外部参数强制覆盖。为了避免有人本地调试时影响公共资源还可以加一个application-local.yml跑集成测试或者联调用。# 本地指定local环境 java -jar app.jar --spring.profiles.activelocal3.4 配置抽离与复用别把一套配置抄三遍配置拆多了以后另一个问题就出来了dev、test、prod三个文件里大量内容相同只有地址和密码不一样。每次要改一个公共参数得同步改三个文件。Spring Boot从2.4版本开始支持spring.profiles.group和配置文件分组可以在公共配置里把profile分组定义好spring: profiles: group: dev: - common - dev-db prod: - common - prod-db不过这种多级分组配置对中小项目来说有点过重了。我更推荐一个轻量做法把确实环境无关的公共项留在application.yml每个环境文件只保留真正有差异的内容。三个环境文件之间公共程度高的项比如连接池参数、超时时间可以在spring.datasource.hikari下统一配置环境文件里只覆盖连接地址。还有一类配置是“不同环境值不同、但键不同”比如第三方回调URL。这类建议用统一前缀管理app: callback-url: http://dev.example.com/callbackapp: callback-url: https://prod.example.com/callback调用方只注入app.callback-url不用关心当前是哪个环境。这样代码里就没有任何环境判断逻辑配置切换变成了纯粹的数据替换。4. 配置优先级与最容易被坑的细节4.1 Spring Boot配置优先级排序多环境配置做到后期常会遇到一个问题我明明在命令行传了--server.port8081为什么启动后还是8080或者环境变量设置了某个值却不生效Spring Boot的配置来源很多优先级从高到低大致是这样优先级配置来源高命令行参数↑Java系统属性-D↑操作系统环境变量↑外部配置文件config/application.yml↑打包内的application-prod.yml↑打包内的application.yml低SpringApplication默认属性这个排序决定了覆盖关系。命令行参数能覆盖一切环境变量能覆盖配置文件profile文件中的配置会覆盖公共配置文件中的同名配置。理解了优先级顺序排错思路就会很清晰配置不生效时先确认有没有更高优先级的来源覆盖了它。我见过好多次“测试环境配置了app.callback-url但实际生效的还是生产地址”的案例最后查出来是环境变量里残留了旧值。4.2 常见坑点第一个坑是spring.profiles.active的加载时机。比如在application.yml里指定了active: dev同时又用spring.profiles.include引入其他配置Spring Boot对include的处理版本之间差异很大。2.4版本之前和之后的处理逻辑不太一样不太建议在新项目里混用这两个配置项容易把自己绕晕。第二个坑是环境变量注入时的大小写和符号转换。Spring Boot对RELAXED_BINDING的支持比较宽松SPRING_DATASOURCE_PASSWORD能对应到spring.datasource.password但这对别名映射也带来了另一个问题新人在环境变量里手误写了个相近的键名配置“看起来”设置了但实际上没生效这种bug排查成本很高。第三个坑是容器环境下传参的区别。Docker里如果这样写ENV JAVA_OPTS-Dspring.profiles.activeprod CMD [java, $JAVA_OPTS, -jar, app.jar]这是错的。$JAVA_OPTS在CMD的Shell形式下会被展开成单个字符串参数传给JVM-Dspring.profiles.activeprod无法被识别。实际应该用CMD [sh, -c, java $JAVA_OPTS -jar app.jar]或者干脆不用-D直接设ENV SPRING_PROFILES_ACTIVEprod。更省事。第四个坑是配置文件里的特殊字符转义。密码如果包含$、、:这类字符在YAML里不处理会直接解析错。比如密码是abc$def$可能在占位符解析时被当成属性占位符。遇到这种密码建议通过环境变量传递不要在YAML里写死或者用YAML的单引号包裹避免转义解析。第五个坑是日志级别跟环境脱钩。开发环境想看SQL和调试日志生产环境如果也配成debug级别磁盘很快会被日志撑爆。但很多人拆了环境配置却忘了把日志级别也拆开。日志不只是级别还包括日志文件的滚动策略、输出路径、格式这些都属于环境差异项应该在profile文件里各配各的。5. 常见问题与排查实录5.1 问题速查表症状可能原因处理方式启动后加载了错误的数据库地址更高优先级来源覆盖了预期配置检查环境变量、命令行参数是否残留旧值指定了active但等于是default环境配置文件里的spring.profiles.active写错位置或拼写错误确认配置项在spring节点下且语法正确Docker容器里profile没有被激活-D参数没有正确传给JVM改用ENV SPRING_PROFILES_ACTIVE或在CMD里正确展开变量环境配置文件里覆盖的端口不生效打包内master配置或外部config目录有更高优先级检查项目根目录/config和jar包同级目录数据库密码包含特殊符号导致启动失败YAML解析或占位符展开问题用环境变量传密码避免直接写入YAML测试环境联调走的是开发环境的第三方接口${}占位符未正确替换检查配置中心或环境变量中的对应键值新加的application-test.yml根本没被加载激活的名字和文件名不匹配确认激活值test与文件名application-test.yml严格一致5.2 排查思路遇到配置不生效我一般按这个顺序排查。第一步看启动日志Spring Boot启动时会在日志里打印一行The following 1 profile is active: prod这里直接告诉你当前激活了哪个profile。如果连这行都没有说明profile配置本身就没生效。第二步确认加载了哪个配置文件。可以在启动参数里加--debugSpring Boot会打印所有配置来源的详细加载过程包括每个配置项来自哪个文件、占用了哪个优先级。这个方法比人肉猜快得多。第三步用Spring Boot Actuator的/actuator/env端点查看配置项的解析结果curl http://localhost:8080/actuator/env返回结果里会有每个配置项的来源列表按优先级从高到低排列直接就能看出是环境变量覆盖了配置文件还是配置文件压根没加载。这是我觉得最实用的排查手段比一遍遍加日志强太多。第四步是验证配置边界。如果某个配置项生效了但是值不对检查是不是别的环境配置文件也定义了同名配置项。比如application-test.yml和application-dev.yml都配了app.callback-url激活test时Spring Boot只会加载test文件不会加载dev文件但如果你在application.yml公共部分里也配了同一个key公共配置会被profile文件覆盖。这个规则记牢了能省不少排查时间。最后说点实际的优化方向多环境配置做到现在还只是基础再往前走一步就是配置中心了。项目环境越来越多、配置项越来越多之后每次改配置都要重新打包发布这个成本很高。可以引入配置中心把配置外置Spring Cloud Config或者Nacos后者国内用的多一些。配置外置之后配置跟构建产物彻底分离改配置不需要动代码。这个演进适合在多环境配置玩熟练之后搞基础打不牢直接上配置中心反而会因为多层覆盖关系搞出更多问题。配置文件和代码一样需要持续维护。每新增一个环境每调整一个参数顺手把配置文件的注释写清楚把改动同步到相关环境不然三个月后自己看着配置都想不起来这些值是干嘛用的。我自己实际操作中的体会是配置管理混到今天不再是什么高难技术但极其考验工程规范意识先想清楚边界再动手比什么都重要。

相关新闻

Meta也买Claude?大模型多模型路由与成本控制实战

Meta也买Claude?大模型多模型路由与成本控制实战

看到这个题目,第一反应可能是“不理解”。Meta 是 Llama 系列开源模型背后的公司,长期强调自研和开源路线,为什么要反过来向 Anthropic 购买 AI 服务?Anthropic 的 Claude 系列是闭源模型,两家在商业上还是竞争对手。这…

2026/10/10 3:12:12 阅读更多 →
AI产物治理:从生成到管理的工程化之路

AI产物治理:从生成到管理的工程化之路

过去半年,我发现很多团队对 AI 编程的抱怨正在悄悄变化:模型生成得“准不准”已经不是首要矛盾,“产出物管不管得住”变成了新的瓶颈。代码从一个对话框里来,技术方案从另一个对话框里来,中间还有 AI 画的原型图、整理…

2026/10/10 3:12:12 阅读更多 →
RabbitMQ死信队列实战:原理、配置与避坑指南

RabbitMQ死信队列实战:原理、配置与避坑指南

RabbitMQ 里的死信队列,很多人一开始都理解成“把消息扔进一个叫死信队列的地方”,但真正配置下来才发现,它其实是“过一遍死信交换机,再决定去哪儿”。我最开始接触这个功能是在做订单超时未支付关单的需求时,主队列里…

2026/10/10 3:12:12 阅读更多 →

最新新闻

USMv6特别版:WinPE深度定制与离线系统修复实战指南

USMv6特别版:WinPE深度定制与离线系统修复实战指南

1. 这不是普通PE,而是一套可定制的“系统手术台”很多人第一次看到“U盘魔术师v6特别版(USMv6)”这个名字,下意识会把它归类为“又一个WinPE启动盘制作工具”。我最初也这么想——直到在某次紧急数据恢复现场,用它三分…

2026/10/10 3:53:29 阅读更多 →
Windows老电脑开机慢的精准诊断与优化指南

Windows老电脑开机慢的精准诊断与优化指南

1. 开机慢不是“老化宿命”,而是可定位、可修复的系统状态信号很多人一看到老电脑开机要一分半钟、点开软件要转圈十秒,第一反应就是“这机器不行了,该换新的了”。我接触过太多类似案例:某高校实验室一批2015年采购的台式机&…

2026/10/10 3:53:29 阅读更多 →
Java五子棋对战小游戏从零实现:控制台+Swing+AI完整教程

Java五子棋对战小游戏从零实现:控制台+Swing+AI完整教程

很多学Java的朋友都会卡在一个尴尬的节点:语法看完了,面向对象也懂了,Swing也刷过几个视频,但要真动手做点东西,不知道从哪下手。我这些年带过不少新人,最常推荐的练手项目就是五子棋。它不依赖框架&#x…

2026/10/10 3:53:29 阅读更多 →
PCA9422+MK20DN128低功耗电源管理实战:微安级待机与硬件级状态机设计

PCA9422+MK20DN128低功耗电源管理实战:微安级待机与硬件级状态机设计

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

2026/10/10 3:53:29 阅读更多 →
MyBatis Plus SQL日志配置实战:从零开始打开与调优

MyBatis Plus SQL日志配置实战:从零开始打开与调优

接手一个老项目,接口慢得离谱,想看看底层 SQL 到底长什么样,结果控制台干干净净,一条日志都没有。翻配置文件,发现 yml 里只写了几句logging.level.root: info,根本没有 MyBatis 相关的配置,于是…

2026/10/10 3:53:29 阅读更多 →
手机评论挖掘:LDA主题建模与情感分析预测销量排序

手机评论挖掘:LDA主题建模与情感分析预测销量排序

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

2026/10/10 3:52:28 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 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/8 21:13:17 阅读更多 →
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/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练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/9 6:17:20 阅读更多 →