OpenHarmony 实战开发——使用分布式菜单创建点餐神器

随着社会的进步与发展,科技手段的推陈出新,餐饮行业也在寻求新的突破与变革,手机扫描二维码点餐系统已经成为餐饮行业的未来趋势,发展空间巨大;扫码点餐,是“互联网+餐饮”潮流的产物,可以有效地为餐厅节省人力成本,提高顾客点餐用餐效率,节省顾客时间,提高餐厅翻台率。

但是,一些老年人也在面对扫码点餐时犯了难;还有些消费者不愿意使用扫码点餐,是担心个人信息泄露等安全问题。

如此,我们设计了一款分布式菜单应用,不需要个人去关注公众号或下载小程序,服务员会提供几个点单的平板,连接店铺网络,局域网内通信,这样大家点单、查看订单详情等都不受网络限制。先上效果:

如上动图:可由一人拉起点单平板上的点单应用,大家可同时点单,点击菜品图片进入菜品详情页面,选择口味后确认,就是一次点单完成,并自动返回到菜单首页;此时可看到下方购物车数量和总额的变化,点击下方"点好了" 可进入订单详细,并通过分布式数据库让其他人也查看订单详情,从订单详情返回到点单页后,可再进行叠加点单。

下面是 Demo 的开发说明。

一、开发说明

基于 OpenAtom OpenHarmony(以下简称“OpenHarmony”) 3.1 beta 版本,并结合方舟开发框架(ArkUI)、分布式组网、分布式数据库等特性,使用 eTS 语言开发的一款分布式菜单应用;主要体现了 OpenHarmony 分布式数据库特性,根据设计师提供的 UX ,首先就要考虑分布式数据库应该要怎么设计,需要包含哪些元素;其次 demo 是没有后台服务端,结合 ArkUI 框架,需要思考多个页面间数据怎么传递。

Demo 主要包含菜单首页、菜单详情页和订单详情页,以及加入菜单分布式数据库和结算订单分布式数据库。三个页面都需要订单列表数据,因为目前 ArkUI 框架在 app.ets 定义数据,其他页面不能直接引用,所以通过 router.push 的方法,带上 param 的参数,将数据在页面间进行传递。

两个分布式数据库,一个是订单列表数据,订单列表需要根据 UX 提供的设计图,来确认数据库中的元素,本 Demo 中的订单页面数据信息其他包括菜品的信息(图片、名称、份数、辣度等)以及点单人的信息(图片、名称和点单的数量);另一个是将下单成功通知所有人。

Demo 也还有很多待完善的点,比如:点击加/减的图标进行菜单的加减、一键清空订单、以及 Demo 是否有更好的方案来达到更好的点单体验等等,期待更多的读者们来完善。

代码结构如下图:

├─entry
│  └─src
│      └─main
│          │  config.json  // 应用配置文件
│          │  
│          ├─ets
│          │  └─MainAbility
│          │      │  app.ets  // 应用程序主入口
│          │      │  
│          │      ├─model
│          │      │      CommonLog.ets  // 日志类
│          │      │      MenuData.ets  // 初始化菜单数据类
│          │      │      MenuListDistributedData.ets  // 加入菜单分布式数据库
│          │      │      RemoteDeviceManager.ets  // 分布式拉起设备管理类
│          │      │      SubmitData.ets   // 结算订单分布式数据库
│          │      │      
│          │      └─pages
│          │              detailedPage.ets // 菜品详细页面
│          │              index.ets // 首页
│          │              menuAccount.ets // 订单详情页面
│          │              
│          └─resources
│              ├─base
│              │  ├─element
│              │  │      string.json
│              │  │      
│              │  ├─graphic
│              │  ├─layout
│              │  ├─media   // 存放媒体资源
│              │  │      icon.png
│              │  │      icon_add.png
│              │  │      icon_back.png
│              │  │      icon_cart.png

二、页面编写

2.1 点单首页

效果图如上,可以分为四部分:

1)顶部页标签

@Component
struct PageInfo {build() {Flex() {Text('点单页').fontSize('36lpx')}.padding({ left: '48lpx', top: '28lpx' }).width('100%').height('10%').backgroundColor('#FFFFFF')}
}

2)用户信息

• 主要用到 Flex 容器 Image 和 Text 组件;

