Rust跨平台应用开发:relic框架架构解析与实战指南

news2026/5/6 18:44:38
1. 项目概述一个面向未来的跨平台应用构建方案最近在折腾一个个人项目需要把同一个应用逻辑部署到桌面端、Web端甚至未来可能还要上移动端。一开始想着用Electron毕竟生态成熟但一想到那动辄上百兆的安装包和不算低的运行时内存占用心里就有点打鼓。后来也考虑过Tauri它确实轻量但当时感觉生态还在发展中一些特定需求的第三方库集成起来有点费劲。就在我纠结的时候一个叫LucioLiu/relic的项目进入了我的视野。简单来说relic是一个旨在简化跨平台应用开发的框架或工具集。它的核心目标是让开发者能用一套代码主要是Rust高效地构建出能在Windows、macOS、Linux以及Web浏览器上运行的应用。这听起来有点像Tauri或Slint但relic在设计和理念上有它自己的侧重点。我花了一些时间研究它的源码、文档和社区讨论发现它并非另一个简单的“Rust WebView”封装而是在尝试提供一套更统一、更底层友好的抽象尤其是在处理UI和原生能力交互上有自己独特的思考。对于像我这样既看重应用性能和控制力又希望开发效率不要太低的开发者来说relic的出现提供了一个新的选项。它不强制你使用某一种特定的UI范式比如纯Web技术而是试图让你用Rust的能力去更直接地驱动界面同时兼顾跨平台的便利性。接下来我就结合自己的研究和理解拆解一下relic的核心思路、技术实现以及它可能适合的应用场景。2. 核心架构与设计哲学解析2.1 为什么是Rust性能与安全的基石relic选择Rust作为核心语言这几乎是它所有技术决策的起点。在今天这个时间点Rust的优势已经非常明显无GC的内存安全、零成本抽象、卓越的并发模型以及强大的类型系统。对于构建长期维护、对稳定性和性能有要求的桌面或系统级应用这些特性是巨大的吸引力。在跨平台场景下Rust还有一个关键优势一流的交叉编译支持。通过rustup可以轻松地管理不同平台x86_64-pc-windows-msvc,aarch64-apple-darwin,x86_64-unknown-linux-gnu等的工具链。这意味着你可以在同一台开发机上为所有目标平台生成最终的可执行文件极大简化了CI/CD流程。relic构建于这个能力之上使得“一次编写到处编译”成为其工作流的核心。但Rust在UI领域一直不算它的强项。生态中有不少优秀的UI库如egui,iced,druid但它们大多专注于提供自己的渲染和控件体系。relic的野心似乎更大一些它想做的不是另一个UI库而是一个“桥梁”或“协调层”。2.2 抽象层设计在统一与灵活之间寻找平衡跨平台框架最大的挑战之一是如何设计抽象层。抽象得太厚会损失性能和对原生特性的控制力抽象得太薄又会让跨平台代码变得繁琐失去框架的意义。relic在这个问题上的思路可以从它的项目结构窥见一斑。它通常会包含几个核心模块核心Core定义跨平台通用的数据类型、事件模型、应用生命周期接口。这部分是纯Rust代码不依赖任何特定平台的API。平台抽象层Platform Abstraction Layer, PAL这是一组特质Trait定义了创建窗口、处理事件、绘制图形、访问文件系统等操作的标准接口。例如可能有一个Windowtrait包含set_title,set_size,show等方法。平台实现Backends针对每个目标平台如Win32, Cocoa, X11, Web提供上述特质的具体实现。在Web后端创建窗口可能对应着操作DOM元素和CSS在桌面后端则直接调用系统原生的窗口API。渲染与UI这是最复杂的部分。relic可能提供多种选择一是集成现有的Rust UI库如egui作为其一个后端二是提供一套更底层的绘图API抽象让开发者可以自由选择使用wgpuVulkan/Metal/DX12/WebGPU的Rust绑定进行硬件加速渲染或者使用软件渲染。这种架构的好处是清晰的分层和解耦。作为应用开发者你主要与核心和平台抽象层的接口打交道编写大部分平台无关的业务逻辑。当你需要调用某个平台特定功能时可以通过PAL提供的、经过统一抽象后的接口来操作框架在背后帮你处理不同平台的差异。注意这种基于特质Trait的抽象方式非常“Rust”它强调编译时的多态和零成本抽象。但这也意味着框架的设计者需要非常谨慎地定义这些特质确保它们既能覆盖常用功能又不会因为过度设计而变得笨重。从relic的代码看它似乎倾向于提供一组相对精简、核心的抽象将更复杂或更定制化的功能暴露给开发者自行通过平台特定的扩展来实现。2.3 WebAssembly通往Web的桥梁对于现代跨平台框架Web支持不再是“加分项”而是“必选项”。relic将Web视为一等公民其关键技术就是WebAssemblyWasm。通过将核心业务逻辑和UI逻辑编译成Wasm模块它可以在浏览器中运行。这里有一个精妙的设计点在Web后端平台实现层会使用WebSys或wasm-bindgen来将PAL的调用转换为对Web API的调用。例如创建一个“窗口”在Web上可能意味着创建一个全屏的div容器处理鼠标事件则直接监听DOM事件。但Web环境与原生桌面环境有根本性差异最大的挑战在于渲染。如果UI库使用的是wgpu那么Web后端可以利用WebGPU API如果浏览器支持来获得接近原生的图形性能。如果使用的是软件渲染或Canvas 2D性能就需要仔细优化。relic需要在这条路径上做出权衡要么推动开发者使用兼容WebGPU的渲染路径要么为Canvas路径提供高效的渲染器。3. 开发体验与关键技术点拆解3.1 项目初始化与配置假设我们想用relic创建一个简单的跨平台应用。首先你需要一个标准的Rust项目环境。relic可能会提供一个类似cargo generate的模板或者详细的README来引导你。# 假设通过 cargo generate 使用模板 cargo generate --git https://github.com/LucioLiu/relic-template.git my-app cd my-app生成的Cargo.toml会包含对relic核心库以及你可能选择的特定后端如relic-winit用于桌面relic-web用于Web的依赖。框架可能会利用Cargo的features机制来让开发者按需选择后端和功能从而控制最终二进制文件的大小。[package] name my-app version 0.1.0 edition 2021 [dependencies] relic 0.1 # 核心库 # 选择你需要的后端 relic-winit { version 0.1, optional true } # 基于winit的桌面后端 relic-web { version 0.1, optional true } # Web/Wasm后端 [features] default [desktop] # 默认构建桌面应用 desktop [relic-winit] web [relic-web, relic/web] # 启用web特定功能这种配置方式非常灵活。你可以通过cargo build --featuresdesktop来构建桌面版通过cargo build --targetwasm32-unknown-unknown --featuresweb来构建Web版。构建Web版通常还需要一个像trunk或wasm-pack这样的工具来打包资源并启动开发服务器。3.2 应用结构与主循环一个典型的relic应用入口点看起来会非常简洁。框架会隐藏掉大部分平台初始化的样板代码。use relic::prelude::*; fn main() - Result(), Boxdyn std::error::Error { let app App::new(); app.run(MyAppState::default())?; Ok(()) } struct MyAppState { // 你的应用状态 counter: i32, } impl AppHandler for MyAppState { fn on_update(mut self, ctx: mut Context) - relic::ControlFlow { // 每一帧的逻辑更新 // 可以在这里处理事件、更新状态 // 返回 ControlFlow::Poll 继续循环ControlFlow::Exit 退出 relic::ControlFlow::Poll } fn on_draw(mut self, ctx: mut Context) { // 渲染逻辑 // 使用ctx提供的绘图API或集成的UI库进行绘制 let mut painter ctx.painter(); painter.text(Hello Relic!, 100.0, 100.0); } fn on_event(mut self, ctx: mut Context, event: Event) { // 处理输入事件鼠标、键盘、窗口事件等 match event { Event::MouseClick { x, y, button } { self.counter 1; ctx.request_redraw(); // 状态改变请求重绘 } _ {} } } }这个结构清晰地区分了状态更新、事件处理和渲染。Context对象是关键它提供了访问平台抽象层PAL的接口比如获取窗口大小、输入状态以及进行绘图的Painter。这种模式对于熟悉游戏循环或即时模式GUIImmediate Mode GUI的开发者来说会非常亲切。3.3 渲染路径的选择与实现渲染是UI框架的核心也是性能的关键。relic可能提供不止一种渲染方案集成现有GUI库如egui这是最快捷的方式。relic可以充当egui的一个后端负责为egui提供窗口、输入和图形上下文。开发者直接使用egui的API来构建界面。这种方式好处是能立刻获得一个功能相对完整、风格统一的UI系统适合工具类、配置类应用。// 伪代码示意集成egui fn on_draw(mut self, ctx: mut Context) { egui::Window::new(My Window).show(ctx.egui_ctx(), |ui| { ui.label(format!(Counter: {}, self.counter)); if ui.button(Increment).clicked() { self.counter 1; } }); // relic 负责将egui的绘制命令提交到GPU或Canvas }提供底层绘图APIrelic也可能暴露一套自己的2D绘图API类似raqote或tiny-skia的Rust绑定或者直接提供对wgpu上下文的访问。这给了开发者极大的自由可以自定义渲染管线实现复杂的视觉效果或游戏。这对于需要高性能图形、自定义控件或非传统界面的应用是必须的。// 伪代码示意使用底层绘图API fn on_draw(mut self, ctx: mut Context) { let mut canvas ctx.canvas(); canvas.clear(Color::WHITE); canvas.fill_rect(50.0, 50.0, 200.0, 100.0, Color::BLUE); canvas.stroke_text(Hello, 100.0, 100.0, Font::default(), Color::BLACK); }混合模式最理想的情况是框架同时支持这两种模式甚至允许它们在同一个应用中混合使用。例如主应用用自定义渲染而设置面板用egui快速搭建。这要求框架的抽象设计得非常出色。实操心得在选择渲染路径时一定要明确应用的需求。如果主要是表单、按钮、列表等标准控件集成egui或类似库能极大提升开发效率。如果你的应用更像一个数字画板、视频编辑器或游戏那么直接操作底层绘图API或wgpu是更合适的选择。relic的价值在于它试图让这两种模式都能在同一个跨平台框架下顺畅工作。3.4 状态管理与数据流对于稍复杂的应用状态管理是个绕不开的话题。relic作为底层框架可能不会强制推行某一种状态管理方案如Redux模式或响应式编程但它提供的事件驱动模型为各种方案奠定了基础。在上面的示例中状态MyAppState是保存在实现AppHandler的结构体中的。这是一种简单直接的方式适合小型应用。当状态变得复杂时你可以使用RcRefCellT或ArcMutexT在Rust中共享可变状态的标准方式。需要注意避免死锁和运行时借用检查的开销。采用消息传递Message Passing这是很多Rust GUI框架推崇的模式。应用状态是不可变的通过发送消息枚举类型来触发状态更新。relic的事件循环可以很自然地融入这种模式。enum Message { Increment, Decrement, InputChanged(String), } struct MyAppState { counter: i32 } impl AppHandler for MyAppState { fn on_event(mut self, _ctx: mut Context, event: Event) { // 将原生事件转换为应用自定义的Message // 然后发送到消息队列 } fn on_update(mut self, ctx: mut Context) - ControlFlow { // 从消息队列中取出并处理Message while let Some(msg) self.message_queue.pop() { match msg { Message::Increment self.counter 1, Message::Decrement self.counter - 1, _ {} } } ControlFlow::Poll } }集成响应式库社区中也有像Sycamore用于Web或Iced自带的响应式系统。如果relic的抽象足够好理论上可以将这些库的状态管理部分接入。框架设计者需要仔细考虑如何让这些模式都能方便地工作例如提供全局的事件总线、或与winit等窗口库的事件系统优雅集成。4. 构建、分发与调试实战4.1 多目标构建工作流跨平台开发构建是第一个拦路虎。relic基于Rust这本身已经解决了大部分问题。一个典型的项目工作流可能如下开发环境在主要开发平台比如macOS上直接cargo run即可启动桌面版本进行调试。构建Web版本# 安装wasm目标 rustup target add wasm32-unknown-unknown # 使用 trunk 构建并服务 trunk servetrunk会处理资源HTML, CSS, Wasm, 等的打包和热重载开发体验接近现代Web前端。交叉编译桌面版本# 为Linux构建 (在macOS/Windows上) rustup target add x86_64-unknown-linux-gnu cargo build --release --targetx86_64-unknown-linux-gnu # 为Windows构建 (在macOS/Linux上需要安装mingw-w64工具链) rustup target add x86_64-pc-windows-gnu cargo build --release --targetx86_64-pc-windows-gnu这里的一个常见坑点是原生依赖。如果你的应用依赖了某个C库那么交叉编译时就需要对应目标平台的该库。relic框架本身应尽量使用纯Rust实现避免引入外部C依赖以保持交叉编译的顺畅。4.2 打包与分发构建出二进制文件只是第一步如何打包成用户习惯的安装包同样重要。Windows生成.exe后可以使用NSIS、WiX Toolset或Inno Setup来制作安装程序。一个更Rust的方式是使用cargo-bundle插件它可以为不同平台生成标准的应用包。# Cargo.toml [package.metadata.bundle] name MyApp identifier com.example.myapp运行cargo bundle --release它会尝试生成对应平台的包如macOS的.appWindows的.msi等。macOS除了.appbundle还需要处理代码签名和公证Notarization否则在新系统上运行会遇到麻烦。这通常需要Apple开发者账号。Linux分发方式多样可以打包成.debDebian/Ubuntu、.rpmFedora/RHEL或Flatpak/Snap这样的通用包。cargo-deb和cargo-rpm插件可以辅助完成这项工作。Web输出是静态文件HTML, JS, Wasm, 资源。可以直接部署到任何静态网站托管服务如GitHub Pages, Netlify, Vercel。需要关注Wasm文件的加载性能和兼容性。relic框架的理想状态是能提供或集成一套统一的打包命令简化这个过程但这部分工作通常由社区或上层工具链完成。4.3 调试与性能分析调试跨平台应用尤其是涉及Web后端的需要多管齐下。桌面端调试和普通Rust程序一样可以使用println!日志、dbg!宏或者更强大的调试器如gdb/lldb。对于渲染问题可以借助图形调试工具如RenderDoc来捕获和分析帧。Web端调试这是优势所在。你可以直接使用浏览器强大的开发者工具。Console查看Rust中通过console_log等库输出的日志。Sources在浏览器中直接调试编译为Wasm的Rust源码需要启用调试符号。Performance分析Wasm模块的性能瓶颈查看函数调用耗时。Network检查资源加载情况。性能分析对于性能关键的应用可以使用perfLinux、InstrumentsmacOS、VTuneWindows等系统级分析器。在Rust中cargo-flamegraph可以生成火焰图直观展示CPU时间花费在哪里。对于Wasm浏览器的Performance面板是主要工具。一个实用的技巧是在relic的上下文对象中提供一个简单的性能计时器或帧率显示器方便在开发阶段快速定位性能退化。5. 优势、局限与适用场景分析5.1 核心优势性能潜力巨大得益于Rust和可能的底层图形API如wgpurelic应用可以获得接近原生的性能内存占用通常远低于基于完整Chromium的Electron应用。单一语言栈主要逻辑、UI如果使用Rust UI库都用Rust编写减少了上下文切换有利于代码复用和团队协作。类型安全贯穿始终。真正的原生体验通过不同的后端实现应用在每个平台上都可以使用原生的窗口装饰、菜单栏、文件对话框等用户体验更佳。部署包小巧一个简单的relic应用桌面版最终二进制文件可能在几MB到十几MB而Web版则是静态文件加载速度快。安全性与可靠性Rust的内存安全特性从根本上减少了崩溃和安全漏洞的风险对于需要长期稳定运行的应用尤为重要。5.2 当前面临的挑战与局限生态系统成熟度这是最大的挑战。Rust的GUI生态系统虽然发展迅速但相比WebReact/Vue或成熟的原生框架Qt, .NET MAUI其组件库的丰富度、成熟度和工具链的完善度仍有差距。relic作为一个新框架其自身的稳定性和功能完整性也需要时间验证。学习曲线开发者需要熟悉Rust而Rust本身有一定学习门槛。再加上relic框架自身的概念和API对新手来说入门成本不低。移动端支持从relic的项目描述看目前重点可能在桌面和Web。向iOS和Android的扩展会面临更大的挑战需要处理完全不同的UI范式触摸为主、不同的生命周期、应用商店规范等。这可能需要单独的、更厚重的抽象。开发效率对于高度交互、复杂UI的常规应用使用声明式的Web技术或成熟的GUI设计工具可能仍然比用Rust代码“画”UI更快。relic需要强大的工具支持如可视化设计器、热重载来弥补这一点。5.3 它最适合解决什么问题基于以上分析relic并非一个万能的替代品它在特定场景下会大放异彩性能敏感型工具如图像/音视频处理软件、代码编辑器、数据可视化分析工具、CAD软件等。这些应用需要大量计算和流畅的图形渲染relic提供的性能和控制力是关键。嵌入式或物联网设备的控制界面需要部署在资源受限的设备上同时又要提供Web和桌面管理端。用Rust统一核心逻辑用relic构建轻量级界面是很好的架构。游戏或交互式媒体艺术特别是那些不需要极度复杂3D引擎但需要跨平台部署包括Web的2D游戏或艺术项目。wgpu后端提供了强大的图形能力。内部工具或开发者工具这类工具通常对UI美观度要求不那么苛刻但对稳定性、启动速度和资源占用有要求。团队如果熟悉Rust用relic开发会非常高效。希望从Web技术栈向更高性能方案迁移的项目如果你的Electron应用遇到了性能瓶颈且团队有Rust学习意愿relic可以作为一个渐进式迁移的路径。可以先尝试用relic重写性能最关键的部件。6. 常见问题与避坑指南在实际探索和尝试构建relic应用的过程中你肯定会遇到各种问题。下面是我总结的一些常见陷阱和解决思路。6.1 编译与链接问题问题交叉编译时找不到系统库。表现在macOS上为Linux编译时出现linking with cc failed或cannot find -lxxx错误。原因你的项目或某个依赖包括relic的某个后端间接依赖了C库而交叉编译环境缺少目标平台的对应库。解决首先检查是否必须使用该C库。寻找纯Rust的替代品ring替代OpenSSLrustls替代openssl-sys。如果无法替代需要为目标平台安装交叉编译工具链和库。在macOS上可以使用brew安装x86_64-unknown-linux-gnu工具链在Linux上可以使用apt安装mingw-w64。通过环境变量如PKG_CONFIG_PATH,LIBRARY_PATH告诉链接器库文件的位置。问题WebAssembly构建成功但在浏览器中运行时崩溃或报错。表现控制台报TypeError: import object field ... is not a Function或类似的Wasm实例化错误。原因Rust代码中使用了Wasm环境不支持的API如文件系统操作、线程或者relic-web后端没有正确提供这些API的JavaScript实现polyfill。解决使用cfg(target_arch “wasm32”)条件编译来隔离平台特定代码。确保所有在Wasm中使用的功能都有对应的JavaScript实现。relic-web应该提供大部分基础功能的polyfill但高级功能可能需要你自己通过wasm-bindgen暴露JS函数。仔细检查浏览器控制台的完整错误信息它通常会指向出问题的Wasm导出函数。6.2 渲染与UI相关问题问题UI在不同平台或不同缩放比例下显示不一致。表现文字大小、控件间距、边框粗细在macOS、Windows和Web上看起来不一样。原因直接使用像素px作为单位没有考虑不同平台的DPI每英寸像素数差异。Web环境下的CSS像素与物理像素也存在换算关系。解决使用与DPI无关的单位在relic的绘图API中使用“逻辑点”logical points或“缩放独立像素”dip作为基本单位。框架应该提供从逻辑坐标到物理像素的转换函数如ctx.scale_factor()。查询系统DPI在应用启动时或窗口缩放事件中通过relic的上下文获取当前的DPI缩放因子并据此调整所有绘图和布局计算。字体处理字体渲染是跨平台的一大难题。尽量使用框架内置的字体渲染引擎或者使用像fontdue这样纯Rust、跨平台的字体光栅化库以确保一致性。对于Web可能需要将字体文件打包进Wasm或作为资源加载。问题滚动列表或复杂UI时感到卡顿。表现帧率下降界面响应迟缓。原因每一帧都重绘了整个界面没有做脏矩形优化或局部更新。解决实现局部更新在on_event中只标记状态发生变化的UI区域为“脏区域”。在on_draw中只重绘这些脏区域而不是整个画布。这需要UI系统或你自己维护一个控件树和布局信息。使用离屏渲染或缓存对于复杂的、不常变化的图形元素如背景、图标可以将其渲染到纹理Texture或离屏Canvas中然后每帧直接复制blit到屏幕上避免重复计算。性能剖析使用前面提到的调试工具定位是Rust逻辑计算慢还是Wasm到JS的调用开销大或者是GPU绘图指令过多。针对瓶颈进行优化。6.3 状态与事件管理陷阱问题事件处理代码变得冗长混乱。表现on_event函数里塞满了庞大的match语句难以维护。原因将所有事件处理逻辑都堆砌在一个地方。解决使用消息Message枚举如前所述将原生事件转换为高层次的应用消息。这样on_event只负责转换业务逻辑在on_update中处理消息职责更清晰。拆分状态与视图考虑采用更正式的模式如Model-View-UpdateMVU。将状态、视图渲染、更新逻辑分离到不同的模块或结构中。利用relic可能提供的助手关注框架是否提供了事件过滤、事件冒泡/捕获机制或者与某些状态管理库的集成方案。问题在异步操作如网络请求、文件IO后更新UI失败。表现点击按钮触发一个异步任务任务完成后数据变了但屏幕没有刷新。原因异步任务在非主线程中完成直接修改状态后没有通知主线程进行重绘。解决使用框架提供的事件循环代理成熟的GUI框架都会提供一个EventLoopProxy或类似的机制允许你从其他线程向主事件循环发送一个“自定义事件”或“唤醒信号”。在relic中你需要在on_update中检查一个来自异步任务的“完成标志”或消息通道。当异步任务完成时它将结果发送到通道并请求重绘ctx.request_redraw()。主循环在下一次on_update中从通道取出结果更新状态然后触发重绘。代码示例概念性struct MyAppState { data: OptionString, receiver: std::sync::mpsc::ReceiverString, // 接收异步结果 } impl AppHandler for MyAppState { fn on_update(mut self, ctx: mut Context) - ControlFlow { // 检查是否有异步结果到达 if let Ok(new_data) self.receiver.try_recv() { self.data Some(new_data); ctx.request_redraw(); // 重要通知重绘 } ControlFlow::Poll } // ... on_draw 中使用 self.data } // 在某个事件处理中启动异步任务 fn on_event(...) { if button_clicked { let sender self.sender.clone(); // 提前保存的发送端 std::thread::spawn(move || { let result do_async_work(); sender.send(result).unwrap(); }); } }6.4 打包与分发中的细节问题macOS应用图标不显示或格式错误。原因macOS的.appbundle对图标文件.icns有特定要求需要包含多种分辨率。解决使用专业的工具如iconutil命令或在线转换器生成符合规范的.icns文件并确保在Info.plist文件中正确指定了图标名称。问题Windows应用在未安装VC运行库的电脑上无法运行。原因如果链接了MSVC运行时默认则需要相应的vc_redist。解决静态链接在Cargo.toml中配置Rust使用静态链接运行时target-featurecrt-static但这可能会增加二进制大小并带来一些许可考虑。打包运行库在安装包中附带VC运行库安装程序并在安装过程中静默安装。使用GNU工具链换用x86_64-pc-windows-gnu目标它链接的是MinGW运行时通常可以随应用一起分发几个DLL文件相对简单。问题Web版本首次加载Wasm文件太慢。原因Wasm文件体积过大网络加载耗时。解决优化Rust代码体积使用cargo build --release -Z build-stdpanic_abort,std --targetwasm32-unknown-unknown进行LTO链接时优化和panicabort可以显著减小体积。使用wasm-opt工具进行后处理优化。代码分片如果应用很大考虑将非首屏必需的代码拆分成独立的Wasm模块按需加载。这需要更复杂的构建配置和运行时逻辑。压缩与CDN确保服务器启用了Brotli或gzip压缩。使用CDN加速文件分发。流式编译现代浏览器支持流式编译Wasm可以在下载的同时开始编译减少等待时间。确保你的打包工具如trunk和服务器配置支持这一点。探索relic这样的框架更像是在参与一场前沿的实验。它不一定是当下最成熟、最省力的选择但它指向了一个未来用高性能、安全的系统级语言构建优雅、高效的跨平台应用。如果你对Rust有热情对应用性能有要求并且不惧怕在尚不完善但充满可能性的生态中摸索那么relic及其代表的技术路线绝对值得你投入时间深入了解。从理解其架构开始尝试构建一个小工具你会在踩坑和解决问题的过程中获得对现代应用开发更深层次的认知。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2589044.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;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…