JMeter BeanShell采样器实战:复杂接口关联与参数传递
1. 接口关联测试的核心痛点与BeanShell的定位做过接口自动化的人都有一个共识单个接口跑通不难难的是让多个接口像链条一样环环相扣地跑起来。上一秒登录接口返回的token下一秒就要塞进订单接口的请求头里前一个查询接口吐出来的订单号后一个接口得拿它当入参。这种“接口关联”或者叫“参数传递”的场景几乎是每个做自动化测试的人绕不开的坎。JMeter本身提供了不少组件来处理这件事比如正则表达式提取器、JSON提取器、XPath提取器这些都属于“后置处理器”的范畴。它们用起来确实方便配置几下就能把响应里的某个字段抠出来存进变量。但实际项目里情况往往没那么规矩。我见过太多接口返回的数据结构嵌套得跟迷宫一样或者需要根据前一个字段的值做条件判断才能决定取哪个字段甚至返回的根本不是标准JSON而是一段拼接过的字符串。这时候那些标准提取器就开始力不从心了。BeanShell采样器就是在这个缝隙里派上用场的。它本质上是一个轻量级的Java脚本执行环境JMeter把它集成进来让你能在测试计划里直接写Java代码。你可以用它做三件事第一在请求发出前动态构造参数第二在响应回来后对数据进行任意复杂的解析和提取第三把提取出来的值写入JMeter的变量空间供后续采样器使用。这篇文章要聊的就是第二和第三件事——怎么用BeanShell采样器把接口响应里的数据“捞”出来再“喂”给下一个接口。为什么是“三”因为前两篇分别讲了用正则提取器和JSON提取器做参数传递的基本套路这一篇专门啃BeanShell这块硬骨头。适合谁看如果你已经能用JMeter跑通简单的接口测试但遇到复杂响应结构就卡壳或者你厌倦了为每个接口写一堆提取器配置想用一个脚本搞定所有提取逻辑那这篇内容就是给你准备的。我会从设计思路讲到代码实现再到踩过的坑尽量把每个细节都摊开来说。2. 为什么选择BeanShell而不是标准提取器2.1 标准提取器的能力边界在哪里先说说正则表达式提取器。它的逻辑是拿一个正则去匹配响应文本把匹配到的组存成变量。这东西对付简单结构还行比如从{token:abc123}里抠出abc123写个token:(.*?)就完事了。但它有两个致命问题一是正则写复杂了极易出错尤其是遇到嵌套JSON或者需要跨行匹配的时候二是它只能做“匹配-提取”这一种操作没法做逻辑判断。比如响应里有个数组你要取其中某个字段等于特定值的那个元素的另一个字段正则表达式基本写不出来或者写出来也没人能看懂。JSON提取器好一些它基于JSONPath能处理嵌套结构。比如$.data.list[?(.status1)].id这种表达式确实能解决不少问题。但它也有局限第一它只能处理合法的JSON如果响应里混了HTML标签或者转义字符直接就解析失败第二JSONPath本身的能力有限做不了复杂的字符串处理比如你要把提取出来的时间戳转换成日期格式再传下去JSON提取器就干不了第三当提取逻辑需要依赖多个字段的组合判断时JSONPath写起来会非常别扭。XPath提取器就更窄了专门对付XML现在纯XML的接口越来越少用的场景不多。2.2 BeanShell带来的灵活性到底值不值BeanShell采样器的核心价值在于“任意编程”。它给你一个完整的Java运行时环境你可以用Java的所有标准库可以用JMeter暴露出来的vars、props、prev、ctx等对象还可以引入第三方jar包。这意味着什么呢意味着响应数据在你手里不再是“文本”或“JSON对象”而是一个可以被任意切割、转换、判断的字符串或对象。举个例子。假设有个接口返回这样的数据{ code: 200, data: { records: [ {id: A001, type: vip, amount: 100}, {id: A002, type: normal, amount: 50}, {id: A003, type: vip, amount: 200} ] } }现在你要提取所有type为vip的记录中amount最大的那个id。用JSON提取器你得先提取所有vip记录的amount数组再想办法找最大值JSONPath本身不支持聚合函数所以做不到一步到位。但用BeanShell你可以把响应字符串解析成JSONObject遍历records数组写个简单的循环比较几行代码就搞定了。提取出来的id往vars.put(maxVipId, id)一放后面的接口直接用${maxVipId}引用就行。再比如响应里有个字段是经过Base64编码的你需要先解码再提取里面的某个值。标准提取器完全无能为力但BeanShell里调一下Base64.getDecoder().decode()就解决了。所以BeanShell的灵活性是碾压级的。代价是什么代价是你得写代码得懂Java基础得处理异常得调试。对于简单的提取需求用BeanShell属于杀鸡用牛刀配置起来比正则提取器麻烦得多。但对于复杂场景它是唯一的选择。我的经验是能用标准提取器搞定的就别上BeanShell一旦发现提取逻辑超过三行正则或者JSONPath表达式或者需要做条件判断、格式转换、多字段联动果断切到BeanShell。2.3 性能与维护成本的权衡有人担心BeanShell的性能。确实BeanShell是解释执行的每次采样器运行都要编译一遍脚本比原生提取器慢。但在接口测试的场景下这个性能差异几乎可以忽略不计。一个测试计划跑几百个接口每个接口多花几毫秒总共也就多几秒。真正影响性能的是接口本身的响应时间而不是提取逻辑。维护成本倒是需要认真考虑。BeanShell脚本写多了如果没有良好的注释和命名规范过两个月自己都看不懂。而且脚本里的逻辑是“黑盒”的不像提取器那样在界面上直观可见。所以我的建议是把BeanShell脚本当成代码来管理变量命名要清晰关键步骤加注释复杂的提取逻辑最好抽成独立的方法。如果团队里有人不熟悉Java那用BeanShell之前得先评估一下交接成本。3. BeanShell采样器的核心对象与变量空间3.1 vars、props、prev、ctx到底怎么用JMeter在BeanShell脚本里暴露了几个核心对象理解它们是写好脚本的前提。vars是JMeterVariables的实例代表当前线程的变量空间。你可以用vars.get(变量名)读取变量用vars.put(变量名, 值)写入变量。注意vars.put只能存字符串如果要存对象得用vars.putObject。写入的变量在当前线程内全局可见后续的采样器可以通过${变量名}引用。这是参数传递最常用的对象。props是JMeterProperties的实例代表全局属性所有线程共享。一般用来存跨线程的配置信息比如全局的token或者环境地址。props.put(key, value)写入props.get(key)读取。注意props也是只能存字符串。prev是SampleResult的实例代表前一个采样器的结果。你可以用prev.getResponseDataAsString()获取响应体字符串用prev.getResponseCode()获取响应码用prev.getResponseHeaders()获取响应头。这是提取响应数据的主要入口。ctx是JMeterContext的实例代表当前线程的上下文。可以通过它获取当前线程的变量、前一个采样结果等。用得相对少一些但在某些复杂场景下有用。还有一个bsh.args是传递给BeanShell脚本的参数数组一般用得不多。3.2 变量作用域与线程安全这里有个坑需要特别注意vars是线程级别的每个线程有自己独立的变量空间。如果你在测试计划里设置了多个线程并发执行那么线程A写入的变量线程B是读不到的。这通常是符合预期的因为每个虚拟用户应该有自己的会话状态。但如果你确实需要跨线程共享数据那就得用props不过要小心并发写入的问题。另一个坑是变量的生命周期。vars里的变量只在当前线程的当前迭代中有效。如果测试计划设置了循环下一次迭代时变量会被重置。如果你需要变量在多次迭代间保持得用props或者把变量写入文件。还有一点BeanShell采样器本身也是一个采样器它会在测试结果里生成一条记录。如果你只是用它来做数据提取不想让它出现在结果树里干扰查看可以在采样器设置里勾选“不记录响应数据”或者调整它的执行顺序。3.3 响应数据的获取方式对比获取响应数据有几种方式各有适用场景。最常用的是prev.getResponseDataAsString()它返回响应体的字符串形式。如果响应是JSON你可以用JSON库解析如果是XML可以用XML解析库如果只是普通文本直接做字符串处理。如果响应数据量很大比如几十兆的文件用getResponseDataAsString()可能会占用较多内存。这时候可以用prev.getResponseData()拿到字节数组然后按需处理。还有一种情况是响应被压缩了比如gzip格式。JMeter通常会自动解压但如果没解压你得自己处理。可以通过prev.getResponseHeaders()检查Content-Encoding然后做相应的解压操作。对于文件上传下载类的接口响应可能不是文本而是二进制流这时候用字符串方式获取会乱码得用字节数组方式处理。4. 从响应中提取数据的完整实操4.1 环境准备与依赖引入在开始写脚本之前得先把环境搭好。JMeter本身自带BeanShell不需要额外安装。但如果你要用JSON解析库比如fastjson或者Jackson就需要把相应的jar包放到JMeter的lib目录下然后重启JMeter。我一般用fastjson因为它API简单解析速度快。下载fastjson的jar包放到JMETER_HOME/lib/目录下重启JMeter即可。如果你用的是Maven管理项目也可以在pom.xml里引入依赖然后通过JMeter的插件机制加载。除了JSON库有时候还需要commons-lang3、commons-io这些工具库看具体需求。建议把常用的库都放进去省得每次都要折腾。注意jar包的版本要和JMeter的Java版本兼容。JMeter 5.x通常要求Java 8及以上所以选jar包时注意看兼容性说明。4.2 添加BeanShell采样器的正确姿势在JMeter里添加BeanShell采样器很简单右键点击线程组 - 添加 - 采样器 - BeanShell Sampler。但有几个配置项需要留意。“参数”栏可以传入参数在脚本里通过bsh.args获取。“脚本文件”栏可以指定一个外部脚本文件适合脚本较长或者需要复用的场景。如果脚本写在“脚本”区域里就直接在文本框里编写。我通常会把脚本写在“脚本”区域方便调试。如果脚本超过50行会考虑抽到外部文件里用“脚本文件”方式加载这样可以用IDE编辑有语法高亮和自动补全。还有一个重要设置是“重置解释器”。默认情况下BeanShell解释器会在每次采样器执行时重置这意味着你定义的全局变量不会保留到下一次执行。如果你需要保留状态比如累计计数就得取消勾选“重置解释器”。但大多数提取场景不需要保留状态保持默认即可。4.3 解析JSON响应的标准流程假设有个登录接口返回如下响应{ code: 0, message: success, data: { userId: 10086, token: eyJhbGciOiJIUzI1NiIs..., expireTime: 1699999999, roles: [admin, operator] } }现在要提取token和userId存到变量里供后续接口使用。BeanShell脚本可以这样写import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; // 获取响应字符串 String response prev.getResponseDataAsString(); // 解析JSON JSONObject jsonObject JSON.parseObject(response); // 检查返回码 int code jsonObject.getIntValue(code); if (code ! 0) { // 记录错误日志 log.error(登录接口返回异常code code , message jsonObject.getString(message)); // 可以选择让采样器失败 // prev.setSuccessful(false); } else { // 提取data对象 JSONObject data jsonObject.getJSONObject(data); // 提取字段 String token data.getString(token); int userId data.getIntValue(userId); // 存入JMeter变量 vars.put(login_token, token); vars.put(login_userId, String.valueOf(userId)); // 打印日志方便调试 log.info(提取到token: token); log.info(提取到userId: userId); }这段脚本的逻辑很清晰先拿响应字符串解析成JSONObject检查业务返回码然后从data对象里取字段最后写入vars。后续的接口就可以用${login_token}和${login_userId}来引用了。有几个细节值得注意。第一log对象是JMeter提供的日志工具用log.info打印的信息会出现在JMeter的日志文件里调试时非常有用。第二prev.setSuccessful(false)可以把当前采样器标记为失败这样在结果树里会显示为红色方便定位问题。第三String.valueOf(userId)是因为vars.put只接受字符串整数需要转换。4.4 处理嵌套数组与条件筛选再来看一个复杂点的场景。有个订单查询接口返回{ code: 200, data: { orders: [ {orderId: ORD001, status: paid, amount: 299.00}, {orderId: ORD002, status: pending, amount: 150.50}, {orderId: ORD003, status: paid, amount: 89.90} ] } }现在要提取所有状态为paid的订单中金额最大的那个订单号。用BeanShell可以这样写import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; String response prev.getResponseDataAsString(); JSONObject root JSON.parseObject(response); JSONArray orders root.getJSONObject(data).getJSONArray(orders); String maxOrderId null; double maxAmount -1; for (int i 0; i orders.size(); i) { JSONObject order orders.getJSONObject(i); String status order.getString(status); if (paid.equals(status)) { double amount order.getDoubleValue(amount); if (amount maxAmount) { maxAmount amount; maxOrderId order.getString(orderId); } } } if (maxOrderId ! null) { vars.put(max_paid_orderId, maxOrderId); vars.put(max_paid_amount, String.valueOf(maxAmount)); log.info(找到最大金额的已支付订单: maxOrderId , 金额: maxAmount); } else { log.warn(没有找到已支付的订单); vars.put(max_paid_orderId, ); }这段脚本遍历了orders数组筛选出status为paid的记录然后比较amount找出最大值。这种逻辑用JSON提取器是写不出来的但用BeanShell就是几行代码的事。4.5 字符串处理与格式转换有时候响应不是标准JSON而是一段拼接的字符串比如resultSUCCESS;userId10086;tokenabc123def456;expire1699999999这时候就得用字符串处理了。BeanShell脚本可以这样写String response prev.getResponseDataAsString(); // 按分号分割 String[] parts response.split(;); String userId ; String token ; for (String part : parts) { if (part.startsWith(userId)) { userId part.substring(userId.length()); } else if (part.startsWith(token)) { token part.substring(token.length()); } } vars.put(userId, userId); vars.put(token, token); log.info(解析结果 - userId: userId , token: token);如果响应里有时间戳需要转换成日期格式可以这样处理import java.text.SimpleDateFormat; import java.util.Date; String expireStr vars.get(expire); long expireTimestamp Long.parseLong(expireStr) * 1000; // 假设是秒级时间戳 Date expireDate new Date(expireTimestamp); SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss); String expireFormatted sdf.format(expireDate); vars.put(expire_formatted, expireFormatted); log.info(过期时间格式化后: expireFormatted);这种格式转换在构造后续接口的请求参数时非常有用比如有些接口要求传日期字符串而不是时间戳。5. 参数传递的多种方式与选择策略5.1 通过vars传递到HTTP请求最直接的方式就是把提取出来的值存入vars然后在后续的HTTP请求里用${变量名}引用。比如在HTTP请求的“路径”栏写/api/user/${userId}/detail或者在“参数”栏的值里写${token}。这种方式简单直观适合大多数场景。但要注意变量的作用域vars是线程级别的如果测试计划里有多个线程组且线程组之间需要传递数据vars就不行了得用props。5.2 通过props实现跨线程组传递跨线程组传递数据的场景其实不少见。比如线程组A负责登录获取token线程组B负责用token做业务操作。这时候就得用props。在线程组A的BeanShell脚本里props.put(global_token, token);在线程组B的HTTP请求里引用方式稍微不同需要用${__P(global_token)}或者${__property(global_token)}。注意props是全局的所有线程都能读写所以要小心并发覆盖的问题。如果多个线程同时写入同一个props键后写的会覆盖先写的。5.3 写入文件实现持久化传递还有一种更“重”的方式是把提取的数据写入文件后续需要时再读取。这种方式适合数据量较大或者需要跨测试计划传递的场景。写入文件的脚本import java.io.FileWriter; import java.io.BufferedWriter; String filePath extracted_data.txt; BufferedWriter writer new BufferedWriter(new FileWriter(filePath, true)); writer.write(token , userId); writer.newLine(); writer.close();读取文件的脚本import java.io.BufferedReader; import java.io.FileReader; BufferedReader reader new BufferedReader(new FileReader(extracted_data.txt)); String line reader.readLine(); reader.close(); if (line ! null) { String[] parts line.split(,); vars.put(token, parts[0]); vars.put(userId, parts[1]); }文件方式的好处是数据可以持久保存不依赖JMeter的运行状态。缺点是IO操作有性能开销而且需要处理文件路径、并发读写等问题。一般只在特殊场景下使用。5.4 三种方式的对比与选型建议传递方式作用域适用场景注意事项vars当前线程同一线程组内的接口关联线程间不共享迭代后重置props全局跨线程组传递并发写入需加锁只能存字符串文件全局持久跨测试计划、大数据量IO开销大需处理并发我的选型原则是能用vars就用vars简单可靠确实需要跨线程组了再用props文件方式尽量不用除非有明确的持久化需求。6. 常见问题与排查技巧实录6.1 脚本报错但不知道错在哪里BeanShell脚本出错时JMeter的日志里会打印堆栈信息但有时候信息不够明确。我的做法是在脚本里加try-catch把异常信息打印出来try { // 业务逻辑 } catch (Exception e) { log.error(BeanShell脚本执行异常: e.getMessage(), e); prev.setSuccessful(false); }这样日志里会有完整的异常堆栈定位问题方便很多。另外可以在关键步骤前后加log.info打印中间变量确认执行到哪一步了。6.2 提取的变量在后续请求里取不到这个问题太常见了。原因通常有几个第一变量名拼写不一致比如脚本里写的是login_token请求里引用的是${logintoken}第二变量作用域不对比如在BeanShell里用了props.put但请求里用${变量名}引用应该用${__P(变量名)}第三BeanShell采样器的执行顺序不对它应该在提取响应之后、使用变量之前执行。排查方法在BeanShell脚本里加log.info(变量已写入: vars.get(变量名))确认变量确实写入了。然后在后续请求里用${__V(变量名)}或者Debug Sampler查看变量是否存在。6.3 响应数据量太大导致内存溢出如果接口返回的数据量很大比如几十兆的JSON用prev.getResponseDataAsString()可能会撑爆内存。这时候可以考虑用流式解析比如Jackson的Streaming API边读边处理不把整个响应加载到内存里。另一个办法是调整JMeter的堆内存参数在jmeter.bat或jmeter.sh里修改HEAP的值比如-Xms1g -Xmx4g。但这只是缓解根本解决还得靠流式处理。6.4 中文乱码问题有时候响应里有中文提取出来变成乱码。这通常是编码问题。JMeter默认用ISO-8859-1解码响应如果响应是UTF-8就会乱码。解决办法是在BeanShell脚本里手动转码String response new String(prev.getResponseData(), UTF-8);或者在JMeter的配置文件jmeter.properties里设置sampleresult.default.encodingUTF-8让JMeter统一用UTF-8解码。6.5 脚本执行速度慢影响测试效率BeanShell是解释执行的脚本复杂了确实会慢。优化方法有几个第一把不必要的工作移出脚本比如常量定义可以放在测试计划的变量里第二避免在脚本里做大量字符串拼接用StringBuilder代替第三如果脚本逻辑固定可以考虑用JSR223 Sampler配合GroovyGroovy是编译执行的性能比BeanShell好很多。不过还是那句话在接口测试场景下脚本性能通常不是瓶颈接口响应时间才是。除非你的脚本里有循环处理几万条数据否则不用太担心性能问题。6.6 常见问题速查表问题现象可能原因解决方法脚本报错无详细信息异常未捕获加try-catch打印堆栈变量取不到变量名拼写错误或作用域不对检查vars/props使用是否正确内存溢出响应数据过大流式解析或增大堆内存中文乱码编码不一致手动指定UTF-8或修改配置文件脚本执行慢脚本过于复杂优化逻辑或改用Groovy采样器结果显示失败脚本抛异常检查脚本逻辑加异常处理7. 几个实战中的经验与避坑建议先说一个我踩过的坑。有一次做接口关联前一个接口返回的token里包含了特殊字符比如和/我直接把它拼到URL里结果请求一直失败。后来发现是URL编码的问题token里的特殊字符需要先做URLEncoder处理。所以在BeanShell脚本里提取到值之后如果要用在URL参数里记得做编码转换import java.net.URLEncoder; String encodedToken URLEncoder.encode(token, UTF-8); vars.put(encoded_token, encodedToken);另一个坑是关于变量覆盖的。JMeter的变量是“后写覆盖先写”如果多个BeanShell采样器都往同一个变量名里写值后面的会覆盖前面的。有一次我调试了半天发现提取的值总是不对最后发现是另一个采样器也在写同一个变量。所以变量命名最好加上前缀比如login_token、order_id避免冲突。还有一点BeanShell脚本里的代码是在JMeter的线程里执行的如果脚本里有死循环或者长时间阻塞的操作会卡住整个线程。所以脚本里不要做网络请求、不要做大量计算、不要用Thread.sleep。提取逻辑应该尽量轻量复杂的处理可以放到外部程序里做。关于调试我强烈建议在开发脚本时把JMeter的日志级别调到DEBUG这样能看到更多细节。在log4j2.xml里把org.apache.jmeter的级别设为DEBUG重启JMeter即可。调试完之后再调回INFO避免日志文件过大。最后说一个关于脚本复用的技巧。如果你有多个接口需要做类似的提取逻辑可以把公共部分抽成一个方法放在外部脚本文件里然后在各个BeanShell采样器里用source()函数加载。比如source(extract_utils.bsh); String token extractToken(prev.getResponseDataAsString()); vars.put(token, token);这样能减少重复代码也方便统一维护。不过要注意外部脚本文件的路径问题最好用绝对路径或者相对于JMeter启动目录的路径。这些经验都是我在实际项目中一点点积累的有些是踩坑之后才明白的。BeanShell采样器是个强大的工具但强大意味着责任用得好能事半功倍用不好就是给自己挖坑。希望这些内容能帮你少走些弯路。

