Remult:基于TypeScript的全栈类型安全开发框架实战指南

news2026/5/6 2:57:58
1. 项目概述从“全栈噩梦”到“类型安全桥梁”如果你和我一样在前后端分离架构里摸爬滚打了几年肯定对下面这个场景深恶痛绝前端写好了界面信心满满地调用一个/api/users接口结果后端返回的数据结构和你预期的User类型对不上要么多了几个字段要么少了个关键属性调试起来像在玩“大家来找茬”。更头疼的是你需要在后端定义一遍数据模型比如用 TypeORM 的 Entity在前端又得手动维护一套几乎一模一样的 TypeScript 接口一旦业务变更两边都得改稍不留神就不同步了。这种重复劳动和潜在的类型不一致我称之为“全栈开发的隐性税”。Remult 的出现就是为了彻底废除这笔“税”。它不是一个新框架而是一个极简的“粘合剂”或“类型安全桥梁”。它的核心主张是用一套 TypeScript 代码同时定义你的数据模型、业务逻辑和 API 接口。你只需要在一个地方通常是前后端共享的代码区域用 TypeScript 类定义你的实体EntityRemult 就能自动帮你完成以下工作在后端基于这个实体类自动生成对应的 RESTful API 端点并处理数据库的 CRUD 操作。在前端提供强类型的客户端库让你像调用本地对象方法一样调用 API并且获得完整的 TypeScript 类型提示和校验。简单说Remult 让你用声明式的方式定义“数据是什么”以及“能对数据做什么”它负责把这一切无缝地连接到数据库和前端界面。我第一次用它重构一个简单的后台管理项目时原本需要写几十个 API 路由和对应的前端请求函数现在只需要定义几个实体类剩下的增删改查、分页、过滤、排序全都自动有了而且前后端类型100%同步开发体验流畅得不可思议。它特别适合需要快速构建内部工具、管理后台、或者对类型安全有极高要求的全栈应用。2. 核心设计哲学约定优于配置的极致体现Remult 的设计深受“约定优于配置”Convention over Configuration原则的影响但把它提升到了类型安全的维度。它的目标不是替代你现有的后端框架如 Express、NestJS、Next.js API Routes或 ORM如 TypeORM、Prisma而是与它们优雅地集成填补类型同步的鸿沟。2.1 单一可信来源Single Source of Truth这是 Remult 的基石。在传统开发中数据模型的“真相”分散在至少三个地方数据库 Schema、后端实体/模型定义、前端类型定义。Remult 将其统一为一个用 TypeScript 装饰器Decorators修饰的实体类。这个类就是整个应用关于该数据实体的唯一权威定义。// shared/Product.ts - 这个文件可以被前后端共享 import { Entity, Fields, Validators } from remult; Entity(products, { allowApiCrud: true // 约定自动为该实体生成完整的CRUD API }) export class Product { Fields.uuid() id ; // 自动生成UUID Fields.string({ validate: Validators.required, // 声明验证规则 caption: 产品名称 // 元数据可用于生成表单标签 }) name ; Fields.number({ validate: [Validators.required, Validators.min(0)] }) price 0; Fields.boolean() inStock true; Fields.createdAt() createdAt new Date(); }这个Product类定义了字段类型、验证规则甚至一些 UI 提示信息如caption。它既是后端的实体模型也是前端的类型接口。2.2 自动化的 API 层与类型安全的客户端你不需要手动编写app.get(/api/products, handler)。Remult 在服务器端初始化时会根据实体类的allowApiCrud等配置自动注册对应的 REST API。更妙的是它会自动生成 OpenAPI 风格的元数据。在前端你通过remult客户端实例与这些 API 交互// frontend import { remult } from remult; import { Product } from ../shared/Product; async function fetchProducts() { // 类型安全的“查询构建器” const productRepo remult.repo(Product); // 查询获得类型为 Product[] 的响应 const products await productRepo.find({ where: { inStock: true }, orderBy: { price: asc }, limit: 20 }); console.log(products[0].name); // 完全的类型安全 // 新增编译器会检查字段类型 const newProduct await productRepo.insert({ name: 新商品, price: 99, inStock: true }); // 更新同样有类型校验 await productRepo.save({ ...newProduct, price: 89 }); }所有find、insert、save方法的参数和返回值都是强类型的。如果你尝试productRepo.insert({ name: 123 })TypeScript 编译器会在你写代码的时候就报错而不是等到运行时从服务器返回一个“价格必须是数字”的错误。这极大地缩短了反馈循环提升了开发效率和代码可靠性。2.3 与现有技术栈的无缝集成Remult 不强求你更换数据库或 web 框架。它通过“适配器”Adapters来连接外部世界后端框架它提供官方包可以轻松集成到 Express、Fastify、NestJS、Next.js (App Router/Pages Router)、Vite、Astro 等。数据库 ORM它主要与 TypeORM 或 Sequelize 配合利用它们的能力连接 PostgreSQL、MySQL、SQLite、SQL Server 等。你定义的 Remult 实体最终会通过这些 ORM 映射到数据库表。前端框架React、Vue、Angular、Svelte 都可以使用因为核心就是一个 TypeScript 客户端。这种设计让你可以将其渐进式地引入现有项目比如先在一个新的功能模块上试用而无需重写整个应用。3. 核心功能深度解析与实战要点理解了设计哲学我们来深入看看 Remult 如何解决具体问题。我会结合一个“任务管理应用”的实例拆解几个核心功能。3.1 实体定义不止于字段映射实体定义是 Remult 的核心。Entity和Fields装饰器提供了丰富的配置选项。实战要点字段类型与数据库映射Fields.string、Fields.number、Fields.boolean、Fields.date、Fields.json等它们不仅定义 TypeScript 类型也暗示了数据库列类型。对于Fields.jsonRemult 会自动处理序列化和反序列化。内置验证器Validators.required、Validators.min、Validators.max、Validators.unique需在服务器端配置等这些验证在前后端同时生效。前端在提交表单前即可获得即时验证反馈后端在存入数据库前会再次验证确保数据一致性。自定义验证与业务逻辑你可以在实体类中定义方法这些方法可以封装复杂的业务规则。Entity(tasks, { allowApiCrud: true }) export class Task { Fields.uuid() id ; Fields.string({ validate: Validators.required }) title ; Fields.boolean() completed false; Fields.date() dueDate?: Date; // 自定义业务逻辑方法 isOverdue() { return !this.completed this.dueDate this.dueDate new Date(); } // 静态方法用于定义服务器端逻辑 static async setCompleted(taskId: string, completed: boolean) { const taskRepo remult.repo(Task); const task await taskRepo.findId(taskId); // 这里可以添加更复杂的逻辑如权限检查、发送通知等 await taskRepo.save({ ...task, completed }); } }注意像isOverdue这样的实例方法其逻辑默认只在前端执行。如果涉及敏感数据或必须确保在服务器端执行的逻辑如setCompleted你需要通过 Remult 的“后端方法”或“实体生命周期钩子”来实现确保逻辑在受信任的服务器环境运行。3.2 查询构建器类型安全的数据库查询Remult 前端的repository.find()方法提供了一个强大的、类型安全的查询接口。它支持where、orderBy、limit、page、include等选项其语法非常直观。const taskRepo remult.repo(Task); // 复杂查询示例 const urgentTasks await taskRepo.find({ where: { completed: false, dueDate: { : new Date() } // 使用操作符 }, orderBy: { dueDate: asc }, limit: 10 }); // 分页查询 const page2 await taskRepo.find({ page: 2, pageSize: 25 });背后的原理这些查询选项会被 Remult 客户端序列化为一个特殊的查询参数通常是_后面跟一个 JSON 字符串发送到自动生成的 API 端点。服务器端的 Remult 会解析这个参数并将其转换为底层 ORM如 TypeORM的查询条件最终生成 SQL 语句。整个过程对开发者透明你得到的是类型安全的抽象。避坑技巧谨慎使用include关联加载类似 JOIN虽然方便但可能造成“N1 查询”问题或返回过大的数据量。务必清楚关联实体的数据规模和必要性。where条件的灵活性除了简单的等值匹配还支持,,,,!,in,like等操作符这为你构建复杂过滤界面提供了强大支持。服务器端过滤是黄金准则永远通过where子句在数据库层面完成数据过滤和分页而不是把所有数据取到前端再处理。这是 Remult 自动 API 的默认最佳实践。3.3 权限控制从实体到字段的精细化管理任何业务系统都绕不开权限。Remult 提供了多层次、声明式的权限控制方案这是它的一大亮点。3.3.1 实体级 API 控制在Entity装饰器中你可以精确控制哪些操作允许通过 API 访问Entity(tasks, { allowApiRead: Allow.authenticated, // 仅认证用户可读 allowApiInsert: Allow.authenticated, allowApiUpdate: (task, remult) task.createdBy remult.user.id, // 只能更新自己的任务 allowApiDelete: Allow.admin // 仅管理员可删除 }) export class Task { ... }Allow是一个工具类Allow.authenticated表示任何登录用户Allow.everyone表示所有人慎用Allow.admin是预定义角色。你也可以传入一个返回布尔值的函数实现基于数据的行级权限控制。3.3.2 字段级权限控制即使允许更新一个实体你还可以控制哪些字段可以被修改Fields.string({ allowApiUpdate: false // 该字段不允许通过API更新 }) readonlyId ; Fields.string({ allowApiUpdate: Allow.admin // 只有管理员能更新此字段 }) adminNotes ;3.3.3 服务器端验证钩子对于最复杂的业务规则你可以使用实体生命周期钩子如BackendMethod或Entity的apiPrefilter、saving等。BackendMethod({ allowed: Allow.authenticated }) static async completeTask(taskId: string, remult?: Remult) { const task await remult.repo(Task).findId(taskId); // 在这里进行任何服务器端验证和业务操作 if (task.createdBy ! remult.user.id) { throw new Error(只能完成自己的任务); } task.completed true; await remult.repo(Task).save(task); }BackendMethod定义的方法只在服务器端执行客户端调用它本质上是在调用一个特殊的 API。这是放置核心业务逻辑和最终权限检查的安全场所。实战心得权限设计应遵循“最小权限原则”。我的建议是先在实体级别用allowApiCrud: true快速原型开发然后随着功能完善逐步替换为更精细的allowApiRead、allowApiUpdate等控制最后在BackendMethod或钩子中添加核心业务规则。这样迭代起来非常顺畅。4. 完整集成实战从零构建一个 Next.js 全栈应用理论说再多不如动手搭一个。我们以最流行的全栈框架 Next.js (App Router) 为例构建一个带身份验证的任务管理器。4.1 项目初始化与依赖安装npx create-next-applatest remult-todo-app --typescript --tailwind --app cd remult-todo-app npm install remult remult-express remult/next npm install typeorm sqlite3 # 使用SQLite作为示例数据库 npm install bcryptjs jsonwebtoken types/bcryptjs types/jsonwebtoken # 认证相关4.2 定义共享实体创建shared/Task.ts和shared/User.ts// shared/Task.ts import { Entity, Fields, Allow, remult } from remult; Entity(tasks, { allowApiRead: Allow.authenticated, allowApiInsert: Allow.authenticated, allowApiUpdate: (task) task?.owner?.id remult.user?.id, allowApiDelete: (task) task?.owner?.id remult.user?.id, }) export class Task { Fields.uuid() id ; Fields.string({ validate: Validators.required }) title ; Fields.boolean() completed false; Fields.createdAt() createdAt new Date(); Fields.string() ownerId ; Fields.json({ lazy: true }) owner?: { id: string; name: string }; } // shared/User.ts import { Entity, Fields, Validators } from remult; Entity(users, { allowApiCrud: false }) // 不允许直接通过API操作用户 export class User { Fields.uuid() id ; Fields.string({ validate: Validators.required }) name ; Fields.string({ validate: Validators.required }) email ; Fields.string({ includeInApi: false }) // 密码不包含在API响应中 password ; }4.3 配置 Next.js API 路由与 Remult 服务器在app/api/[...remult]/route.ts中配置这是remult/next包约定的特殊路由// app/api/[...remult]/route.ts import { remultNextApp } from remult/next; import { Task } from ../../../shared/Task; import { User } from ../../../shared/User; import { createPostgresConnection } from typeorm; // 假设用Postgres // 获取或创建TypeORM连接 const getDbConnection async () { // ... 你的TypeORM连接配置 }; export const { POST, PUT, DELETE, GET } remultNextApp({ entities: [Task, User], getUser: async (req) { // 从请求的Cookie或Header中解析JWT获取当前用户信息 // 返回类似 { id: user-uuid, name: ..., roles: [user] } 的对象 // 这个对象会被赋值给 remult.user return await yourAuthFunction(req); }, getConnection: getDbConnection, });这个文件是 Remult 在 Next.js 中的入口所有对/api/*的请求如果匹配不到其他路由都会由 Remult 来处理并自动路由到对应实体的 CRUD 操作或后端方法。4.4 前端组件与 Remult 客户端交互在页面或组件中你需要初始化 Remult 客户端并设置认证令牌如果使用 JWT。// app/providers.tsx (一个客户端组件) use client; import { Remult, remult } from remult; import { Task } from ../shared/Task; import { useEffect } from react; export function RemultProvider({ children }: { children: React.ReactNode }) { useEffect(() { // 配置Remult实例的API地址和认证token remult.apiClient.url /api; // Next.js API路由的基础路径 const token localStorage.getItem(authToken); if (token) { remult.apiClient.setAuthToken(token); } }, []); return {children}/; } // app/page.tsx (主页面) use client; import { remult } from remult; import { Task } from ../shared/Task; import { useEffect, useState } from react; export default function HomePage() { const [tasks, setTasks] useStateTask[]([]); const [newTaskTitle, setNewTaskTitle] useState(); const taskRepo remult.repo(Task); useEffect(() { // 加载任务 taskRepo.find({ orderBy: { createdAt: desc } }).then(setTasks); }, []); const addTask async () { if (!newTaskTitle.trim()) return; const newTask await taskRepo.insert({ title: newTaskTitle, completed: false, ownerId: remult.user?.id! // 从remult.user获取当前用户ID }); setTasks([newTask, ...tasks]); setNewTaskTitle(); }; const toggleTask async (task: Task) { const updated await taskRepo.save({ ...task, completed: !task.completed }); setTasks(tasks.map(t t.id updated.id ? updated : t)); }; return ( div input value{newTaskTitle} onChange{e setNewTaskTitle(e.target.value)} / button onClick{addTask}添加/button ul {tasks.map(task ( li key{task.id} input typecheckbox checked{task.completed} onChange{() toggleTask(task)} / span{task.title}/span /li ))} /ul /div ); }4.5 身份验证流程集成身份验证是 Remult 中需要手动集成的一部分。通常流程是创建一个BackendMethod来处理登录验证用户名密码生成 JWT。前端调用这个登录方法获取 Token 并存储在本地如 localStorage 或 cookie。在 Remult 客户端设置这个 Token (remult.apiClient.setAuthToken(token))。在remultNextApp的getUser回调中验证并解析这个 Token返回用户信息。这个过程确保了 API 调用的安全性和remult.user上下文的正确性。5. 常见问题、性能考量与进阶技巧即使有了强大的抽象在实际项目中还是会遇到各种挑战。下面是我在多个项目中总结的一些经验和解决方案。5.1 性能优化与查询陷阱问题1N1 查询问题当你查询Task列表并且每个Task都想显示其所有者User的名字时如果设计不当可能会先查询 1 次获取任务列表然后对每个任务再查询 1 次获取用户信息N 次。解决方案使用 Remult 的include或 ORM 的关系映射。方法ARemultinclude在find查询中指定include。这通常会让 Remult 生成 JOIN 查询一次性获取关联数据。const tasks await taskRepo.find({ include: { owner: true } // 假设实体中定义了关系 });方法B在实体中定义关系结合底层 ORM如 TypeORM的关系装饰器ManyToOne,OneToMany并在 Remult 字段中配置。这需要更深入的 ORM 知识但更强大和灵活。问题2分页与总数计算find方法配合page和pageSize可以实现分页但如何获取总记录数以显示总页数解决方案使用repository.count()方法。const pageSize 25; const currentPage 2; const [tasks, totalCount] await Promise.all([ taskRepo.find({ page: currentPage, pageSize }), taskRepo.count() // 或者 count(whereCondition) 用于过滤后的总数 ]);注意count()是另一个独立的 API 调用。对于复杂过滤条件确保count和find使用相同的where条件。5.2 复杂业务逻辑与事务处理对于涉及多个实体修改的操作如“转账”需要保证原子性事务。解决方案在BackendMethod中使用底层 ORM 的事务管理。import { getConnection } from typeorm; BackendMethod({ allowed: Allow.authenticated }) static async transferPoints(fromUserId: string, toUserId: string, points: number, remult?: Remult) { const userRepo remult.repo(User); const connection getConnection(); // 获取TypeORM连接 await connection.transaction(async transactionalEntityManager { const fromUser await userRepo.findId(fromUserId); const toUser await userRepo.findId(toUserId); if (fromUser.points points) throw new Error(余额不足); // 使用transactionalEntityManager执行更新确保在同一个事务内 await transactionalEntityManager.update(User, fromUserId, { points: fromUser.points - points }); await transactionalEntityManager.update(User, toUserId, { points: toUser.points points }); // 还可以记录一笔交易日志... }); }将复杂的、多步骤的业务逻辑放在BackendMethod中并利用数据库事务是保证数据一致性的最佳实践。5.3 实时数据与订阅Remult 核心不直接提供 WebSocket 或 SSE 等实时功能。但对于需要实时更新的场景如聊天应用、实时仪表盘有几种整合方案轮询最简单前端定时调用repo.find()。对于更新不频繁的场景足够用使用where: { updatedAt: { : lastFetchTime } }可以优化为增量拉取。集成第三方实时服务在BackendMethod或实体生命周期钩子如saving中当数据变更时向 Pusher、Ably、Socket.io 服务器发送事件。前端订阅这些事件收到通知后再通过 Remult 拉取新数据。使用支持实时查询的数据库如果底层数据库是 Supabase 或 Firebase它们本身就提供了实时监听查询结果的功能。你可以将 Remult 与这些数据库的客户端 SDK 结合使用Remult 负责类型安全和 API 抽象数据库 SDK 负责实时流。5.4 部署与生产环境考虑API 安全性确保在生产环境中allowApiCrud: true这样的宽松设置被更严格的、基于角色的权限控制所替代。仔细审查每个实体的allowApiRead/Insert/Update/Delete规则。CORS如果你的前端和后端部署在不同域名需要在服务器端配置 CORS。使用remultExpress()或 Next.js 的中间件可以轻松配置。数据库连接池在生产环境中确保你的数据库连接如 TypeORM 连接被正确池化和管理以避免连接泄漏和性能问题。错误处理与日志Remult 抛出的错误会以标准 HTTP 错误响应返回。建议在服务器端配置全局错误处理中间件将未预期的错误记录到日志系统如 Winston、Pino并返回对用户友好的信息避免泄露堆栈跟踪。一个重要的避坑提示Remult 自动生成的 API 端点默认是公开的除非你用allowApiCrud: false或更细粒度的规则限制。在将应用部署到公网前务必使用remult.user和权限规则对所有敏感数据端点进行保护。对于管理类操作强烈建议使用BackendMethod因为其执行逻辑完全在服务器端控制之下更为安全。从我个人的使用体验来看Remult 最适合的场景是开发速度至关重要、且团队熟悉 TypeScript 的中小型全栈项目尤其是内部工具、管理后台和原型开发。它能将你从繁琐的胶水代码中解放出来让你更专注于核心业务逻辑。然而对于超大规模、需要极度定制化 API 或复杂微服务架构的应用Remult 的“约定”可能会成为一种限制需要评估其灵活性是否满足要求。但对于绝大多数场景它提供的生产力和类型安全保障是极具吸引力的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2586956.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…