• 用户名称和头像图标,根据设备序列号不同,可展示不同的名称和图标;

• 点击右上角分享的小图标,可分布式拉起局域网内的另一台设备。

@Component
struct MemberInfo {@Consume userImg: Resource@Consume userName: stringaboutToAppear() {// 根据设备序列号不同,展示不同的名称和图标CommonLog.info('==serial===' + deviceInfo.serial);if (deviceInfo.serial == '150100384754463452061bba4c3d670b') {this.userImg = $r("app.media.icon_user")this.userName = 'Sunny'}else {this.userImg = $r("app.media.icon_user_another")this.userName = 'Jenny'}}build() {Flex({ direction: FlexDirection.Column }) {Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {Image(this.userImg).width('96lpx').height('96lpx').margin({ right: '18lpx' })Text(this.userName).fontSize('36lpx').fontWeight(FontWeight.Bold).flexGrow(1)Image($r("app.media.icon_share")).width('64lpx').height('64lpx')}// 打开分布式设备列表.onClick(() => {this.DeviceDialog.open()}).layoutWeight(1).padding({ left: '48lpx', right: '48lpx' })Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {Column() {Text('124').fontSize('40lpx').margin({ bottom: '24lpx' })Text('积分').fontSize('22lpx').opacity(0.4)}.flexGrow(1)Column() {Text('0').fontSize('40lpx').margin({ bottom: '24lpx' })Text('优惠劵').fontSize('22lpx').opacity(0.4)}.flexGrow(1)Column() {Image($r("app.media.icon_member")).width('48lpx').height('48lpx').margin({ bottom: '24lpx' })Text('会员码').fontSize('22lpx').fontColor('#000000').opacity(0.4)}.flexGrow(1)}.layoutWeight(1)}.width('93%').height('25%').borderRadius('16lpx').backgroundColor('#FFFFFF').margin({ top: '24lpx', bottom: '32lpx' })}
}

3)列表展示

• 主要用到 Flex 容器和 Scroll 容器 Image 和 Text 组件;

• 从首页点击列表进入菜品详细页面,点菜成功后会自动返回首页,此时列表需要动态更新菜品的数量。

@Component
struct MenuHome {private specialty: any[]private winterNew: any[]private classic: any[]private soup: any[]private menuItems: MenuData[]private titleList = ['招牌菜', '冬季新品', '下饭菜', '汤品']@State name: string = '招牌菜'build() {Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start }) {Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceAround }) {ForEach(this.titleList, item => {Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {Text(item).fontSize('24lpx')}.padding({ left: '24lpx' }).backgroundColor(this.name == item ? '#1A006A3A' : '#FFFFFF').height('160lpx').onClick(() => {this.name = itemif (this.name == '招牌菜') {this.menuItems = initializeOnStartup(this.specialty);}else if (this.name == '冬季新品') {this.menuItems = initializeOnStartup(this.winterNew);}else if (this.name == '下饭菜') {this.menuItems = initializeOnStartup(this.classic);}else if (this.name == '汤品') {this.menuItems = initializeOnStartup(this.soup);}})}, item => item)}.width('20%').backgroundColor('#FFFFFF')Flex({ direction: FlexDirection.Column }) {Text(this.name).fontSize('32lpx').fontWeight(FontWeight.Bold).opacity(0.4).height('8%')Scroll() {Column() {List() {ForEach(this.menuItems, item => {ListItem() {MenuListItem({ menuItem: item })}}, item => item.id.toString())}}}.height('92%')}.margin({ left: '10lpx' }).width('75%')}.height('50%')}
}

4)底部总额

• 主要用到 Flex 容器和 Stack 容器 Image 和 Text 组件;

• 从首页点击列表进入菜品详细页面,点菜成功后会自动返回首页,更新订单数量和总额;

• 点击底部总额框,将订单列表加入分布式数据库,@entry 模拟监听数据库变化,拉起订单列表详情页面。

