kizumi_header_banner_img

Learn. Build. Share.

加载中

文章导读

基于脚手架微服务的视频点播系统-客户端业务逻辑处理部分(一)


avatar
xiu114514 2025年9月20日 248
基于脚手架微服务的视频点播系统-客户端业务逻辑处理部分(一)

@TOC 前面的文章我们已经实现完毕客户端的界面,播放器以及数据中心模块与通信模块的预备工作。那么接下来我们便对客户端的业务逻辑进行实现。

一.RESTful API

本项目采用RESTful API是⼀种遵循REST架构风格,基于HTTP协议的应用程序接口设计规范,它提供了⼀种通过标准化的操作和资源访问模式进行客户端与服务器通信的⽅式。 REST是Representational State Transfer的缩写,翻译过来就是表现层状态转化。 资源(Resource) RESTful API 中的每⼀个对象、实体或数据都被抽象为⼀个资源。例如,用户、文章等都可以作为资源。每个资源都通过⼀个唯⼀的 URI (统⼀资源标识符)标识。 URI(统⼀资源标识) URI是用于标识资源的地址。 RESTful API 中,通常使用 URL (统⼀资源定位符)作为 URI 。例如: /users/123 表示 id 为 123 的用户资源 /posts/456 表示 id 为 456 的⽂章资源 HTTP动作(HTTP Methods) RESTful API 依赖于 HTTP 协议的常见方法来对资源进⾏操作,每个 HTTP 方法对应不同的操作: GET :获取服务器上的资源。 POST :在服务器上创建新的资源。 PUT :更新服务器的上的资源。 DELETE :删除服务器上的资源。 无状态 RESTful API 是无状态的。每个请求都应该是独立的,服务器不会在请求之间保存客户端的状态。 表现层状态转移(Representational State Transfer) 资源的表现形式可以是 JSON 、 XML 、 HTML 等格式,通常 RESTful API 使用 JSON 作为数据交换格式,因为它轻量且易于解析。 RESTful API的优点可以总结如下: 1.简单与统一接口:使用标准的 HTTP 方法(GET, POST, PUT, DELETE 等)来执行操作,设计直观,学习和使用成本低。 2.可伸缩性:无状态特性(每次请求都包含所有必要信息)使得服务器无需保存客户端状态,更容易通过增加服务器来扩展系统性能。 3.松耦合与独立性:客户端和服务器是分离的,只要接口不变,可以独立地发展和更换技术栈。 4.通用性与互操作性:基于 HTTP 协议,可以被任何支持 HTTP 的客户端(浏览器、移动应用、IoT 设备等)轻松调用,语言无关。 我们之前开发的测试接口(如hello和ping)采用的就是RESTful API设计,这种标准化接口几乎无需额外学习就能快速上手使用。所以我们使用它来实现客户端背后的业务逻辑。

二.启动页-临时用户登录接口

在进行项目实现之前,我们就已经规定好了请求的URL以及请求的参数字段: 请求URL:

请求参数(客户端):

字段名称字段类型字段说明
requestIdstring请求ID

示例:

返回响应:200 OK

字段名称字段类型字段说明
requestIdstring请求ID
errorCodeinteger错误码;0-成功
errorMsgstring错误信息
resultstring响应结果
sessionIdstring客户端会话ID

示例:

那么首先我们在dataCenter.h之前我们给hello与ping测试接口定义异步请求方法以及完成信号的相同位置定好临时登录请求的异步方法与信号:

接下来我们去netclient类中根据我们之前定好的请求接口与URL实现tempLogin方法:

对于session与cookie不了解的读者可以移步至我之前写过的一篇文章: HTTP协议解析:Session/Cookie机制与HTTPS加密体系的技术演进(二) 这里我们就不再深入介绍了。当服务端收到临时登录请求后,会向客户端发送一个sessionId。由于HTTP协议本身是无状态的,为了保持后续通信的"有状态"特性,客户端需要保存这个sessionId,并在之后与服务端的所有交互中都携带该sessionId。我们在dataCenter中添加一个成员变量记录该sessionId并添加setSessionId方法。 客户端请求处理完毕,接下来我们在mockServer模拟实现一个简单的响应逻辑: 首先新增枚举常量UserType标识本次通信对象的身份-默认为临时登录用户:

