Spring Boot 整合微信小程序 AccessToken 缓存与分布式锁实战

1. 项目背景与整体设计思路

做过微信小程序后端对接的同学应该都有体会,AccessToken 这玩意儿看着简单,真到项目里落地的时候,坑是一点都不少。我最近刚把一个 Spring Boot 服务和小程序做对接,核心需求就是稳定地获取和管理 AccessToken,中间踩了不少雷,也总结了一些比较实用的方案。这篇文章就把整个思路和实现过程完整地梳理一遍,从方案选型到代码落地,再到线上排查,尽量把每个环节讲透。

先说清楚这个项目要解决什么问题。微信小程序的很多服务端接口,比如获取用户手机号、发送订阅消息、生成小程序码、内容安全检测等,都需要带上一个叫 AccessToken 的凭证。这个 Token 由微信服务端颁发,有有效期,默认是 7200 秒,也就是两个小时。过期之后需要重新获取。听起来很简单对吧?但问题在于,这个 Token 是全局唯一的,同一个 AppID 下,多次调用获取接口会导致之前那个 Token 失效。这就意味着,如果你在多台服务器上各自去获取,或者每次请求都去拿一个新的,就会出现互相顶掉的情况,线上表现就是接口时不时报 Token 无效。

所以这个项目的核心目标可以拆成三块:第一,用 Spring Boot 封装一个可靠的 AccessToken 获取逻辑;第二,做好缓存和过期管理,避免频繁请求微信接口;第三,处理好并发和刷新问题,保证多实例部署下也不会互相干扰。适合谁看呢?如果你正在做小程序后端,或者准备做,对 Spring Boot 有一定了解,但对微信这套凭证机制还不太熟,那这篇内容应该能帮你少走不少弯路。

整体设计上,我采用的是“集中获取 + 本地缓存 + 定时刷新 + 分布式锁兜底”的思路。为什么这么设计?因为 AccessToken 的获取接口本身有调用频率限制,而且每次获取都会让旧 Token 失效,所以绝对不能每次业务请求都去拿。缓存是必须的,但缓存放在哪、怎么刷新、多实例怎么办,这几个问题决定了方案的复杂度。我下面会一层一层拆开讲。

2. 核心机制解析与关键细节

2.1 AccessToken 的本质与获取接口

AccessToken 本质上是微信服务端颁发的一个临时凭证,你可以把它理解成一张两小时有效期的通行证。它的获取接口是https://api.weixin.qq.com/cgi-bin/token,需要传三个参数:grant_type固定为client_credential,appid是小程序的 AppID,secret是小程序的 AppSecret。返回结果是一个 JSON,包含access_token和expires_in两个字段。

这里有个细节很多人会忽略:expires_in返回的是 7200,但实际有效时间并不是精确的 7200 秒。微信官方文档里也提到,建议开发者提前刷新,不要等到最后一刻。我一般会预留 300 秒的缓冲,也就是实际缓存时间设为 6900 秒左右。这个缓冲很重要,因为网络延迟、时钟偏差、微信服务端的状态同步都可能让 Token 提前失效。你如果卡着 7200 秒用,线上大概率会遇到偶发的 Token 失效问题。

还有一个关键点:AppSecret 绝对不能放在前端或者客户端。它只能存在于服务端,而且要做好保密。我见过有同学把 AppSecret 写在小程序代码里,这是非常危险的,一旦被反编译,别人就能拿着你的 AppID 和 Secret 去获取 Token,后果不用我多说。

2.2 为什么不能每次请求都获取

这个问题值得单独说一下。假设你的小程序日活一万,每个用户操作都触发一次后端接口,如果每次接口都去调微信的获取 Token 接口,那一天的调用量就是几万次。微信对获取 Token 的接口是有频率限制的,虽然官方没有明确公布具体数字,但实测下来,频繁调用很快就会被限流,返回错误码 45009 或者 45011。