@Component
struct TotalInfo {@Consume TotalMenu: any[];private total: number = 0;private amount: number = 0;private remoteData: MenuListDataaboutToAppear() {for (var index = 0; index < this.TotalMenu.length; index++) {this.total = this.total + this.TotalMenu[index].price * this.TotalMenu[index].quantitythis.amount = this.amount + this.TotalMenu[index].quantity}}build() {Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {Stack({ alignContent: Alignment.Center }) {Image($r("app.media.icon_cart")).width('96lpx').height('96lpx').margin({ left: '22lpx' })Text(this.amount.toString()).backgroundColor('#F84747').borderRadius('30plx').fontSize('24plx').textAlign(TextAlign.Center).fontColor('#FFFFFF').width('50lpx').height('50lpx').margin({ left: '100lpx', bottom: '85lpx' })}.width('150lpx').height('150lpx')Text('¥').fontSize('22lpx').fontColor('#006A3A').margin({ left: '22lpx' })Text(this.total.toString()).fontSize('40lpx').fontColor('#006A3A').flexGrow(1)Text('点好了').height('100%').width('35%').fontColor('#FFFFFF').backgroundColor('#F84747').textAlign(TextAlign.Center)}// 将总的订单数据,加入分布式数据库.onClick(() => {this.remoteData.putData("menu_list", this.TotalMenu)}).width('100%').height('10%').backgroundColor('#FFFFFF')}
}

2.2 菜品详情页

效果图如上,可以分为三部分:

1)顶部页标签

@Component
struct PageInfo {build() {Flex() {Text('点单页').fontSize('36lpx')}.padding({ left: '48lpx', top: '28lpx' }).width('100%').height('10%').backgroundColor('#FFFFFF')}
}

2)菜单详情

• 主要用到 Flex 容器 Image 和 Text 组件 Button 组件;
• 辣度可以选择。

@Component
struct detailInfo {private menuItemprivate spicyList = ['正常辣', '加辣', '少辣']@State spicy: string = '正常辣'private TotalMenu: any[]private index = 0private userName: stringbuild() {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) {Flex({ direction: FlexDirection.Row }) {Button().backgroundColor('#006A3A ').width('8lpx').height('48lpx').margin({ right: '12lpx' })Text('辣度')}.margin({ left: '44lpx', top: '48lpx', bottom: '32lpx' })Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceEvenly }) {ForEach(this.spicyList, item => {Button(item).fontSize('28lpx').height('60lpx').width('156lpx').borderRadius('12lpx').backgroundColor(this.spicy == item ? '#006A3A' : '#0D000000').fontColor(this.spicy == item ? '#FFFFFF' : '#000000').onClick(() => {this.spicy = item})}, item => item)}}.margin({ top: '56lpx' }).width('92%').height('50%').borderRadius('16lpx').backgroundColor('#FFFFFF')}}
}

3)点击按钮

• 点击选好了,需要判断该菜品是否已经在总订单里面,并判断是哪一个用户添加,根据判断,做出相应的增加。

Button('选好了').fontSize('36lpx').width('80%').height('7%').backgroundColor('#F84747').onClick(() => {for (this.index = 0; this.index < this.TotalMenu.length; this.index++) {if (this.TotalMenu[this.index].name == this.menuItem.name && this.TotalMenu[this.index].spicy == this.spicy) {this.TotalMenu[this.index].quantity = this.TotalMenu[this.index].quantity + 1;if (this.userName == 'Sunny') {this.TotalMenu[this.index].userNumber = this.TotalMenu[this.index].userNumber + 1;} else if (this.userName == 'Jenny') {this.TotalMenu[this.index].anotherUserNumber = this.TotalMenu[this.index].anotherUserNumber + 1;}break;}}// 菜名不一样,辣度不一样,都需要重新push到列表里面if (this.index == this.TotalMenu.length) {this.menuItem.spicy = this.spicy;this.menuItem.quantity = 1;//根据不用的用户名称,if (this.userName == 'Sunny') {this.menuItem.userNumber = 1;} else if (this.userName == 'Jenny') {this.menuItem.anotherUserNumber = 1;}this.TotalMenu.push(this.menuItem);}router.push({uri: 'pages/index',params: { menuItem: this.menuItem, TotalMenu: this.TotalMenu }})}).margin({ top: '10%' })

2.3 订单详情页

效果如上,可以分为三部分:

** 1)订单列表**

• 主要用到 Flex 容器 Image 和 Text 组件 Button 组件;

• 展示不同用户加入菜单数量。

@Component
struct TotalItem {private totalMenu: MenuDatabuild() {Flex({ direction: FlexDirection.Column }) {Flex({ direction: FlexDirection.Row, alignContent: FlexAlign.Start, justifyContent: FlexAlign.Start }) {if (this.totalMenu.userNumber > 0) {Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {Image(this.totalMenu.userImg).width('96lpx').height('96lpx')Text(this.totalMenu.userName).fontSize('36lpx').fontWeight(FontWeight.Bold).margin({ left: '12lpx' }).flexGrow(1)Text(this.totalMenu.userNumber.toString()).fontSize('32lpx').margin({ right: '11plx' })}.height('150lpx')}if (this.totalMenu.anotherUserNumber > 0) {Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {Image(this.totalMenu.anotherUserImg).width('96lpx').height('96lpx')Text(this.totalMenu.anotherUserName).fontSize('36lpx').fontWeight(FontWeight.Bold).margin({ left: '12lpx' }).flexGrow(1)Text(this.totalMenu.anotherUserNumber.toString()).fontSize('32lpx').margin({ right: '11plx' })}.height('150lpx')}}.margin({ top: '12lpx' }).borderRadius('16lpx').padding({ left: '3%', right: '3%', top: '2%' }).backgroundColor('#FFFFFF')}
}

2)下单按钮
• 点击下单,将"submitOk" 加入分布式数据库,监听数据库变化后,弹出自定义对话框。

@Component
struct SubmitList {private remoteData: SubmitDataprivate SubmitOK: any[] = [{submit: "submitOk"}];build() {Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Text('下单').fontSize('36lpx').fontColor('#FFFFFF')}.width('100%').height('10%').backgroundColor('#F84747').onClick(() => {this.remoteData.putData("submit", this.SubmitOK)}).margin({ top: '5%' })}
}