接下来定义实现临时登录请求的响应接口,同时根据我们之前规定好的URL设置路由:

当客户端收到服务端的响应时,会发射一个名为tempLoginDone的信号。我们这里的处理方法是在启动页调用其异步处理方法并处理该信号-当响应处理完毕后,再显示首页界面:

接下来我们启动客户端与服务端就能看到如下效果: 在这里插入图片描述 在这里插入图片描述

三.首页-获取全部视频列表

刚进⼊首页时,在用户还没有进行任何选择情况下,默认先获取所有视频列表,给用户⼀个默认的视频信息页面,默认情况下⼀次性获取20个视频,这些视频按照播放量和点赞量之后降序排列。 请求URL: POST /HttpService/allVideoList 请求参数(客户端):

字段名称字段类型字段说明
requestIdstring请求ID
sessionIdstring客⼾端会话ID
pageIndexinteger⻚码
pageCountinteger每⻚条⽬数量

示例:

针对单个分类下视频数量庞大的情况,我们采用分页加载机制来优化性能。系统默认每页加载20个视频数据,当用户滚动至页面底部时自动触发下一页的加载。其中,pageCount参数控制每页加载的视频数量,pageIndex参数则指定当前加载的页码。针对单个分类下视频数量庞大的情况,我们采用分页加载机制来优化性能。系统默认每页加载20个视频数据,当用户滚动至页面底部时自动触发下一页的加载。其中,pageCount参数控制每页加载的视频数量,pageIndex参数则指定当前加载的页码。

返回响应:200 OK

字段名称字段类型字段说明
requestIdstring请求ID
errorCodeinteger错误码;0-成功
errorMsgstring错误信息
resultobject响应结果
totalCountinteger总数量
videoListarray视频列表
videoIdstring视频ID
userIdstring所属用户ID
userAvatarIdstring用户头像ID
nicknamestring所属用户名称
videoFiledstring视频文件ID
photoFiledstring封面文件ID
likeCountinteger点赞数量
playCountinteger播放数量
videoSizeinteger视频大小
videoDescstring视频简介
videoTitlestring视频标题
videoDurationinteger视频时长
videoUpTimestring视频上架时间

示例:

注意:videoList是⼀个数组,内部存放返回给客⼾端的单个视频JSON对象。根据响应中单个视频中包含的信息,除此之外客⼾端在解析响应结果时,需要将所有视频信息组织起来,所以定义描述视频信息的结构以及管理这些视频信息的视频列表实现如下:

因为之后单条视频的信息是要设置到videobox中的,所以我们需要在videobox中处理videoInfo提供的信息:

接下来定义实现异步接口与完成信号-同时当服务端返回响应报文时,将报文中的视频信息添加到DataCenter类中管理起来:

在netclient类中实现getAllVideoList客户端请求方法:

客户端处理完毕,接下来我们在mockServer中构造一批假数据作为响应返回给客户端:

收到视频信息之后,我们需要在首页进行视频的更新,那么就应该在首页类中处理getAllVideoListDone信号,然后将datacenter中记录的所有videoInfo更新到首页中去:

四.首页-获取分类,标签,搜索视频列表,顺带实现置顶与刷新以及获取下一页视频的方法

由于点击分类标签之后需要更新dataCenter中的视频列表,所以需要先将原有视频列表清空,这里我们在首页类中新增清空视频列表的方法:

由于获取全部视频列表与分类视频列表,标签视频列表以及搜索视频列表的实现机制几乎类似,同时他们的响应字段均相同,请求字段后三者仅比前者多了一处不同,所以接下来我们实现过程不再赘述对于这三者,直接给出实现的方法。 获取分类视频列表的接口描述如下: 请求URL: 对于分类视频列表: POST /HttpService/allVideoList 对于标签视频列表: POST /HttpService/tagVideoList 对于搜索视频列表: POST /HttpService/keyVideoList 请求参数(客户端):