更严重的是,每次获取新 Token 都会让旧 Token 失效。如果你的服务是多实例部署,实例 A 刚获取了一个 Token,实例 B 又去获取了一个,那实例 A 手里的 Token 就废了。用户请求打到实例 A,就会报 Token 无效。这种问题在测试环境可能看不出来,因为测试环境通常只有一个实例,但一上生产就暴露了。

所以正确的做法是:全局维护一份 Token,所有实例共享。获取操作要加锁,保证同一时间只有一个实例去刷新。缓存要设置合理的过期时间,并且有主动刷新的机制。这就是我前面说的“集中获取 + 本地缓存 + 定时刷新 + 分布式锁兜底”的由来。

2.3 缓存方案选型:本地缓存还是 Redis

缓存放在哪,这是个需要权衡的问题。本地缓存比如用 Caffeine 或者 Guava Cache,优点是快,没有网络开销,实现简单。缺点是多个实例之间不共享,每个实例都有一份自己的 Token,如果各自刷新,还是会互相顶掉。Redis 的优点是全局共享,所有实例读同一份 Token,天然解决了多实例问题。缺点是多了一次网络调用,而且 Redis 本身也需要保证高可用。

我的选择是:Redis 作为主缓存,本地缓存作为一级缓存做短时间的兜底。具体来说,Token 存在 Redis 里,设置过期时间。每个实例本地再用 Caffeine 缓存一份,过期时间设短一点,比如 60 秒。这样大部分请求直接读本地缓存,只有本地缓存过期了才去读 Redis,减少 Redis 的压力。刷新的时候,用 Redis 的分布式锁保证只有一个实例去调微信接口,刷新完成后更新 Redis,其他实例等锁释放后重新读取。

这个方案的好处是兼顾了性能和一致性。本地缓存 60 秒的过期时间意味着即使 Redis 挂了,最多 60 秒内服务还是可用的。当然,如果你的项目规模不大,单实例部署,那直接用本地缓存就够了,不用上 Redis,简单直接。方案选型一定要结合自己的实际情况,不要为了技术而技术。

3. 实操过程与核心代码实现

3.1 项目依赖与基础配置

先说一下项目环境。我用的是 Spring Boot 2.7 版本,JDK 11,Redis 用的是 Spring Data Redis,HTTP 客户端用的是 OkHttp,相比 RestTemplate 更轻量,连接池管理也更方便。缓存用的是 Caffeine。下面是 Maven 的核心依赖,我列了个表格方便对照。

依赖用途备注
spring-boot-starter-webWeb 框架基础依赖
spring-boot-starter-data-redisRedis 操作用于分布式缓存和锁
caffeine本地缓存一级缓存
okhttpHTTP 客户端调用微信接口
fastjson2JSON 解析解析返回结果
lombok简化代码可选

配置文件里需要配好 AppID、AppSecret 和 Redis 连接信息。我建议把这些敏感信息放在配置中心或者环境变量里,不要直接写在 application.yml 里提交到代码仓库。下面是一个配置类的示例,用@ConfigurationProperties来绑定配置。