3)自定义弹框

• 通过 @CustomDialog 装饰器来创建自定义弹窗,使用方式可参考 自定义弹窗;

• 规则弹窗效果如下,弹窗组成由一个 Image 和两个 Text 竖向排列组成;

• 在 build()下使用 Flex 容器来包裹,组件代码如下:

@CustomDialog
struct SubmitDialog {private controller: CustomDialogControllerbuild() {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {Flex({ justifyContent: FlexAlign.Center }) {Image($r("app.media.icon_success")).width('100lpx').height('80lpx')}.flexGrow(1)Text('下单成功').fontSize('36lpx').fontColor('#000000').flexGrow(1)Text('*温馨提示:菜品具体售卖情况请以店面实际情况为准哦~').fontSize('22lpx').opacity(0.6).fontColor('#000000').padding({ left: '10lpx', right: '10lpx' })}.height('300lpx').width('100%').padding({ top: '50lpx', bottom: '20lpx' })}
}

• 在 @entry 模块创建 CustomDialogController 对象并传入弹窗所需参数,设置点击允许点击遮障层退出,通过 open() 方法,显示弹窗。

SubmitDialog: CustomDialogController = new CustomDialogController({builder: SubmitDialog(),autoCancel: true})
aboutToAppear() {this.remoteData.createManager(() => {let self = thisvar data;if (JSON.stringify(self.remoteData.dataItem).length > 0) {data = self.remoteData.dataItem;CommonLog.info("======submit==" + data[0].submit);if (data[0].submit == "submitOk") {this.SubmitDialog.open()}}}, "com.distributed.order", "submit")}

三、分布式数据管理

OpenHarmony 技术特性包括分布式数据管理、分布式任务调度等;分布式数据管理基于分布式软总线的能力,实现应用程序数据和用户数据的分布式管理。用户数据不再与单一物理设备绑定,业务逻辑与数据存储分离,跨设备的数据处理如同本地数据处理一样方便快捷,让开发者能够轻松实现全场景、多设备下的数据存储、共享和访问,为打造一致、流畅的用户体验创造了基础条件。

3.1 开发步骤

分布式数据管理要求两个或多个设备在同一网络。开发步骤:

1)导入模块

import distributedData from '@ohos.data.distributedData';

2)创建一个 KVManager 对象实例,用于管理数据库对象;注意 bundleName 需要修改为自己的包名。

let kvManager;
try {const kvManagerConfig = {bundleName : 'com.distributed.order',userInfo : {userId : '0',userType : distributedData.UserType.SAME_USER_ID}}distributedData.createKVManager(kvManagerConfig, function (err, manager) {if (err) {console.log("createKVManager err: "  + JSON.stringify(err));return;}console.log("createKVManager success")kvManager = manager});
} catch (e) {console.log("An unexpected error occurred. Error:" + e);
}