字段名称字段类型字段说明
requestIdstring请求ID
sessionIdstring客⼾端会话ID
videoTypeIdinteger视频分类类型
pageIndexinteger⻚码
pageCountinteger每⻚条⽬数量

对于标签视频列表第三个字段为: videoTag integer 视频标签类型 对于搜索视频列表第三个字段为: searchKey string 搜索关键字

示例:

对于标签视频列表第三个字段为: "videoTag" : 0 对于搜索视频列表第三个字段为: "searchKey" : "string"

返回响应:200 OK

字段名称字段类型字段说明
requestIdstring请求ID
errorCodeinteger错误码;0-成功
errorMsgstring错误信息
resultobject响应结果
totalCountinteger总数量
videoListarray视频列表
videoIdstring视频ID
userIdstring所属用户ID
userAvatarIdstring用户头像ID
nicknamestring所属用户名称
videoFiledstring视频文件ID
photoFiledstring封面文件ID
likeCountinteger点赞数量
playCountinteger播放数量
videoSizeinteger视频大小
videoDescstring视频简介
videoTitlestring视频标题
videoDurationinteger视频时长
videoUpTimestring视频上架时间

示例:

datacenter中新增这三者的完成信号与异步请求方法:

在netclient中实现对应方法:

在mockServer构造假数据响应给客户端:

记得不要忘记在init函数中路由我们规定好的URI。 接下来我们在首页调用datacenter中的异步方法并处理完成信号,同时实现置顶与刷新方法以及获取下一页视频的方法,因为比较多,这里我就不像之前那样只给新增的部分了,而是把对应模块的cpp与h文件全部给出,以便读者理解:

五.videoBox页-下载图片接口

我们首先来分析下videoBox需要显示图片的部分,一处是视频的封面,还有一处是上传视频的用户头像,那么我们可以通过之前在videoInfo中存储的userAvatarId-用户头像ID , photoFiled-封面文件ID向服务端发送请求获取图片资源。而这些信息并不是敏感信息,所以我们这里换用GET的方法向服务端发送下载图片的请求: 请求URL : GET /HttpService/downloadPhoto?requestId=xxx&sessionId=xxx&fileId=xxx 请求参数也不用再设计了,因为它已经在URL中包含了。然后需要将Content-Type头部中的application/json更改为application/octet-stream。 客户端定义请求下载图片方法:

这里也可以使用post,但一般不这样干,因为POST 请求虽然也可以在 URL 中带有查询参数,但这通常用于非核心的、辅助性的参数,而不是用于传递要创建或更新的主体数据。 不过我们现在并没有图片数据,所以只能先造一批假的图片数据了: 在这里插入图片描述 然后根据我们之前在处理视频列表中造的假数据设置相应图片ID与图片的映射关系:

接下来我们利用这一批假数据返回响应给客户端:

六.videoBox页-更新视频封面

这里我们就可以使用上面实现的下载图片接口来获取视频封面了,但是有一个问题,因为之前我们的imageBox是QWidget类型的,也就意味着我们不能像QLabel那样使用QPixmap加载服务端给的二进制流数据然后直接设置为封面图了。 所以我们有两种解决方法,一种就是重写videoBox的paintEvent的方法,另一种便是将imageBox类型修改为QLabel。后者比较简单,但是考虑到部分读者需要去改之前相关部分的代码,这里我们选用第一种方式,之前写的代码我们也不需要进行修改了:

接下来便可以编写代码,向服务端发送获取视频封面图片的请求,并处理返回的响应数据。

七.videoBox页-更新上传视频的用户头像

这就比较简单了,我们直接使用QPixmap加载服务端给的二进制流数据给他设置上去就ok了

这些业务逻辑处理完毕之后,我们能看到如下效果: 全部视频列表: 在这里插入图片描述 分类视频列表: 在这里插入图片描述 标签视频列表: 在这里插入图片描述 搜索视频列表: 在这里插入图片描述 在这里插入图片描述

 

 

 

 



评论(已关闭)

评论已关闭

日历

2025 年 9 月
 1
2345678
9101112131415
16171819202122
23242526272829
3031