相关新闻

AI 终端 aiopsterm 实测:自然语言驱动的远程排障与安全边界

AI 终端 aiopsterm 实测:自然语言驱动的远程排障与安全边界

上个月我接手一台常年没人维护的业务节点,光排查磁盘告警就来回 SSH 敲了二十多条命令。如果你也经历过这种远程主机排障的体力活,应该能理解我为什么一看到 aiopsterm 这个开源 AI 终端,就立刻搭环境实测。它做的事情其实很直接:…

2026/10/13 6:34:48 阅读更多 →
CrewAI智能体自定义工具开发全指南

CrewAI智能体自定义工具开发全指南

1. CrewAI智能体开发概述在人工智能技术快速发展的当下,智能体(Agent)开发已经成为许多开发者关注的热点。CrewAI作为新兴的智能体开发框架,提供了创建自定义工具的完整解决方案。不同于传统AI应用开发,CrewAI智能体能够自主决策、执行复杂任…

2026/10/13 6:34:48 阅读更多 →
Java单例模式:饿汉式与懒汉式实现对比

Java单例模式:饿汉式与懒汉式实现对比

1. 单例模式基础认知单例模式作为设计模式中最基础也最常用的模式之一,其核心在于确保一个类仅有一个实例,并提供一个全局访问点。在Java开发中,单例模式的应用场景非常广泛,从配置管理、线程池到缓存系统,几乎无处不在…