3)通过指定 Options 和 storeId,创建并获取 KVStore 数据库,如下是参数说明;需要先通过 createKVManager 构建一个 KVManager 实例。

let kvStore;
let kvManager;
try {const options = {createIfMissing : true,encrypt : false,backup : false,autoSync : true,kvStoreType : distributedData.KVStoreType.SINGLE_VERSION,securityLevel : distributedData.SecurityLevel.S2,};kvManager.getKVStore('storeId', options, function (err, store) {if (err) {console.log("getKVStore err: "  + JSON.stringify(err));return;}console.log("getKVStore success");kvStore = store});
} catch (e) {console.log("An unexpected error occurred. Error:" + e);
}

4)KVStore 数据库实例, KVStore.put 提供增加数据的方法,如下是参数说明。

let kvStore;
try {kvStore.put(key, value, function (err,data) {if (err != undefined) {console.log("put err: " + JSON.stringify(err))return;}console.log("put success");});
}catch (e) {console.log("An unexpected error occurred. Error:" + e);
}

5) KVStore 数据库实例,KVStore.on 订阅指定类型的数据变更通知;一般监听远端设备变化,再进行相应操作达到分布式数据共享的效果

let kvStore;
kvStore.on('dataChange', distributedData.SubscribeType.SUBSCRIBE_TYPE_LOCAL, function (data) {console.log("dataChange callback call data: " + JSON.stringify(data));
});

6)具体开发请参考分布式数据管理:

https://gitee.com/openharmony/docs/blob/OpenHarmony-3.1-Beta/zh-cn/application-dev/reference/apis/js-apis-distributed-data.md

3.2 应用示例

本项目通过 storeId (数据库唯一标识符)值不同,创建了两个数据管理类,分别是 MenuListData 类和 SubmitData 类,即 Demo 中的 MenuListDistributedData.ets SubmitData.ets 文件。

1)MenuListData 是将完整订单添加到分布式数据库,当监听到数据库变化时,获取完整订单列表,并通过 router.push 接口将数据传递到订单详情页面展示。

• 创建一个 MenuListData 类

private remoteData: MenuListData = new MenuListData()

• 定义一个订单列表集合,集合中的元素包括菜单信息和点单用户信息;点菜后就根据菜品名称和辣度的不同,对订单数据集合进行修改或增加。

TotalMenu: any[] = [{"imgSrc": "",   // 菜品图片"name": "",     // 菜品名称"remarks": "",  // 菜品备注"price": 0,     // 菜品价格"quantity": 0,  // 菜品数量"spicy": "",    //辣度"userImg": ,    "userName": "", "userNumber": 0,"anotherUserImg": "","anotherUserName": "","anotherUserNumber": 0,}];

• 将订单数据加入到分布式数据库

this.remoteData.putData("menu_list", this.TotalMenu)

• 监听数据库变化,获取数据,并将数据传递到 menuAccount 订单详情页面;

this.remoteData.createManager(() => {let self = thisvar dataif (JSON.stringify(self.remoteData.dataItem).length > 0) {data = self.remoteData.dataItemvar list = []for (var i = 0; i < data.length; i++) {list[i] = data[i]}router.push({uri: 'pages/menuAccount',params: { TotalMenu: list }})}})

2)SubmitData 在订单结算时点击下单,将 submitOK 集合添加到数据库,表示下单完成,监听到数据库变化,各设备弹出下单成功提示框;

• 创建一个 SubmitData 类

private remoteData: SubmitData = new SubmitData();

• 定义一个 SubmitOK 集合,这里用集合主要是为了处理数据方便

private SubmitOK: any[] = [{submit: "submitOk"}]

• 添加 SubmitOK 集合到数据库中

this.remoteData.putData("submit", this.SubmitOK)

• 监听到数据库变化,获取数据并比较是 submitOK 后,弹出提示框,告知所有人下单成功。

this.remoteData.createManager(() => {let self = thisvar dataif (JSON.stringify(self.remoteData.dataItem).length > 0) {data = self.remoteData.dataItemif (data[0].submit == "submitOk") {this.SubmitDialog.open()}}})

更完整的分布式数据库的使用,请参考 Demo。

四、项目下载和导入

项目地址:https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/FA/Shopping/DistributedOrder

1)git 下载

