当前位置: 首页 > news >正文

CommonAPI学习笔记-1

CommonAPI学习笔记-1

一. 整体结构

在这里插入图片描述
CommonAPI分为两层:核心层和绑定层,使用了Franca来描述服务接口的定义和部署,而Franca是一个用于定义和转换接口的框架(https://franca.github.io/franca/)。

​ 核心层和通信中间件无关,使用fidl配置文件来描述接口的逻辑,绑定层和中间件相关(DBUS/SOMEIP)。因此在fdepl配置文件中设置了中间件所依赖的参数。(CommonAPI C++ is divided up in a middleware-independent part (CommonAPI Core) and in a middleware-specific part(CommonAPI Binding) )

​ 通过代码生成工具(core-generator, someip-generator和dbus-generator)根据配置文件生成核心层和绑定层的业务代码,这些业务代码依赖CommonAPI的运行库libCommonAPI.so,而CommonAPI的运行库则依赖CommonAPI的绑定库(libCommonAPI-SomeIP.so),CommonAPI的绑定库依赖具体的中间件运行时库 (libsomep.so)。
在这里插入图片描述

二. Franca 配置文件

​ 前面说过CommonAPI分为核心层和绑定层,核心层和绑定层都有代码生成工具,我们需要根据业务场景的实际需求,编写对应的fidl(核心层)和fdepl(绑定层)配置文件,并且由代码生成工具生成代码。

​ fidl文件主要由下列元素组成:

类型说明
package接口所属的名称空间,类似JAVA的包名或者DDS中的domainid
interface接口名称,相当于someip中的serviceid
version接口版本号,这个版本号同样会被绑定层使用到
attribute接口中的属性成员,对外提供读和写的接口
typeCollection用于自定义类型的容器,内部保存用户自己定义的数据类型
struct用户自定义数据类型,类似C语言的结构体

​ fidl文件的范例(来自官方代码https://github.com/COVESA/capicxx-core-tools/blob/master/CommonAPI-Examples/E02Attributes/fidl/E02Attributes.fidl):

/* Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)* This Source Code Form is subject to the terms of the Mozilla Public* License, v. 2.0. If a copy of the MPL was not distributed with this* file, You can obtain one at http://mozilla.org/MPL/2.0/. */package commonapi.examples  // package包名interface E02Attributes {    // interface接口名称version { major 1 minor 0 }   // 接口版本号attribute Int32 x      // 基本数据类型属性attribute CommonTypes.a1Struct a1  // 用户自定义数据类型属性
}typeCollection CommonTypes {    // 用户自定义类型集合version { major 1 minor 0 }  // 类型版本号struct a1Struct {     // 用户自定义类型String sa2Struct a2       // 嵌套了用户自定义类型成员}struct a2Struct {	  // 用户自定义类型Int32 aBoolean bDouble d}
}

​ fdepl文件对应的是绑定层的代码实现,因此,fdepl文件中的配置是和绑定层对应的中间件相对应的,例如如果fidl中定义了接口中的属性,那么如果绑定层是someip的话,那么fdepl文件中需要指定接口对应的someip服务的信息(serviceid, instanceid),属性对应的方法信息(method, eventid, eventgroupid)等,这里用官方范例中的fdepl文件(https://github.com/COVESA/capicxx-core-tools/blob/master/CommonAPI-Examples/E02Attributes/fidl/E02Attributes-SomeIP.fdepl)来说明

/* Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)* This Source Code Form is subject to the terms of the Mozilla Public* License, v. 2.0. If a copy of the MPL was not distributed with this* file, You can obtain one at http://mozilla.org/MPL/2.0/. */import "platform:/plugin/org.genivi.commonapi.someip/deployment/CommonAPI-4-SOMEIP_deployment_spec.fdepl"
import "E02Attributes.fidl"    // 重点,这个import就意味着如果不先生成fidl对应的代码文件,可能无法生成该fdepl文件的代码文件
// 定义了commonapi.examples.E02Attributes这个服务接口的CommonAPI SOME/IP部署规范(SOMEIP服务的参数配置)
define org.genivi.commonapi.someip.deployment for interface commonapi.examples.E02Attributes { //这里会生成部署文件/* service id = 0x1235*/SomeIpServiceID = 4661   // fidl中服务接口对应someip服务idattribute x {         // fidl的接口中,属性对应someip的属性(包含get和set方法以及notifier对应的事件和事件组)SomeIpGetterID = 3000   // somep属性的get方法 method_idSomeIpSetterID = 3001	// somep属性的set方法 method_idSomeIpNotifierID = 33010  // // somep属性的notifier对应的event_idSomeIpNotifierEventGroups = { 33010 }   // 事件组SomeIpAttributeReliable = true    // someip属性的通信方式(TCP/UDP)}attribute a1 {SomeIpGetterID = 3002SomeIpSetterID = 3003SomeIpNotifierID = 33011SomeIpNotifierEventGroups = { 33011 }SomeIpAttributeReliable = true}
}
// 只是将fidl中用户自定义类型在这里简单的申明了一下,实际测是下来是可以删除的,并不影响绑定层代码的生成和编译,删除也会生成绑定层的CommonTypes代码文件
define org.genivi.commonapi.someip.deployment for typeCollection commonapi.examples.CommonTypes {struct a1Struct {}struct a2Struct {}}
// 这部分为CommonAPI接口实例和SOME/IP服务提供者(provider)之间的关系
define org.genivi.commonapi.someip.deployment for provider as Service {   // 实例关系申明开始instance commonapi.examples.E02Attributes {     // E02Attributes接口实例1InstanceId = "commonapi.examples.Attributes"   // E02Attributes接口实例名称   SomeIpInstanceID = 22136    // someip的service instance_id    // 对应的SOMEIP服务instance_id}// 下面其实可以申明多个实例的
}    // 实例关系申明结束

三. Generate Code

  1. fidl生成的代码文件:在这里插入图片描述

  2. fdepl生成的代码文件:
    在这里插入图片描述

  3. 依赖关系:
    在这里插入图片描述
    ​ 用户应用程序是不需要关心绑定层的,用户应用程序直接和核心层配置文件生成的代码打交道,通过CommonAPI核心层的运行时Runtime创建核心层的Proxy和Stub(E02AttributesProxy,E02AttributesStub)。

​ 用户应用程序创建E02AttributesProxy和E02AttributesStub对象,这两个对象都是核心层的对象,实现了CommonAPI核心层的Proxy和Stub接口。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

​ 可以看到fidl生成出来的Proxy和Stub类都是核心层的Proxy和Stub接口的实现类。

​ 绑定层生成的Proxy和Stub类在程序开始运行的时候就将自己的构造函数注册到绑定层的工厂中,构造函数和CommonAPI的接口名进行绑定,如下:

在这里插入图片描述
在这里插入图片描述

​ INITIALIZER宏是用于展开其中的函数定义,将函数定义为跟随程序模块启动时自动加载运行,因此,INITIALIZER宏中定义的函数在程序的main函数之前就被执行了,INITIALIZER宏中会将fdepl生成的绑定层Proxy/Stub的初始化函数注册给SomeIP/DBus绑定层Factory (CommonAPI::SomeIP: : Factory),后者会在初始化的时候执行注册进来的所有绑定层Proxy/Stub的初始化函数,大致的时序如下:

在这里插入图片描述

​ 可以从上面的时序图看出来,注册给CommonAPI::SomeIP::Factory的函数(initializeHelloWorldSomeIPProxy)的用途有两个:

  1. 注册核心层interface和绑定层中间件服务之间的对应关系

    CommonAPI::SomeIP::AddressTranslator::get()->insert("local:commonapi.examples.E02Attributes:v1_0:commonapi.examples.Attributes",0x1235, 0x5678, 1, 0);    // AddressTranslator中记录了commonapi interface和Someip Service信息之间的对应关系
    
  2. 注册绑定层Proxy/Stub的创建函数

    CommonAPI::SomeIP::Factory::get()->registerProxyCreateMethod("commonapi.examples.E02Attributes:v1_0",    // CommonAPI Interface&createE02AttributesSomeIPProxy);     // 绑定层根据fdepl生成Proxy的创建函数
    
    CommonAPI::SomeIP::Factory::get()->registerStubAdapterCreateMethod("commonapi.examples.E02Attributes:v1_0",    // CommonAPI Interface&createE02AttributesSomeIPStubAdapter);     // 绑定层根据fdepl生成Stub的创建函数
    

​ 生成的核心层的Proxy和Stub代码的主要作用是根据fidl中定义的接口规范生成对应的接口客户端和服务端的接口代码,此外还有一个作用就是实现getInterface接口,这个接口会返回fidl中定义的服务的interface接口名称。创建核心层的Proxy和Stub时需要指定Common的Domain,interface接口名称和Instanceid,依据这三个参数核心层怎么知道该怎么创建绑定层的Proxy和Stub,有怎么知道绑定层的通信参数(例如service_id,instance_id)呢?

​ 这个就要依赖生成的绑定层代码在INITIALIZER宏注册的initialize函数来完成了,每个绑定层工厂中有一个map容器保存CommonAPI的interface和该绑定层通信地址的对应关系:

CommonAPI::SomeIP::AddressTranslator::get()->insert("local:commonapi.examples.E02Attributes:v1_0:commonapi.examples.Attributes",0x1235, 0x5678, 1, 0);    // AddressTranslator中记录了commonapi interface和Someip Service信息之间的对应关系CommonAPI::SomeIP::Factory::get()->registerProxyCreateMethod("commonapi.examples.E02Attributes:v1_0",    // CommonAPI Interface&createE02AttributesSomeIPProxy);     // 绑定层根据fdepl生成Proxy的创建函数

​ 核心层的createProxy/registerStub函数会将让手下目前支持的两个绑定层(DBus和SomeIP)去各自Factory中看下是否注册过这次传入的CommonAPI的interface,如果有的话就能找到对应的中间件的通信参数,创建中间件的服务实例,这部分代码逻辑在CommonAPI::Runtime::createProxyHelper中:

std::shared_ptr<Proxy>
Runtime::createProxyHelper(const std::string &_domain, const std::string &_interface, const std::string &_instance,const std::string &_connectionId, bool _useDefault) {std::lock_guard<std::mutex> itsLock(factoriesMutex_);for (auto factory : factories_) {   // 绑定层工厂容器,包括someip/dbus//如果通过AddressTranslator注册过,那么这里就能创建出绑定层的Proxystd::shared_ptr<Proxy> proxy= factory.second->createProxy(_domain, _interface, _instance, _connectionId);if (proxy)return proxy;}return (_useDefault && defaultFactory_ ?defaultFactory_->createProxy(_domain, _interface, _instance, _connectionId): nullptr);
}

​ 由于生成的Proxy代码已经在INITIALIZER中调用了registerProxyCreateMethod注册了创建绑定层Proxy的函数,因此绑定层工厂就可以找到该函数来创建绑定层Proxy,代码如下:

std::shared_ptr<CommonAPI::Proxy>    // CommonAPI-SomeIP绑定层工厂创建绑定层Proxy
Factory::createProxy(const std::string &_domain,    // CommonAPI的domainconst std::string &_interface, const std::string &_instance,    // CommonAPI的interface和instanceconst ConnectionId_t &_connectionId) {auto proxyCreateFunctionsIterator= proxyCreateFunctions_.lower_bound(_interface);if (proxyCreateFunctionsIterator!= proxyCreateFunctions_.end()) {std::string itsInterface(_interface);if (proxyCreateFunctionsIterator->first != _interface) {  // 首先根据interface找注册过的绑定层Proxy创建函数std::string itsInterfaceMajor(_interface.substr(0, _interface.find('_')));if (proxyCreateFunctionsIterator->first.find(itsInterfaceMajor) != 0)return nullptr;    //如果该Interface没有注册过绑定层创建函数,则直接返回nullptritsInterface = proxyCreateFunctionsIterator->first;}CommonAPI::Address address(_domain, itsInterface, _instance);Address someipAddress;   // 保存绑定层中间件通信的地址参数// 从AddressTranslator中找注册的绑定层Proxy的创建函数if (AddressTranslator::get()->translate(address, someipAddress)) {std::shared_ptr<Connection> itsConnection  // 这个Connection类封装了对vsomeip中间件的调用= getConnection(_connectionId);if (itsConnection) {std::shared_ptr<Proxy> proxy= proxyCreateFunctionsIterator->second(    //使用注册的prox创建函数生成fdepl中的绑定层ProxysomeipAddress, itsConnection);if (proxy && proxy->init())   // 初始化绑定层Proxyreturn proxy;}}}COMMONAPI_ERROR("Creating proxy for \"", _domain, ":", _interface, ":",_instance, "\" failed!");return nullptr;
}

四. 基本开发流程

  1. 安装vsomeip库

    https://blog.csdn.net/qq_43655213/article/details/129344035

  2. 安装commonapi代码生成工具

    https://blog.csdn.net/qq_43655213/article/details/129344035

  3. 编译并且安装commonapi代码库

    https://blog.csdn.net/qq_43655213/article/details/129344035

  4. 编写fidl和fdepl

    https://github.com/COVESA/capicxx-core-tools/blob/master/CommonAPI-Examples/E02Attributes/fidl/E02Attributes-SomeIP.fidl

    https://github.com/COVESA/capicxx-core-tools/blob/master/CommonAPI-Examples/E02Attributes/fidl/E02Attributes-SomeIP.fdepl

  5. 生成generated-code

    如下两行命令会在当前目录下创建src-gen目录并且生成核心层和绑定层的Proxy和Stub相关代码文件:

    commonapi-core-generator-linux-x86_64 -sk E02Attributes-SomeIP.fidl

    commonapi-someip-generator-linux-x86_64 -ll verbose E02Attributes-SomeIP.fdepl

  6. 编写客户端应用

    客户端:

    a. 指定创建的domain, instance, connection_name

    std::string domain = "local";
    std::string instance = "commonapi.examples.Attributes"; 
    std::string connection = "client-sample";
    

    b. 通过CommonAPI::Runtime创建Proxy

    std::shared_ptr < CommonAPI::Runtime > runtime = CommonAPI::Runtime::get();
    auto myProxy = runtime->buildProxyWithDefaultAttributeExtension<E02AttributesProxy, CommonAPI::Extensions::AttributeCacheExtension>(domain, instance, connection);
    // 等待对端stub可用
    std::cout << "Waiting for service to become available." << std::endl;
    while (!myProxy->isAvailable()) {std::this_thread::sleep_for(std::chrono::microseconds(10));
    }
    

    c. 调用Proxy中实现的fidl定义的接口

    服务端:

​ a. 指定创建的domain, instance, connection_name

std::string domain = "local";
std::string instance = "commonapi.examples.Attributes"; 
std::string connection = "service-sample";

​ b. 创建绑定层Stub对象

std::shared_ptr<E02AttributesStubImpl> myService = std::make_shared<E02AttributesStubImpl>();

​ c. 注册绑定层Stub对象到SomeIP绑定层工厂

while (!runtime->registerService(domain, instance, myService, connection)) {std::cout << "Register Service failed, trying again in 100 milliseconds..." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

​ 注意:E02AttributesStubImpl是需要用户自行实现fdepl生成的绑定层Stub抽象类的接口的,fdepl生成的绑定层Stub类是个抽象类,因为毕竟只有用户才知道该怎么实现这个接口,生成工具做不到的。

相关文章:

CommonAPI学习笔记-1

CommonAPI学习笔记-1 一. 整体结构 CommonAPI分为两层&#xff1a;核心层和绑定层&#xff0c;使用了Franca来描述服务接口的定义和部署&#xff0c;而Franca是一个用于定义和转换接口的框架&#xff08;https://franca.github.io/franca/&#xff09;。 ​ 核心层和通信中间…...

从入门到精通:RabbitMQ的深度探索与实战应用

目录 一、RabbitMQ 初相识 二、基础概念速览 &#xff08;一&#xff09;消息队列是什么 &#xff08;二&#xff09;RabbitMQ 核心组件 三、RabbitMQ 基本使用 &#xff08;一&#xff09;安装与环境搭建 &#xff08;二&#xff09;简单示例 &#xff08;三&#xff09;…...

深入理解若依RuoYi-Vue数据字典设计与实现

深入理解若依数据字典设计与实现 一、Vue2版本主要文件目录 组件目录src/components&#xff1a;数据字典组件、字典标签组件 工具目录src/utils&#xff1a;字典工具类 store目录src/store&#xff1a;字典数据 main.js&#xff1a;字典数据初始化 页面使用字典例子&#xf…...

Cursor 帮你写一个小程序

Cursor注册地址 首先下载客户端 点击链接下载 1 打开微信开发者工具创建一个小程序项目 选择TS-基础模版 官方 2 然后使用Cursor打开小程序创建的项目 3 在CHAT聊天框输入自己的需求 比如 小程序功能描述&#xff1a;吃什么助手 项目名称&#xff1a; 吃什么小程序 功能目标…...

进程控制的学习

目录 1.进程创建 1.1 fork函数 1.2 fork函数返回值 1.3 写时拷贝 1.4 fork 常规用法 1.5 fork 调用失败的原因 2. 进程终止 2.1 进程退出场景 2.2 进程常见退出方法 2.2.1 从main 返回 2.2.2 echo $&#xff1f; 查看进程退出码 2.2.2.1 我们如何得到退出码代表的含…...

一文讲解Java中的接口和抽象类

抽象类和接口有什么区别&#xff1f; 一个类只能继承一个抽象类&#xff1b;但一个类可以实现多个接口。所以我们在新建线程类的时候&#xff0c;一般推荐使用Runnable接口的方式&#xff0c;这样线程类还可以继承其他类&#xff0c;而不单单是Thread类&#xff1b;抽象类符合…...

Vue 3 30天精进之旅:Day 05 - 事件处理

引言 在前几天的学习中&#xff0c;我们探讨了Vue实例、计算属性和侦听器。这些概念为我们搭建了Vue应用的基础。今天&#xff0c;我们将专注于事件处理&#xff0c;这是交互式Web应用的核心部分。通过学习如何在Vue中处理事件&#xff0c;你将能够更好地与用户进行交互&#…...

STM32完全学习——RT-thread在STM32F407上移植

一、写在前面 关于源码的下载&#xff0c;以及在KEIL工程里面添加操作系统的源代码&#xff0c;这里就不再赘述了。需要注意的是RT-thread默认里面是会使用串口的&#xff0c;因此需要额外的进行串口的初始化&#xff0c;有些人可能会问&#xff0c;为什么不直接使用CubMAX直接…...

Shodan Dorks安装指南,通过Shodan搜索漏洞

Shodan Dorks是一种基于Shodan的工具&#xff0c;不知道Shodan是什么的不必阅读下面的内容。简单的说就是&#xff0c;利用预定义的查询&#xff08;dorks&#xff09;&#xff0c;通过Shodan轻松搜索漏洞和机密信息。 推荐渗透测试人员自行测试。 安装方法&#xff1a; 1.确…...

poi在word中打开本地文件

poi版本 5.2.0 方法1&#xff1a;使用XWPFFieldRun&#xff08;推荐&#xff09; 比如打开当前相对路径的aaaaa.docx XWPFFieldRun run paragraph.createFieldRun();CTRPr ctrPr run.getCTR().addNewRPr();CTFonts font ctrPr.addNewRFonts();// 设置字体font.setAscii(&quo…...

Linux查看服务器的内外网地址

目录&#xff1a; 1、内网地址2、外网地址3、ping时显示地址与真实不一致 1、内网地址 ifconfig2、外网地址 curl ifconfig.me3、ping时显示地址与真实不一致 原因是dns缓存导致的&#xff0c;ping这种方法也是不准确的&#xff0c;有弊端不建议使用&#xff0c;只适用于测试…...

OAuth1和OAuth2授权协议

OAuth 1 授权协议 1. 概述 OAuth1 是 OAuth 标准的第一个正式版本&#xff0c;它通过 签名和令牌 的方式&#xff0c;实现用户授权第三方访问其资源的功能。在 OAuth1 中&#xff0c;安全性依赖于签名机制&#xff0c;无需传递用户密码。 2. 核心特性 使用 签名&#xff08…...

DeepSeek学术题目选择效果怎么样?

论文选题 一篇出色的论文背后&#xff0c;必定有一个“智慧的选题”在撑腰。选题足够好文章就能顺利登上高水平期刊&#xff1b;选题不行再精彩的写作也只能“当花瓶”。然而许多宝子们常常忽视这个环节&#xff0c;把大量时间花在写作上&#xff0c;选题时却像抓阄一样随便挑一…...

数据结构(一)顺序表和链表

目录 1. 时间复杂度和空间复杂度 2. 顺序表 3. 链表 1. 时间复杂度和空间复杂度 如何估算一个算法的效率高低一般就是使用到时间复杂度和空间复杂度; 时间复杂度是评价一个算法运行快慢的, 而空间复杂度是算法额外需要空间大小. 1.1 时间复杂度的计算: 准确来说时间复杂度是…...

单相可控整流电路——单相桥式全控整流电路

以下是关于单相桥式整流电路的介绍&#xff1a; 电路构成&#xff08;带阻性负载的工作情况&#xff09; - 二极管&#xff1a;是电路0的核心元件&#xff0c;通常采用四个同型号或根据需求选择不同型号的二极管&#xff0c;如1N4001、1N4007等&#xff0c;如图Vt1和Vt4是一对…...

DeepSeek-R1:性能对标 OpenAI,开源助力 AI 生态发展

DeepSeek-R1&#xff1a;性能对标 OpenAI&#xff0c;开源助力 AI 生态发展 在人工智能领域&#xff0c;大模型的竞争一直备受关注。最近&#xff0c;DeepSeek 团队发布了 DeepSeek-R1 模型&#xff0c;并开源了模型权重&#xff0c;这一举动无疑为 AI 领域带来了新的活力。今…...

【Maui】提示消息的扩展

文章目录 前言一、问题描述二、解决方案三、软件开发&#xff08;源码&#xff09;3.1 消息扩展库3.2 消息提示框使用3.3 错误消息提示使用3.4 问题选择框使用 四、项目展示 前言 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架&#xff0c;用于使用 C# 和 XAML 创建本机移…...

001 mybatis入门

文章目录 mybatis是什么ORM是什么ORM框架和MyBatis的区别#{}和${}的区别编码流程UserDaoImpl.javaUserDao.javaUser.javadb.propertiesSqlMapConfig.xmlUserMapper.xmlMybatisTest.javapom.xmluser.sql 表现层 SpringMVC 业务层 Spring 持久层 Mybatis https://mybatis.org/myb…...

tomcat的accept-count、max-connections、max-threads三个参数的含义

tomcat的accept-count、max-connections、max-threads三个参数的含义 tomcat的accept-count、max-connections、max-threads三个参数的含义 max-connections&#xff1a;最大连接数 最大连接数是指&#xff0c;同一时刻&#xff0c;能够连接的最大请求数 需要注意的是&#x…...

8.2 从看图识字到智能解读:GPT-4 with Vision 开启多模态 AI 新纪元

从看图识字到智能解读:GPT-4 with Vision 开启多模态 AI 新纪元 引言:AI 的多模态跃迁 随着人工智能技术的快速发展,我们正迈入一个新的智能交互时代。传统的 AI 模型主要聚焦于文本处理,而多模态 AI 模型如 GPT-4 with Vision(GPT-4V) 则能够同时处理图像和文本。GPT-4…...

.strip()用法

.strip("") 是 Python 字符串方法 strip() 的一个用法&#xff0c;它会去除字符串两端指定字符集中的字符。 基本语法&#xff1a; string.strip([chars])string: 这是你要操作的字符串。chars: 可选参数&#xff0c;表示你想要去除的字符集&#xff08;默认为空格…...

蓝桥杯例题三

无论前方困难如何重重&#xff0c;我们都要坚定信念&#xff0c;勇往直前。面对挑战和困境&#xff0c;不要退缩&#xff0c;不要放弃&#xff0c;要坚持走下去。当我们感到疲惫时&#xff0c;要告诉自己&#xff1a;“我可以&#xff0c;我一定行&#xff01;”相信自己的实力…...

关于pygame窗口输入法状态异常切换现象的分析报告

一、问题描述 1.1 需求说明 我们准备使用Pygame开发一个键盘输入测试程序&#xff0c;需要确保输入时窗口始终处于英文输入模式&#xff0c;也就是禁止中文输入&#xff1b; 1.2 现象描述 控制台种显示&#xff0c;程序在初始化时&#xff0c;会有两次IMM状态切换操作&…...

【JavaEE进阶】应用分层

目录 &#x1f38b;序言 &#x1f343;什么是应用分层 &#x1f38d;为什么需要应用分层 &#x1f340;如何分层(三层架构) &#x1f384;MVC和三层架构的区别和联系 &#x1f333;什么是高内聚低耦合 &#x1f38b;序言 通过上⾯的练习,我们学习了SpringMVC简单功能的开…...

两数相加:链表操作的基础与扩展

两数相加&#xff1a;链表操作的基础与扩展 引言 链表&#xff08;Linked List&#xff09;是一种灵活且高效的数据结构&#xff0c;特别适用于动态增删操作。无论是初学者还是资深程序员&#xff0c;链表的基本操作都是算法学习中的重要一环。而 “两数相加” 问题则是链表操…...

ChatGPT从数据分析到内容写作建议相关的46个提示词分享!

在当今快节奏的学术环境中&#xff0c;研究人员面临着海量的信息和复杂的研究任务。幸运的是&#xff0c;随着人工智能技术的发展&#xff0c;像ChatGPT这样的先进工具为科研人员提供了强大的支持。今天就让我们一起探索如何利用ChatGPT提升研究效率进一步优化研究流程。 ChatG…...

解析“in the wild”——编程和生活中的俚语妙用

解析“in the wild”——编程和生活中的俚语妙用 看下面的技术文章中遇到 in the wild这个词&#xff0c;想要研究一下&#xff0c;遂产生此文。 Are there ever pointers to pointers to pointers? There is an old programming joke which says you can rate C programmers…...

rocketmq原理源码分析之控制器模式- dledger

简介 RocketMQ 4.5 版本之前&#xff0c;RocketMQ 的broker是 Master/Slave部署架构&#xff0c;一组 broker 有一个 Master &#xff0c;有0到若干Slave&#xff0c;Slave复制Master消息存储&#xff0c;随时替代下线的Master。Master/Slave部署架构提供一定的高可用性&#x…...

Hello Moto

“Hello Moto” 是摩托罗拉&#xff08;Motorola&#xff09;的一句经典广告口号&#xff0c;用于推广其品牌和产品&#xff0c;特别是在手机领域。以下是它的含义和背景&#xff1a; 1. 品牌宣传的标志性语句 直白含义&#xff1a;简单地向摩托罗拉打招呼&#xff08;“Hell…...

存储基础 -- SCSI命令格式与使用场景

SCSI命令格式与使用场景 1. SCSI命令描述符块&#xff08;CDB&#xff09; 1.1 CDB基本概念 SCSI命令通过**命令描述符块&#xff08;CDB, Command Descriptor Block&#xff09;**表示。 CDB长度&#xff1a;SCSI命令根据使用场景有不同长度的CDB&#xff0c;常见的有6字节…...

ceph基本概念,架构,部署(一)

一、分布式存储概述 1.存储分类 存储分为封闭系统的存储和开放系统的存储&#xff0c;而对于开放系统的存储又被分为内置存储和外挂存储。 外挂存储又被细分为直连式存储(DAS)和网络存储(FAS)&#xff0c;而网络存储又被细分网络接入存储(NAS)和存储区域网络(SAN)等。 DAS(D…...

CNN-GRU卷积门控循环单元时间序列预测(Matlab完整源码和数据)

CNN-GRU卷积门控循环单元时间序列预测&#xff08;Matlab完整源码和数据&#xff09; 目录 CNN-GRU卷积门控循环单元时间序列预测&#xff08;Matlab完整源码和数据&#xff09;预测效果基本介绍CNN-GRU卷积门控循环单元时间序列预测一、引言1.1、研究背景与意义1.2、研究现状1…...

Ubuntu 顶部状态栏 配置,gnu扩展程序

顶部状态栏 默认没有配置、隐藏的地方 安装使用Hide Top Bar 或Just Perfection等进行配置 1 安装 sudo apt install gnome-shell-extension-manager2 打开 安装的“扩展管理器” 3. 对顶部状态栏进行配置 使用Hide Top Bar 智能隐藏&#xff0c;或者使用Just Perfection 直…...

React应用深度优化与调试实战指南

一、渲染性能优化进阶 1.1 精细化渲染控制 typescript 复制 // components/HeavyComponent.tsx import React, { memo, useMemo } from react;interface Item {id: string;complexData: {// 复杂嵌套结构}; }const HeavyComponent memo(({ items }: { items: Item[] }) &g…...

Spring中的事件和事件监听器是如何工作的?

目录 一、事件&#xff08;Event&#xff09; 二、事件发布器&#xff08;Event Publisher&#xff09; 三、事件监听器&#xff08;Event Listener&#xff09; 四、使用场景 五、总结 以下是关于Spring中的事件和事件监听器的介绍与使用说明&#xff0c;结合了使用场景&…...

Vue.js组件开发-实现多个文件附件压缩下载

在 Vue 项目中实现多个附件压缩下载&#xff0c;可以借助 jszip 库来创建压缩文件&#xff0c;以及 file-saver 库来保存生成的压缩文件。 步骤 1&#xff1a;安装依赖 首先&#xff0c;在 Vue 项目中安装 jszip 和 file-saver&#xff1a; npm install jszip file-saver步骤…...

基于dlib/face recognition人脸识别推拉流实现

目录 一.环境搭建 二.推拉流代码 三.人脸检测推拉流 一.环境搭建 1.下载RTSP服务器MediaMTX与FFmpeg FFmpeg是一款功能强大的开源多媒体处理工具,而MediaMTX则是一个轻量级的流媒体服务器。两者结合,可以实现将本地视频或者实时摄像头画面推送到RTSP流,从而实现视频…...

qt QNetworkRequest详解

1、概述 QNetworkRequest是Qt网络模块中的一个核心类&#xff0c;专门用于处理网络请求。它封装了网络请求的所有关键信息&#xff0c;包括请求的URL、HTTP头部信息等&#xff0c;使得开发者能够方便地在Qt应用程序中执行网络操作&#xff0c;如文件下载、网页内容获取等。QNe…...

uvm timeout的哪些事

如下图所示&#xff0c;设置timeout并未生效&#xff0c;原因多了一个空格&#xff0c;坑 进一步分析&#xff0c;默认是overidable的 是否加括号呢&#xff0c;如下所示&#xff0c;这两个造型都可以&#xff0c;中间有空格也行 那么&#xff0c;我加上单位可以吗&#xff0c;…...

JavaScript赋能智能网页设计

构建AI驱动的实时风格迁移系统 案例概述 本案例将实现一个基于深度学习的实时图像风格迁移系统&#xff0c;通过浏览器端神经网络推理实现以下高级特性&#xff1a; WebAssembly加速的ONNX模型推理 WebGL Shader实现的风格混合算法 WebRTC实时视频流处理 基于Web Workers的…...

全面了解 Web3 AIGC 和 AI Agent 的创新先锋 MelodAI

不管是在传统领域还是 Crypto&#xff0c;AI 都是公认的最有前景的赛道。随着数字内容需求的爆炸式增长和技术的快速迭代&#xff0c;Web3 AIGC&#xff08;AI生成内容&#xff09;和 AI Agent&#xff08;人工智能代理&#xff09;正成为两大关键赛道。 AIGC 通过 AI 技术生成…...

leetcode_链表 234.回文链表

234.回文链表 给你一个单链表的头节点head&#xff0c;请你判断该链表是否为回文链表。如果是, 返回 true ; 否则, 返回false。思路&#xff1a; 找到中间节点(快慢指针法)反转后半部分的链表比较前半部分和后半部分链表 # Definition for singly-linked list. # class List…...

cloc下载和使用

cloc&#xff08;Count Lines of Code&#xff09;是一个跨平台的命令行工具&#xff0c;用于计算代码行数。以下是下载和使用 cloc 的步骤&#xff1a; 下载 cloc 对于 Windows 用户&#xff1a; 访问 cloc 的 GitHub 仓库&#xff1a;https://github.com/AlDanial/cloc在 …...

在 Windows 系统上,将 Ubuntu 从 C 盘 迁移到 D 盘

在 Windows 系统上&#xff0c;如果你使用的是 WSL&#xff08;Windows Subsystem for Linux&#xff09;并安装了 Ubuntu&#xff0c;你可以将 Ubuntu 从 C 盘 迁移到 D 盘。迁移过程涉及导出当前的 Ubuntu 发行版&#xff0c;然后将其导入到 D 盘的目标目录。以下是详细的步骤…...

【Redis】Redis入门以及什么是分布式系统{Redis引入+分布式系统介绍}

文章目录 介绍redis的引入 分布式系统单机架构应用服务和数据库服务分离【负载均衡】引入更多的应用服务器节点 单机架构 分布式是什么 数据库分离和负载均衡 理解负载均衡 数据库读写分离 引入缓存 数据库分库分表 引入微服务 介绍 The open source, in-memory data store us…...

wow-agent---task4 MetaGPT初体验

先说坑&#xff1a; 1.使用git clone模式安装metagpt 2.模型尽量使用在线模型或本地高参数模型。 这里使用python3.10.11调试成功 一&#xff0c;安装 安装 | MetaGPT&#xff0c;参考这里的以开发模型进行安装 git clone https://github.com/geekan/MetaGPT.git cd /you…...

Leetcode::3432. 统计元素和差值为偶数的分区方案

3432. 统计元素和差值为偶数的分区方案 已解答 简单 相关企业 提示 给你一个长度为 n 的整数数组 nums 。 分区 是指将数组按照下标 i &#xff08;0 < i < n - 1&#xff09;划分成两个 非空 子数组&#xff0c;其中&#xff1a; 左子数组包含区间 [0, i] 内的所…...

linux如何修改密码,要在CentOS 7系统中修改密码

要在CentOS 7系统中修改密码&#xff0c;你可以按照以下步骤操作&#xff1a; 步骤 1: 登录到系统 在登录提示符 localhost login: 后输入你的用户名。输入密码并按回车键。 步骤 2: 修改密码 登录后&#xff0c;使用 passwd 命令来修改密码&#xff1a; passwd 系统会提…...

GIS与相关专业软件汇总

闲来无事突然想整理一下看看 GIS及相关领域 究竟有多少软件或者工具包等。 我询问了几个AI工具并汇总了一个软件汇总&#xff0c;不搜不知道&#xff0c;一搜吓一跳&#xff0c;搜索出来了大量的软件&#xff0c;大部分软件或者工具包都没有见过&#xff0c;不知大家还有没有要…...

云计算架构学习之LNMP架构部署、架构拆分、负载均衡-会话保持

一.LNMP架构部署 1.1. LNMP服务搭建 1.磁盘信息 2.内存 3.负载信息 4.Nginx你们公司都用来干嘛 5.文件句柄(文件描述符 打开文件最大数量) 6.你处理过系统中的漏洞吗 SSH漏洞 7.你写过什么shell脚本 8.监控通过什么告警 zabbix 具体监控哪些内容 9.mysql redis查询 你好H…...