2026/10/13 6:34:48 阅读更多 →

最新新闻

关系模型实战指南:从二维表到业务稳定性的底层逻辑

关系模型实战指南:从二维表到业务稳定性的底层逻辑

1. 这不是教科书里的“关系”,而是你每天都在用的数据组织逻辑“关系模型的基本概念”——看到这八个字,很多人第一反应是大学数据库课上那个被粉笔灰笼罩的下午,黑板上写着“实体、属性、域、键”,讲台下有人偷偷刷手机&#xff…

2026/10/13 12:22:17 阅读更多 →
Qt国际化翻译完整实践:从tr()到动态语言切换

Qt国际化翻译完整实践:从tr()到动态语言切换

做Qt开发这么多年,遇到最多的问题不是功能写不出来,而是功能做完以后客户说看不懂。于是QT国际化翻译就成了绕不开的环节。表面上看,这事只是把界面文字换成英文、日文,真正做起来却涉及源码扫描、翻译文件管理、运行时加载、动态…

2026/10/13 12:22:17 阅读更多 →
华为+红帽双赛道:2026网工转型的破局之道

华为+红帽双赛道:2026网工转型的破局之道

1. 为什么2026年网工转型,我建议你押注"华为红帽"双赛道最近不少朋友私信问我关于2026年转行网络工程师(网工)的事,大家的焦虑点很一致:AI工具越来越强,初中级网工的活是不是要被替代&#xff1f…