git clone https://gitee.com/openharmony-sig/knowledge_demo_temp.git

2)项目导入

打开 DevEco Studio,点击 File->Open->下载路径/FA/Shopping/DistributedOrder

3)硬件约束

需要下载对应开发板镜像(https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-v3.1-beta.md)进行烧录;如下图:

为了帮助到大家能够更有效的学习OpenHarmony 开发的内容,下面特别准备了一些相关的参考学习资料:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……

系统架构分析:https://qr18.cn/CgxrRy

  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

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

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

相关文章

学前端网络安全这块还不懂?细说CSRF

什么是CSRF&#xff1f; 举个栗子&#xff0c;比如我们需要在某个博客上删除一个文章&#xff0c;攻击者首先在自己的域构造一个页面&#xff0c;使用了一个img标签&#xff0c;其地址指向了删除博客的链接。攻击者诱使目标用户&#xff0c;也就是博客主访问这个页面&#xff…

SOP for Oracle 23ai:Python 连接 Oracle 的两种方法

前情回顾 前文介绍了如何使用 python-oracledb 连接 Oracle 23ai 数据库&#xff0c;并演示了如何使用独立连接方式。 其中提到了支持两种连接池&#xff1a; DRCP 和 PRCP。 本文将对这两种连接池做具体演示。 DRCP 和 PRCP 连接池 连接池技术的优点不言而喻&#xff1a; 缩短…

稚晖君独家撰文:具身智能即将为通用机器人补全最后一块拼图

具身智能新纪元。 *本文为稚晖君独家供稿,「甲子光年」经智元机器人授权发布。稚晖君本名彭志辉,先后任职OPPO、华为,现为智元机器人CTO、首席架构师。 在ChatGPT之后,又一个大模型概念火了——具身智能(Embodied AI)。 在学术界,图灵奖得主、上海期智研究院院长姚期…

吞吐量 和 延时的关系

关于吞吐量/吞吐率、延时&#xff0c;你可以通过 Jmeter中的”聚合报告“和”用表格查看报告“来获取。 Throughput 越大&#xff0c;Latency 越差&#xff1a;因为请求过多&#xff0c;系统繁忙导致响应速度降低。Latency 的值越小说明能支持的 Throughput 越高&#xff1a;L…

软考一年只能考一次吗?24软考各科目考试时间一览表

软考考试次数&#xff1a; 软考高级【系统分析师】及【系统架构设计师】是一年考两次的。 此外&#xff0c;软考中级【软件设计师】和【网络工程师】也是一年考两次的。 其他科目一年都只开考一次&#xff0c;或者上半年开考&#xff0c;或者下半年开考&#xff0c;具体考试…

分页查询PageHelper插件分页条件查询(xml映射文件,动态SQL)

黑马程序员JavaWeb开发教程 文章目录 一、分页查询-分析二、分页查询-实现1. 实现思路1.1 controller1.2 service1.3 mapper 1.4 postman测试接口 三、分页查询-PageHelper插件1. 引入pageHelper插件的依赖2. 修改原来的代码2.1 mapper2.2 serviceimpl2.3 postman测试接口 四、…

47 tcp网络程序

网路聊天 API详解 下面用到的API&#xff0c;都在sys/socket.h中 socket (): socket() 打开一个网络通讯端口&#xff0c;如果成功的话&#xff0c;就像open() 一样返回一个文件描述符应用程序可以像读文件一样用read/write在网络上收发数据如果调用出错返回-1对于IPv4&am…

Day28 代码随想录打卡|栈与队列篇---逆波兰表达式求值

题目&#xff08;leecode T150&#xff09;&#xff1a; 给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意&#xff1a; 有效的算符为 、-、* 和 / 。每个操作数&#xff08;运算…

机械手避障如何选择激光雷达?

在选择用于机械手避障的激光雷达时&#xff0c;应该考虑以下主要技术参数&#xff1a; 测量范围&#xff1a;激光雷达的测量范围决定了它能够检测到的最大距离。您需要根据机械手的应用场景和工作环境来选择合适的测量范围。 精度&#xff1a;精度是激光雷达测量结果的重要参数…

ENZO--Leptin (human) ELISA kit