@Data @Component @ConfigurationProperties(prefix = "wechat.miniapp") public class WechatProperties { private String appId; private String appSecret; private String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token"; private int expireBuffer = 300; }

对应的 yml 配置大概是这样:

wechat: miniapp: app-id: ${WECHAT_APP_ID} app-secret: ${WECHAT_APP_SECRET} expire-buffer: 300

这里用环境变量占位,实际部署的时候通过环境变量注入,这样代码仓库里就不会有敏感信息。expire-buffer就是前面说的提前刷新缓冲,单位是秒。

3.2 AccessToken 的获取与解析

获取 Token 的核心逻辑就是发一个 GET 请求,然后解析返回的 JSON。但这里有几个细节要注意。第一,要处理网络异常和超时,设置合理的连接超时和读取超时,我一般设 3 秒和 5 秒。第二,要处理微信返回的错误码,比如 40001 表示 AppSecret 错误,40013 表示 AppID 无效,这些错误要能识别出来并记录日志。第三,返回的 Token 要校验非空。

下面是我封装的获取方法,用 OkHttp 实现:

public String fetchAccessToken() { HttpUrl url = HttpUrl.parse(properties.getTokenUrl()) .newBuilder() .addQueryParameter("grant_type", "client_credential") .addQueryParameter("appid", properties.getAppId()) .addQueryParameter("secret", properties.getAppSecret()) .build(); Request request = new Request.Builder().url(url).get().build(); try (Response response = httpClient.newCall(request).execute()) { if (!response.isSuccessful() || response.body() == null) { throw new RuntimeException("请求微信接口失败,HTTP状态:" + response.code()); } String body = response.body().string(); JSONObject json = JSON.parseObject(body); Integer errCode = json.getInteger("errcode"); if (errCode != null && errCode != 0) { throw new RuntimeException("获取AccessToken失败,错误码:" + errCode + ",错误信息:" + json.getString("errmsg")); } String token = json.getString("access_token"); if (token == null || token.isEmpty()) { throw new RuntimeException("获取AccessToken为空"); } return token; } catch (IOException e) { throw new RuntimeException("获取AccessToken网络异常", e); } }

这段代码里,我把错误码和错误信息都带出来了,方便排查。实际项目中,你可能还需要根据不同的错误码做不同的处理,比如 40001 说明 Secret 配错了,这种是配置问题,重试也没用,应该直接告警。而网络超时这种是可以重试的。

3.3 缓存与刷新逻辑的实现

缓存这块我用 Redis 存 Token,key 设计成wechat:miniapp:access_token:{appId},这样如果以后有多个小程序,可以区分开。value 就是 Token 字符串。过期时间设为expires_in - expireBuffer,也就是 7200 减 300,等于 6900 秒。

本地缓存用 Caffeine,过期时间设 60 秒,最大容量设 10 就行,因为一个 AppID 只有一个 Token。读取逻辑是:先读本地缓存,命中就返回;没命中就读 Redis,Redis 有就返回并写入本地缓存;Redis 也没有,就去获取新的 Token。

刷新逻辑我做了两层保障。第一层是定时任务,每隔一段时间检查 Redis 里的 Token 剩余有效期,如果快过期了就主动刷新。第二层是懒加载,当读取的时候发现 Redis 里没有 Token,就触发一次获取。两层结合,基本不会出现 Token 失效的情况。

定时刷新的代码大概是这样:

@Scheduled(fixedDelay = 60_000) public void refreshTokenTask() { String key = buildRedisKey(); Long ttl = redisTemplate.getExpire(key, TimeUnit.SECONDS); if (ttl == null || ttl < properties.getExpireBuffer()) { refreshTokenWithLock(); } }

这里用fixedDelay而不是fixedRate,是因为fixedDelay是上一次执行完成后才计算下一次的间隔,避免任务堆积。每分钟检查一次,如果剩余有效期小于缓冲时间,就触发刷新。

3.4 分布式锁保证多实例安全

多实例部署的时候,必须保证同一时间只有一个实例去刷新 Token。我用 Redis 的setIfAbsent命令实现了一个简单的分布式锁。锁的 key 是wechat:miniapp:token:lock:{appId},value 是一个随机 UUID,防止误删别人的锁。过期时间设 30 秒,防止死锁。

public void refreshTokenWithLock() { String lockKey = buildLockKey(); String lockValue = UUID.randomUUID().toString(); Boolean locked = redisTemplate.opsForValue() .setIfAbsent(lockKey, lockValue, 30, TimeUnit.SECONDS); if (Boolean.TRUE.equals(locked)) { try { String token = fetchAccessToken(); long ttl = 7200 - properties.getExpireBuffer(); redisTemplate.opsForValue().set(buildRedisKey(), token, ttl, TimeUnit.SECONDS); localCache.put(buildRedisKey(), token); } finally { // 释放锁,校验value防止误删 String currentValue = (String) redisTemplate.opsForValue().get(lockKey); if (lockValue.equals(currentValue)) { redisTemplate.delete(lockKey); } } } else { // 没抢到锁,等一会儿重新读缓存 try { Thread.sleep(200); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }

这里有个细节:释放锁的时候要先 get 再判断 value 是否一致,再 delete。虽然这不是原子操作,但在实际场景下已经够用了。如果你追求更严谨,可以用 Lua 脚本来保证原子性。不过对于 Token 刷新这种低频操作,简单实现就够了。

注意:锁的过期时间要大于获取 Token 的最长耗时。如果获取 Token 的接口响应很慢,超过了锁的过期时间,锁自动释放了,另一个实例就可能拿到锁去刷新,导致并发。所以锁的过期时间要留足余量,我设的 30 秒,一般接口响应都在几百毫秒内,足够了。

4. 常见问题与排查技巧实录

4.1 Token 失效的典型表现与原因

线上最常见的问题就是接口突然报 Token 无效,错误码通常是 40001 或者 42001。40001 是 Token 无效,42001 是 Token 过期。遇到这个问题,先别急着改代码,按下面的顺序排查。

第一,检查是不是多实例各自刷新导致的。如果你没有用分布式锁,或者锁没生效,多个实例同时去获取 Token,就会互相顶掉。排查方法是看日志里获取 Token 的时间戳,如果短时间内有多次获取记录,基本就是这个原因。

第二,检查缓存过期时间是不是设得太长。如果你把缓存时间设成了 7200 秒,没有留缓冲,那 Token 在微信服务端可能已经过期了,但你的缓存还没过期,就会用到失效的 Token。解决办法就是留 300 秒左右的缓冲。

第三,检查 AppSecret 是不是被重置过。如果在小程序后台重置了 Secret,那旧的 Secret 获取的 Token 就会失效。这种情况需要更新配置并重启服务。

第四,检查是不是有多个环境共用同一个 AppID。比如测试环境和生产环境用了同一个 AppID,测试环境频繁刷新 Token,就会把生产环境的 Token 顶掉。这种情况一定要隔离环境,用不同的 AppID。

4.2 常见问题速查表

我把实际遇到过的几个典型问题整理成了表格,方便对照排查。

问题现象可能原因排查方法解决方案
接口报 40001 Token 无效多实例并发刷新查看获取 Token 的日志频率加分布式锁
接口报 42001 Token 过期缓存时间设置过长检查缓存 TTL 配置预留 300 秒缓冲
获取 Token 返回 40013AppID 配置错误核对配置文件修正 AppID
获取 Token 返回 40001AppSecret 错误核对配置文件修正 Secret
获取 Token 返回 45009调用频率超限查看调用次数减少调用,加缓存
服务启动后首次请求慢懒加载首次获取查看启动日志启动时预热 Token

4.3 实操心得与避坑建议

说几个我在实际项目中总结的经验。第一个,服务启动的时候最好预热一下 Token,也就是在ApplicationRunner里主动调一次获取逻辑,把 Token 加载到缓存里。这样第一个用户请求就不会因为要等 Token 获取而变慢。预热的时候如果获取失败,不要阻止服务启动,记录日志就行,等第一次业务请求再触发获取。

第二个,日志一定要打全。获取 Token 的成功和失败都要记录,包括时间戳、耗时、错误码。我一般会在获取成功后打一条 INFO 日志,记录 Token 的前几位和过期时间,方便排查。失败的时候打 ERROR 日志,把错误码和错误信息都带上。这样线上出问题的时候,看日志就能快速定位。

第三个,监控和告警要跟上。Token 获取失败应该触发告警,因为这意味着所有依赖 Token 的接口都会不可用。我一般会监控获取失败的次数,连续失败超过 3 次就发告警。另外,Token 的剩余有效期也可以监控,如果长时间没有刷新,可能定时任务挂了。

第四个,关于 HTTP 客户端的连接池。OkHttp 默认的连接池是 5 个空闲连接,keep-alive 5 分钟。对于获取 Token 这种低频调用,默认配置就够了。但如果你还用同一个客户端调其他微信接口,可以适当调大连接池。另外记得设置超时,我设的连接超时 3 秒,读取超时 5 秒,写入超时 5 秒。

第五个,关于 Token 的存储格式。我建议存字符串就行,不要存 JSON。有些同学喜欢把 Token 和过期时间一起存成 JSON,读取的时候再解析。这样虽然信息全,但多了一次序列化和反序列化的开销。过期时间交给 Redis 的 TTL 来管理就够了,不需要额外存。

4.4 性能优化与扩展思路

如果你的小程序规模比较大,QPS 比较高,可以考虑进一步优化。比如本地缓存的过期时间可以适当延长,减少 Redis 的读压力。但要注意,本地缓存越长,Token 刷新后其他实例感知的延迟就越大。60 秒是一个比较平衡的值,你可以根据自己的业务容忍度调整。

另外,如果你的项目有多个小程序,可以把这套逻辑封装成一个通用的服务,通过 AppID 来区分不同的 Token。缓存 key 和锁 key 都带上 AppID 前缀,这样一套代码可以支持多个小程序。配置上可以用一个 Map 来存多个小程序的 AppID 和 Secret。

还有一个扩展点是 Token 的降级策略。如果 Redis 挂了,本地缓存还能撑 60 秒。如果本地缓存也过期了,获取 Token 又失败,这时候可以考虑返回一个明确的错误,让上游知道是凭证问题,而不是直接抛异常。这样上游可以做针对性的处理,比如提示用户稍后重试。

最后说一个我踩过的坑。有一次线上突然大量报 Token 无效,排查了半天发现是运维同学在另一台机器上部署了一个旧版本的服务,那个版本没有用分布式锁,而且缓存时间设的是 7200 秒。它一启动就去获取了 Token,把正常的 Token 顶掉了。所以版本管理和部署规范也很重要,确保所有实例用的是同一套逻辑。

这套方案我在两个项目里都用过,一个是单实例的小项目,直接用本地缓存,简单稳定;另一个是多实例的项目,用了 Redis 加分布式锁,跑了半年多没出过 Token 相关的问题。核心就是理解 Token 的全局唯一性和过期机制,然后针对性地做缓存和并发控制。代码不复杂,但细节决定成败。

相关新闻

计算机网络基本概念实战指南:从OSI到TCP/IP的分层排查思维

计算机网络基本概念实战指南:从OSI到TCP/IP的分层排查思维

1. 为什么还要回头聊“计算机网络基本概念”你可能觉得奇怪&#xff0c;都什么年代了&#xff0c;怎么还有人写计算机网络基本概念这种“大一第一课”的内容。我一开始也这么想&#xff0c;直到最近帮几个朋友排查问题&#xff0c;发现一个很普遍的现象&#xff1a;很多人能写代…

2026/10/19 19:17:17 阅读更多 →
open-code-review:基于CLI+Diff+LLM Agent的可审计代码审查范式

open-code-review:基于CLI+Diff+LLM Agent的可审计代码审查范式

1. 这不是另一个“AI代码审查工具”&#xff0c;而是一套可落地的开源协作新范式 “open-code-review”这个词组乍看像某个新发布的CLI工具名&#xff0c;但实际它指向的是一类正在快速成型的技术实践&#xff1a;用开源、透明、可审计的方式&#xff0c;把大模型驱动的代码审…

2026/10/19 19:17:17 阅读更多 →
HTML Help Workshop汉化版安装配置与CHM中文编译避坑指南

HTML Help Workshop汉化版安装配置与CHM中文编译避坑指南

简介&#xff1a;HTML Help Workshop 汉化版面向需要制作 CHM 帮助文档的中文用户&#xff0c;尤其是软件开发者、技术写手与文档维护人员。原版为微软官方英文工具&#xff0c;汉化后提供全中文界面&#xff0c;降低了国内用户学习与操作门槛&#xff0c;可用于编写 HTML 页面…

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

最新新闻

L应用内存取证复盘:蓝队如何从内存镜像还原攻击链路

L应用内存取证复盘:蓝队如何从内存镜像还原攻击链路

我去年处理过一起很有意思的应急事件&#xff1a;某企业内部办公应用L在深夜出现异常外联&#xff0c;登录日志被攻击者清得干干净净&#xff0c;磁盘上能翻到的痕迹少得可怜。但内存镜像拉下来之后&#xff0c;攻击者的后门配置、窃取的会话凭证、甚至绕过二次认证的完整链路全…

2026/10/19 20:09:45 阅读更多 →
4G基站同步异常致小区不可用:从GPS失锁到同步板卡更换复盘

4G基站同步异常致小区不可用:从GPS失锁到同步板卡更换复盘

那天午休刚结束&#xff0c;值班手机弹出一条告警&#xff1a;某4G站点的所有小区同步异常&#xff0c;随后状态快速转成“小区不可用”。这种告警在维护群里并不少见&#xff0c;但真正让人紧张的&#xff0c;是它已经从“失步”一路演变到整站掉线&#xff0c;等于现场业务直…

2026/10/19 20:09:45 阅读更多 →
零基础手作项目artcraft:从创意到实物的完整流程

零基础手作项目artcraft:从创意到实物的完整流程

artcraft 这名字听起来有点像某个游戏 ID&#xff0c;但对我来说&#xff0c;它其实是一间可以随身带走的临时手作工作室。这个项目我已经断断续续做了快两年&#xff0c;核心只有一句话&#xff1a;把脑子里的创意&#xff0c;变成手里拿得住的实物。它没有标准流程&#xff0…

2026/10/19 20:09:45 阅读更多 →
ARIMA模型输出参数解读:Python与R双实现的时间序列预测实战

ARIMA模型输出参数解读:Python与R双实现的时间序列预测实战

先把话放前面&#xff1a;这篇文章不是讲“怎么把ARIMA跑通”的入门教案&#xff0c;而是讲“跑通之后&#xff0c;那些输出参数到底该怎么看、怎么用”。我之前折腾过一个销售预测任务&#xff0c;代码确实整出了预测曲线&#xff0c;项目汇报时也讲得头头是道&#xff0c;结果…

2026/10/19 20:09:45 阅读更多 →
从设计规范到性能优化:前端图表设计系统搭建实战

从设计规范到性能优化:前端图表设计系统搭建实战

1. 项目概述&#xff1a;一张设计稿背后的"图表设计系统"先交代一下背景。我是在做某个跨平台数据产品时&#xff0c;被逼着做了这个代号为diagram-design的项目。说白了&#xff0c;就是一套能把"原始数据"变成"规范图表"的前端图表设计与渲染方…

2026/10/19 20:09:45 阅读更多 →
Postman接口串联实战:变量作用域、提取脚本与执行顺序控制

Postman接口串联实战:变量作用域、提取脚本与执行顺序控制

1. 接口串联的真实痛点与整体设计思路做过接口测试的人几乎都遇到过这种场景&#xff1a;你手里有两个接口&#xff0c;A接口是业务主流程&#xff0c;B接口是前置依赖。A接口的请求体里有一个必填字段&#xff0c;而这个字段的值必须从B接口的响应里拿。比如下单接口需要一个动…

2026/10/19 20:08:44 阅读更多 →

日新闻

频率跟踪型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/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

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

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

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

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

如果你的信息流最近也天天刷到“机器人大脑”这个词&#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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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 阅读更多 →