2026/10/13 12:22:17 阅读更多 →
Modern.js 服务端编译核心 @modern-js/server-utils:TypeScript 编译、别名解析与原生 ESM 支持的源码级解析

Modern.js 服务端编译核心 @modern-js/server-utils:TypeScript 编译、别名解析与原生 ESM 支持的源码级解析

前端后端Web框架 【免费下载链接】modern.js A progressive web framework based on React and Rsbuild. 项目地址: https://gitcode.com/gh_mirrors/mo/modern.js 点击查看 免费下载 本文围绕 packages/server/utils/CHANGELOG.md 记录的能力演进,结合…

2026/10/13 12:22:17 阅读更多 →
基于SpringBoot+Vue的派出所健康档案管理系统设计与实现

基于SpringBoot+Vue的派出所健康档案管理系统设计与实现

选题背景 社会对公共安全的重视,派出所民警的工作压力日益增大,其健康状况备受关注。早期的健康档案管理方式效率低下,难以实现信息的实时共享和动态更新。本系统采用 Spring Boot 框架,结合前端技术和数据库技术,构建…

2026/10/13 12:22:17 阅读更多 →
EmbeddingGemma 2本地多模态嵌入模型部署与向量检索实战

EmbeddingGemma 2本地多模态嵌入模型部署与向量检索实战

1. 这个模型到底是什么:先把它的定位弄清楚拿到"EmbeddingGemma 2"这个名字,第一反应就是:这是个嵌入模型,740M参数规模,多模态,而且主打本地推理。这几个关键词放在一起,意味着它并不…

2026/10/13 12:21:16 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →