uniapp小程序开发 | 从零实现一款影视类app (后台接口实现,go-zero微服务的使用)

uniapp小程序开发实战系列,完整介绍从零实现一款影视类小程序。包含小程序前端和后台接口的全部完整实现。系列连载中,喜欢的可以点击收藏。

该篇着重介绍获取轮播图后台接口和获取正在热映电影的两个后台接口的实现。 

后台服务使用golang,因为它太适合做后台服务了。而且配合使用go-zero微服务框架,不但强大,还提供了好用的goctl工具,自动生成接口框架代码,让你写接口速度飞升。

下文以两个接口(轮播图接口和豆瓣热门影视接口)示例,可以看到使用go-zero写服务接口是多么的简单。

为了示例和快速实现,暂无后台管理界面。只实现后台接口。

轮播图接口,返回json数据,图片存储在腾讯云的COS对象存储服务,作为图床使用。

豆瓣正在热映电影接口,使用go-zero的httpc转发客户端请求,到豆瓣v2的开源api服务(https://api.douban.com/v2)接口去请求数据。

go-zero 介绍

go-zero是一个集成了各种工程实践的 web 和 rpc 框架。通过弹性设计保障了大并发服务端的稳定性,经受了充分的实战检验。

go-zero 包含极简的 API 定义和生成工具 goctl,可以根据定义的 api 文件一键生成 Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript 代码,并可直接运行。

详细介绍:go-zero 缩短从需求到上线的距离

github地址:https://github.com/zeromicro/go-zero

文档介绍:go-zero/readme-cn.md at master · zeromicro/go-zero · GitHub 

goctl 工具安装

goctl 是 go-zero 的内置脚手架,是提升开发效率的一大利器,可以一键生成代码、文档、部署 k8s yaml、dockerfile 等。

# Go
GOPROXY=https://goproxy.cn/,direct go install github.com/zeromicro/go-zero/tools/goctl@latest# For Mac
brew install goctl# docker for amd64 architecture
docker pull kevinwan/goctl
# run goctl like
docker run --rm -it -v `pwd`:/app kevinwan/goctl --help

由于我是在我的ubuntu20服务器上安装使用的,所以选择了方式三。其实如果使用vscode, 则可以直接安装插件即可,在vscode中搜索goctl插件。 在windows 上安装就不提了,更简单了。

由于我的测试代码跑在腾讯云服务器上,建议使用vscode远程连接的开发方式。在vscode上安装Remote - SSH插件,非常好用,使用方法:VSCODE远程连接服务器,远程开发。

goctl快速使用文档:zero-doc/docs/zero/goctl-api.md at main · zeromicro/zero-doc · GitHub 

快速开始 

前提是具备golang环境和成功安装完成了goctl工具。

简易使用教程,参加我的博客:go-zero微服务框架入门教程_go-zero教程-CSDN博客

下面介绍下如何快速开始一个使用go-zero微服务框架的一个项目。

goctl api new greet
cd greet
go mod tidy
go run greet.go -f etc/greet-api.yaml

执行以上代码,会自动创建工程目录greet,生成一些可以运行的模板文件。一个工程就创建完啦,且执行go run 命令,后台网关服务就已经启动起来啦,默认端口8888,这么简单。

接下来可以使用 curl命令测试一下接口: 

curl -i http://localhost:8888/from/you
  • api 文件定义了服务对外 HTTP 接口,可参考 api 规范
  • 可以在 servicecontext.go 里面传递依赖给 logic,比如 mysql, redis 等。

生成 api 服务

完成上面后,只是一个空的服务接口,如何增加自己的呢?接下来详细介绍。其实就是写好api文件。api 文件定义了服务对外 HTTP 接口,按它的api规范定义自己的接口文件。

我的api文件如下:

syntax = "v1"info (title:   "doc title"desc:    "imovie background service api"version: "1.0"
)type (//轮播图--应答SwiperData {id       int    `json:"id"`imageUrl string `json:"imageUrl"`title    string `json:"title"`desc     string `json:"description"`}SwiperResp {code    int          `json:"code"`message string       `json:"message"`data    []SwiperData `json:"data"`}//热门影视--请求HotMovieReq {start int    `json:"start"`count int    `json:"count"`city  string `json:"city"`}//热门影视--应答HotItem {id    string `json:"id"`cover string `json:"cover"`title string `json:"title"`rate  int    `json:"rate"`}HotMovieResp {code    int       `json:"code"`message string    `json:"message"`data    []HotItem `json:"data"`count   int       `json:"count"`start   int       `json:"start"`total   int       `json:"total"`title   string    `json:"title"`}
)type Request {Name string `path:"name,options=you|me"`
}type Response {Message string `json:"message"`
}service imovie-api {@doc (summary: "imovie api")@handler TestHandlerget /test/:name (Request) returns (Response)@handler SwiperHandlerget /api/v1/swiperdata returns (SwiperResp)@handler HotMovieHandlerpost /api/v1/hotmovie (HotMovieReq) returns (HotMovieResp)
}

由于我是在ubuntu服务器上以docker方式安装的goctl工具,所以使用起来有点儿麻烦,类似下面这样这么长一串:

docker run --rm -it -v `pwd`:/app kevinwan/goctl --help

为了简单使用docker方式安装部署的goctl工具,写了以下配置: 

docker-compose.yml

   version: '3'services:goctl:image: kevinwan/goctlvolumes:- .:/appworking_dir: /app

于是后续再使用goctl命令,变成了下面这种方式,使用下述命令自动生成接口代码: 

sudo docker-compose run goctl api go -api go-imovie/imovie.api -dir go-imovie/

上述命令,就根据 api 文件自动生成了服务接口代码。

参数含义介绍:

业务代码编写 

接下来开始关键的地方了,业务接口的业务逻辑编写,这部分主要在internal文件夹下的logic文件夹下实现。

轮播图接口

swiperlogic.go文件实现

package logicimport ("context""imovie/internal/svc""imovie/internal/types""github.com/zeromicro/go-zero/core/logx"
)type SwiperLogic struct {logx.Loggerctx    context.ContextsvcCtx *svc.ServiceContext
}var MyPic_ = "https://pic-1258623197.cos.ap-beijing.myqcloud.com"func NewSwiperLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SwiperLogic {return &SwiperLogic{Logger: logx.WithContext(ctx),ctx:    ctx,svcCtx: svcCtx,}
}func (l *SwiperLogic) Swiper() (resp *types.SwiperResp, err error) {// todo: add your logic here and delete this line//var item types.SwiperDatavar responseData []types.SwiperDataitem1 := types.SwiperData{Id:       1,ImageUrl: MyPic_ + "/pic0/1.jpg",Title:    "标题1",}item2 := types.SwiperData{Id:       2,ImageUrl: MyPic_ + "/pic0/2.jpg",Title:    "标题2",}item3 := types.SwiperData{Id:       3,ImageUrl: MyPic_ + "/pic0/3.jpg",Title:    "标题3",}responseData = append(responseData, item1)responseData = append(responseData, item2)responseData = append(responseData, item3)resp = &types.SwiperResp{Code:    0,Message: "success",Data:    responseData,}return resp, nil
}

热映电影接口 

hotmovielogic.go文件实现,实现客户端接口转发到豆瓣服务接口。

package logicimport ("context""encoding/json""io""net/http""imovie/internal/svc""imovie/internal/types""github.com/zeromicro/go-zero/core/logx""github.com/zeromicro/go-zero/rest/httpc"
)type HotMovieLogic struct {logx.Loggerctx    context.ContextsvcCtx *svc.ServiceContext
}var Url_ = "https://api.douban.com/v2/movie/in_theaters"
var ApiKey_ = "xxxxxxxxxx"
var Referer_ = "https://images.weserv.nl/?url="func NewHotMovieLogic(ctx context.Context, svcCtx *svc.ServiceContext) *HotMovieLogic {return &HotMovieLogic{Logger: logx.WithContext(ctx),ctx:    ctx,svcCtx: svcCtx,}
}func (l *HotMovieLogic) HotMovie(req *types.HotMovieReq) (resp *types.HotMovieResp, err error) {// todo: add your logic here and delete this linetype Request struct {Req    types.HotMovieReqApiKey string `json:"apikey"`}req_ := Request{Req:    *req,ApiKey: ApiKey_,}l.Debug(req_)url := Url_res, err_ := httpc.Do(l.ctx, http.MethodPost, url, req_)if err_ != nil {l.Error(err_)return nil, err_}defer res.Body.Close()body, err := io.ReadAll(res.Body)if err != nil {l.Errorf("Failed to read response body:", err)return nil, err}//格式化输出json//var str bytes.Buffer//_ = json.Indent(&str, []byte(body), "", "    ")//l.Debugf("formated: ", str.String())var keyVal map[string]interface{}err = json.Unmarshal(body, &keyVal)if err != nil {l.Errorf("Failed to extract key value:", err)}//l.Debug(keyValue)var hot types.HotItemvar responseData []types.HotItemlist_, ok := keyVal["subjects"].([]interface{})if ok {for _, item := range list_ {itemMap, ok := item.(map[string]interface{})if ok {//l.Debug(itemMap)hot.Id = itemMap["id"].(string)hot.Title = itemMap["title"].(string)tmp := itemMap["images"].(map[string]interface{})hot.Cover = Referer_ + tmp["small"].(string)hot.Rate = int(itemMap["rating"].(map[string]interface{})["average"].(float64))}responseData = append(responseData, hot)}}//t := reflect.TypeOf(keyVal["count"])//l.Debugf("Type: %v\n", t)resp = &types.HotMovieResp{Code:    0,Message: res.Status,Data:    responseData,Count:   int(keyVal["count"].(float64)),Start:   int(keyVal["start"].(float64)),Total:   int(keyVal["total"].(float64)),Title:   keyVal["title"].(string),}return resp, nil
}

启动服务

启动服务很简单,直接进入项目目录并执行 go run imovie.go即可。默认端口8888.

如果要更改配置,可以进入项目目录下的etc文件夹,找到imovie-api.yml文件修改。配置文件默认是yaml格式。日志的级别也可以在这里配置更改:

Name: imovie-api
Host: 0.0.0.0
Port: 8000
Log:Level: debug

关于YAML文件

YAML(YAML Ain't Markup Language)是一种简洁、易读、易写的,用于数据序列化的数据交换格式。它常用于配置文件,因为它比XML更简洁,比JSON更易读写(支持多行文本、注释等)。

YAML的基本特点:

1.大小写敏感

2.使用缩进表示层级关系:不允许使用Tab键,必须使用空格,且相同层级的元素左侧对齐。

3.# 表示注释,从这个字符开始直到行尾的内容都会被忽略。

YAML 文件示例

下面是一个简单的YAML文件示例,展示了如何定义键值对、数组、嵌套结构以及使用注释。

# 这是一个YAML配置文件示例
server:# 服务器地址host: "localhost"# 服务器端口port: 8080# 数据库配置
database:# 数据库类型type: "mysql"# 数据库地址host: "127.0.0.1"# 用户名username: "root"# 密码password: "password123"# 应用日志设置
logging:level: "info"    # 日志级别# 日志文件路径file: "/var/log/app.log"# 开发者列表
developers:- name: "张三"email: "zhangsan@example.com"- name: "李四"email: "lisi@example.com"

在这个示例中,server、database、logging 和 developers 是顶层键,每个键下可以有子键。
# 符号后面的内容是注释。

数组(如 developers)通过 - 符号标识每个元素,并且每个元素都是一个映射(键值对)。

YAML文件在许多编程语言和框架中都有良好的支持,用于配置应用程序的各种设置。 

接口测试工具

推荐使用vscode的rest client插件,编写以下测试(文件名test.http):

post http://175.178.126.10:8000/api/v1/hotmovie
Content-Type:application/json{"start": 0,"count": 1,"city": "郑州"
}### 下一项测试,注意前面三个###分割

 结果成功收到应答:

豆瓣接口介绍

获取正在热映的电影

使用vscode的rest client插件测试接口:

### Below is the code of douban.http,use vscode extension REST Client to send request.post https://api.douban.com/v2/movie/in_theaters
Content-Type:application/json{"start": 0,"count": 1,"city": "郑州","apikey": "xxxxxxxxxxx"
}### Respondse{"count": 1,"start": 0,"total": 43,"subjects": [],"title": "\u6b63\u5728\u4e0a\u6620\u7684\u7535\u5f71-\u90d1\u5dde"
}

或者使用curl命令测试接口: 

curl --location --request POST 'https://api.douban.com/v2/movie/in_theaters?city=广州&start=0&count=1' --data-urlencode 'apikey=xxxxxxxxxxxxxx' |python3 -m json.tool% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100  1732  100  1693  100    39   4480    103 --:--:-- --:--:-- --:--:--  4582
{"count": 1,"start": 0,"total": 46,"subjects": [{"rating": {"max": 10,"average": 9.5,"stars": "50","min": 0},"genres": ["\u7eaa\u5f55\u7247","\u97f3\u4e50"],"title": "\u5742\u672c\u9f99\u4e00\uff1a\u6770\u4f5c","casts": [{"alt": "https://movie.douban.com/celebrity/1148641/","avatars": {"small": "https://img1.doubanio.com/view/personage/m/public/12ce4a9f67eac0cb029736ae87549dd0.jpg","large": "https://img1.doubanio.com/view/personage/m/public/12ce4a9f67eac0cb029736ae87549dd0.jpg","medium": "https://img1.doubanio.com/view/personage/m/public/12ce4a9f67eac0cb029736ae87549dd0.jpg"},"name": "\u5742\u672c\u9f99\u4e00","id": "1148641"}],"collect_count": 19158,"original_title": "Ryuichi Sakamoto | Opus","subtype": "movie","directors": [{"alt": "https://movie.douban.com/celebrity/1442776/","avatars": {"small": "https://img1.doubanio.com/view/celebrity/m/public/pXA5FFrGwJ94cel_avatar_uploaded1597077781.8.jpg","large": "https://img1.doubanio.com/view/celebrity/m/public/pXA5FFrGwJ94cel_avatar_uploaded1597077781.8.jpg","medium": "https://img1.doubanio.com/view/celebrity/m/public/pXA5FFrGwJ94cel_avatar_uploaded1597077781.8.jpg"},"name": "\u7a7a\u97f3\u592e","id": "1442776"}],"year": "2023","images": {"small": "https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2907966076.jpg","large": "https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2907966076.jpg","medium": "https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2907966076.jpg"},"alt": "https://movie.douban.com/subject/36491177/","id": "36491177"}],"title": "\u6b63\u5728\u4e0a\u6620\u7684\u7535\u5f71-\u5e7f\u5dde"
}

访问外部图片返回 403 Forbidden 错误问题

遇到提示{"code":"40310015","msg":"referer uri is forbidden"},表明豆瓣对图片资源的访问实施了Referer策略,只允许特定来源(referer)的请求访问图片资源。当你直接在浏览器中输入图片链接能访问,是因为浏览器的请求被视为合法的直接访问,而前端应用(尤其是Web应用)发起请求时,如果其域名不在豆瓣允许的Referer列表中,就会被拒绝访问。

可以在前端页面头部添加一个meta:

<meta name="referrer" content="no-referrer" />

或者最简单的方式就是在<img>标签中增加:

<img src=""    referrerPolicy="no-referrer">

各有优缺点吧,某些旧版本或非主流浏览器可能不支持 referrer-policy。如果原始服务器严格限制Referer,上述这种方法可能无效。

也可以借助Images.weserv.nl图片缓存网站帮我们解决这个问题。

images.weserv.nl 是一个免费的图片托管和缓存服务,它可以用来间接访问受Referer限制的图片。这个服务会将原始图片URL作为参数传递,然后返回一个新的URL,这个新URL可以直接在前端使用,而不需要担心Referer限制。

使用 images.weserv.nl 的步骤如下:

替换图片URL:将豆瓣的原始图片URL替换为 https://images.weserv.nl/?url=<原始图片URL>。

在前端处理:

// 图片防盗链问题解决
function attachImageUrl(srcUrl) {if (srcUrl !== undefined) {return srcUrl.replace(/http\w{0,1}:\/\/p/g, 'https://images.weserv.nl/?url=p')}
}

或者后台处理,返回的图片url上做处理。

var Referer_ = "https://images.weserv.nl/?url="
    var Referer_ = "https://images.weserv.nl/?url="var keyVal map[string]interface{}err = json.Unmarshal(body, &keyVal)if err != nil {l.Errorf("Failed to extract key value:", err)}//l.Debug(keyValue)var hot types.HotItemvar responseData []types.HotItemlist_, ok := keyVal["subjects"].([]interface{})if ok {for _, item := range list_ {itemMap, ok := item.(map[string]interface{})if ok {//l.Debug(itemMap)hot.Id = itemMap["id"].(string)hot.Title = itemMap["title"].(string)tmp := itemMap["images"].(map[string]interface{})hot.Cover = Referer_ + tmp["small"].(string)hot.Rate = int(itemMap["rating"].(map[string]interface{})["average"].(float64))}responseData = append(responseData, hot)}}

由于豆瓣接口返回的json数据比较多且略显杂乱,上述的json解析显得很麻烦。其实可以借助golang的三方库gjson处理这种格式的json数据。 gjson地址:GitHub - tidwall/gjson: Get JSON values quickly - JSON parser for Go

图床服务推荐

我使用的是腾讯云,上面的COS对象存储服务,可以作为开发测试用。它提供试用和免费额度,且提供免费域名直接可以https访问,挺不错的。虽然github和gitee也能用作免费图床,但是github访问慢,而gitee直接停止page服务,无法用了。

关于图床工具,推荐使用PicList.

PicList是一款高效的云存储和图床平台管理工具,在PicGo的基础上经过深度的二次开发,不仅完整保留了PicGo的所有功能,还增添了许多新的feature。例如相册支持同步云端删除文件,内置图床额外添加了WebDav、本地图床和SFTP等。

PicList同时增加了完整的云存储管理功能,包括云端目录查看、文件搜索、批量上传下载和删除文件,复制多种格式文件链接和图片/markdown/文本/视频预览等,另外还有更加强大的相册和多项功能新增或优化。

写在最后

最后,附上完整后台golang源码:https://download.csdn.net/download/qq8864/89401886

其他资源

0ab215a8b1977939201640fa14c66bab

https://go-zero.dev/docs/tutorials

https://zhuanlan.zhihu.com/p/570979109

https://github.com/zeromicro/go-zero?tab=readme-ov-file

https://github.com/zeromicro/zero-doc/blob/main/docs/zero/goctl-api.md

https://zhuanlan.zhihu.com/p/529462051

GitHub - tidwall/gjson: Get JSON values quickly - JSON parser for Go

https://www.jianshu.com/p/ef3fcf94295b

https://zhuanlan.zhihu.com/p/113500478

https://juejin.cn/post/6844903832040767496

https://blog.51cto.com/lanxf/5536521

uniapp中image不显示网络图片_uniapp image站外图片-CSDN博客

https://www.cnblogs.com/bigron/p/17334936.html

小白的最强保姆教学:PicGo + gitee +Typora免费搭建属于个人的图床工具_picgo+csdn-CSDN博客

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

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

相关文章

解决MAC M1 Docker Desktop启动一直在starting

问题描述&#xff1a; 今天使用docker buildx 构建Multi-platform&#xff0c;提示如下错误&#xff1a; ERROR: Multi-platform build is not supported for the docker driver. Switch to a different driver, or turn on the containerd image store, and try again. 于是按…

关系代数与规范化

本文是根据自己的理解&#xff0c;结合实践整理所得&#xff0c;有兴趣的可以参考学习。

在k8s中部署Kafka高可用集群超详细讲解

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《数据流专家&#xff1a;Kafka探索》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Kafka简介 2、为什么在Kubernetes中部署Kafka 二、…

金融科技发展报告:移动支付的市场格局、趋势与优缺点

一、引言 随着科技的飞速发展,金融科技已成为推动全球经济发展的重要力量。移动支付作为金融科技的重要分支,其市场格局与趋势日益受到业界的关注。本报告将详细剖析移动支付的市场格局,并深入探讨其发展趋势,同时结合相关案例和数据,为读者呈现移动支付的优缺点,以及国…

idea 中:运行 Application 时出错。命令行过长

一、问题描述&#xff1a; idea 导入新项目&#xff0c;在编译后&#xff0c;运行项目时&#xff0c;报以下错误&#xff1a; 14:47 运行 Application 时出错运行 Application 时出错。命令行过长。通过 JAR 清单或通过类路径文件缩短命令行&#xff0c;然后重新运行。二、问题…

小程序丨最大填表限制如何开启?

老师在新建填表时&#xff0c;希望设置最大数量限制&#xff0c;若填表达到限制&#xff0c;后续的学生将不能继续提交填表。 通过开启【表格最大限制】功能即可实现&#xff0c;下面就来教大家如何制作吧。 &#x1f50e;如何开启表格最大限制功能&#xff1f; 按照常规流程…

C++结合OpenCV进行图像处理与分类

⭐️我叫忆_恒心&#xff0c;一名喜欢书写博客的在读研究生&#x1f468;‍&#x1f393;。 如果觉得本文能帮到您&#xff0c;麻烦点个赞&#x1f44d;呗&#xff01; 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧&#xff0c;喜欢的小伙伴给个三…

GPT-4o:重塑人机交互的未来

一个愿意伫立在巨人肩膀上的农民...... 一、推出 在人工智能&#xff08;AI&#xff09;领域&#xff0c;自然语言处理&#xff08;NLP&#xff09;技术一直被视为连接人类与机器的桥梁。近年来&#xff0c;随着深度学习技术的快速发展&#xff0c;NLP领域迎来了前所未有的变革…

使用正则表达式分割字符串

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 split()方法用于实现根据正则表达式分割字符串&#xff0c;并以列表的形式返回。其作用同字符串对象的split()方法类似&#xff0c;所不同的就是分割…

【Vue】路由的基本使用

文章目录 一、固定5个固定的步骤二、代码示例三、两个核心步骤四、完整代码 vue-router插件作用 修改地址栏路径时&#xff0c;切换显示匹配的组件 说明 Vue 官方的一个路由插件&#xff0c;是一个第三方包 官网 https://v3.router.vuejs.org/zh/ VueRouter的使用&#xff0…

【java基础】内部类

1、 非静态成员内部类可以访问所在类的全部方法和对象&#xff08;就相当于一个对象方法&#xff08;属于对象阶层和非静态方法同时加载在类加载之后&#xff09;&#xff09; 2、非静态成员内部类无法在该类&#xff08;就是非静态成员内部类所在的类&#xff09;的静态方法中…

期望18K,4年前端Cvte 视源股份一面挂

一面 1、自我介绍&#xff1f;毕业的时候一直在 xx 公司&#xff0c;你基本都在做什么项目&#xff1f; 2、你讲一下你主要负责哪一块的&#xff1f;balabala 3、你们的 json 是怎么定义组件间的联动的&#xff1f; 4、怎么确定区分两个 input&#xff1f; 5、你们是怎么触…

3. 使用tcpdump抓取rdma数据包

系列文章 第1章 多机多卡运行nccl-tests 和channel获取第2章 多机多卡nccl-tests 对比分析第3章 使用tcpdump抓取rdma数据包 目录 系列文章一、准备工作1. 源码编译tcpdump2. 安装wireshark 二、Tcpdump抓包三、Wireshark分析 一、准备工作 1. 源码编译tcpdump 使用 tcpdump…

基于web的垃圾分类回收系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;用户管理&#xff0c;公告管理&#xff0c;运输管理&#xff0c;基础数据管理 用户账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;运输管理&#xff0c;公告…

基于Django的博客系统之用HayStack连接elasticsearch增加搜索功能(五)

上一篇&#xff1a;搭建基于Django的博客系统数据库迁移从Sqlite3到MySQL&#xff08;四&#xff09; 下一篇&#xff1a;基于Django的博客系统之增加类别导航栏&#xff08;六&#xff09; 功能概述 添加搜索框用于搜索博客。 需求详细描述 1. 添加搜索框用于搜索博客 描…

C语言 | Leetcode C语言题解之第133题克隆图

题目&#xff1a; 题解&#xff1a; struct Node** visited; int* state; //数组存放结点状态 0&#xff1a;结点未创建 1&#xff1a;仅创建结点 2&#xff1a;结点已创建并已填入所有内容void bfs(struct Node* s) {if (visited[s->val] && state[s->val] 2…

图片和PDF展示预览、并支持下载

需求 展示图片和PDF类型&#xff0c;并且点击图片或者PDF可以预览 第一步&#xff1a;遍历所有的图片和PDF列表 <div v-for"(data,index) in parerFont(item.fileInfo)" :key"index" class"data-list-item"><downloadCard :file-inf…

【面试八股总结】锁:互斥锁、自旋锁、读写锁、乐观锁、悲观锁

使用加锁操作和解锁操作可以解决并发线程/进程的互斥问题。任何想进入临界区的线程&#xff0c;必须先执行加锁操作。若加锁操作顺利通过&#xff0c;则线程可进入临界区&#xff1b;在完成对临界资源的访问后再执行解锁操作&#xff0c;以释放该临界资源。 一、互斥锁与自旋锁…

【C语言】详解函数(下)(庖丁解牛版)

文章目录 1. 前言2. 数组做函数形参3. 函数嵌套调用和链式访问3.1 嵌套调用3.2 链式访问 1. 前言 详解C语言函数(上)的链接&#xff1a;http://t.csdnimg.cn/EGsfe 经过对函数的初步了解之后,相信大家已经对C语言标准库里的函数已经有初步的认知了&#xff0c;并且还学会了如…

Linux系统Docker部署Apache Superset并实现远程访问详细流程

目录 前言 1. 使用Docker部署Apache Superset 1.1 第一步安装docker 、docker compose 1.2 克隆superset代码到本地并使用docker compose启动 2. 安装cpolar内网穿透&#xff0c;实现公网访问 3. 设置固定连接公网地址 前言 作者简介&#xff1a; 懒大王敲代码&#xff0…