瘦素(Leptin)是由ob基因编码、在脂肪组织中生成的一种脂肪代谢调控产物&#xff0c;在代谢和调控体重等方面发挥重要作用。它通过下丘脑中的瘦素受体发出信号&#xff0c;降低食欲&#xff0c;增加能量消耗。在外周组织中&#xff0c;瘦素能拮抗胰岛素信号传导&#xff0c;增加…

Windows只能安装在GPT磁盘上

转换磁盘分区形式 步骤1. 先按照正常流程使用Windows系统安装光盘或系统U盘引导计算机。 步骤2. 在Windows安装程序中点击“开始安装”&#xff0c;然后按ShiftF10打开命令提示符。 步骤3. 依次输入以下命令&#xff0c;并在每一行命令后按一次Enter键执行。 步骤4. 等待转换…

黑马基于Web-socket的java聊天室基本解析

要是用Web-socket协议&#xff0c;我们要前端upgrade升级成web-socket协议 首先我们要引入springboot的websocket起步依赖&#xff0c;这样子方便使用&#xff0c;自己指定版本注意 <dependency><groupId>org.springframework.boot</groupId><artifactId&…

Django视图Views

Views视图 HttpRequest 和HttpResponse Django中的视图主要用来接受web请求&#xff0c;并做出响应。视图的本质就是一个Python中的函数视图的响应分为两大类 1)以Json数据形式返回(JsonResponse) 2)以网页的形式返回 2.1)重定向到另一个网页 (HttpRe…

Mini Cheetah 代码分析(八)基于零空间的任务分级

一、主要公式 二、源代码注释 三、相关原理解释 一、主要公式 二、源代码注释 该功能的实现在文件KinWBC.cpp中的FindConfiguration函数&#xff0c;主要看注释&#xff0c;与公式是能够对应起来的&#xff0c;由第0个任务&#xff0c;也就是接触任务开始进行迭代&#xff0…

Java类和对象(二)—— 封装,static 关键字与代码块

前言 在面向对象的编程语言中&#xff0c;有三大特性&#xff1a;封装、继承和多态~~ 今天我们就来学习封装的知识 封装 什么是封装 在现实生活中&#xff0c;我们经常使用手机来进行沟通与交流&#xff0c;实际上我们拿到的手机是被封装好的&#xff0c;精美的屏幕&a…

关键字详解

1.用于定义访问权限修饰符的关键字 面向对象程序三大特性&#xff1a;封装、继承、多态。 1.1 访问权限符 Java 中主要通过类和访问权限来实现封装&#xff1a; 类可以将数据以及封装数据的方法结合在一起 &#xff0c;更符合人类对事物的认知&#xff0c;而访问权限用来控制…

5月15日,机器人任务挑战赛(无人协同系统)第二期培训即将开启!

一.大赛培训通知 本月起&#xff0c;卓翼飞思实验室将针对机器人任务挑战赛&#xff08;无人协同系统&#xff09;赛项内容开启赛事培训计划&#xff0c;采用“线上线下”相结合的培训模式&#xff0c;围绕赛事关键技术&#xff0c;让您轻松应对比赛。本期培训为第二期&#x…

Go微服务: 日志系统ELK核心架构设计

微服务日志系统建设 1 &#xff09;为什么需要日志系统 业务发展越来越庞大&#xff0c;服务器越来越多各种访问日志&#xff0c;应用日志&#xff0c;错误日志量越来越多&#xff0c;无法管理开发人员排查问题&#xff0c;需要到服务器上查日志 2 &#xff09;Elastic Stack…

惠普打印机无线网络连接设置

休息一下&#xff0c;灌个水。这次没多少内容&#xff0c;具体步骤惠普官网上都有&#xff0c;唯一增加的是对安装过程中踩的坑做了一个说明。 一&#xff0e;打印机无线网络连接设置步骤 惠普打印机设置无线网络连接&#xff0c;共16个步骤。 1. 在电脑上打开任意浏览器&am…

HAProxy系列文章二《Patroni+ETCD+PG14+HAProxy的安装部署》

瀚高数据库 目录 文档用途 详细信息 文档用途 本文主要介绍Patroni架构下单点HAProxy的安装部署&#xff0c;通过单点HAProxy实现数据库的负载均衡。本文为HAProxy系列文章之一&#xff0c;其他相关文章请点击文档下方的相关文档链接进行详细查看&#xff0c;文章内不在赘述。…