10、Go Gin 连接Redis以及CookieSession
一、Redis
在Go语言中,使用Gin框架结合Redis数据库可以构建高性能的Web应用程序。Gin是一个轻量级的HTTP框架,提供了快速构建RESTful API的能力;而Redis则是一个高性能的键值存储系统,常用于缓存、消息队列、计数器等多种场景
1、安装Redis客户端库
要在Go语言的Gin框架中连接Redis并执行基本操作,你需要先安装Go的Redis客户端库。推荐使用go-redis/redis
,这是一个高性能的Redis客户端
go get -u github.com/go-redis/redis/v8
2、示例代码一
注意:确保你的Redis服务正在运行,并根据实际情况调整连接参数。
package mainimport ("context""github.com/gin-gonic/gin"redis "github.com/go-redis/redis/v8""log"
)var rdb *redis.Clientfunc init() {// 初始化Redis客户端rdb = redis.NewClient(&redis.Options{Addr: "localhost:6379", // Redis服务器地址和端口Password: "", // 密码,如果没有设置则留空DB: 0, // 使用默认数据库})
}func main() {ctx := context.Background()// 测试Redis连接_, err := rdb.Ping(ctx).Result()if err != nil {log.Fatalf("无法连接到Redis: %v", err)}router := gin.Default()// http://localhost:8080/set/aaa/123router.GET("/set/:key/:value", func(c *gin.Context) {key := c.Param("key")value := c.Param("value")err := rdb.Set(ctx, key, value, 0).Err()if err != nil {c.JSON(500, gin.H{"error": "设置键值对失败"})return}c.JSON(200, gin.H{"message": "设置成功"})})// http://localhost:8080/get/aaarouter.GET("/get/:key", func(c *gin.Context) {key := c.Param("key")val, err := rdb.Get(ctx, key).Result()if err == redis.Nil {c.JSON(404, gin.H{"message": "键不存在"})return} else if err != nil {c.JSON(500, gin.H{"error": "获取键值对失败"})return}c.JSON(200, gin.H{"key": key, "value": val})})router.Run(":8080")
}
3、示例代码二
注意:确保你的Redis服务正在运行,并根据实际情况调整连接参数。
package mainimport ("context""github.com/gin-gonic/gin"redis "github.com/go-redis/redis/v8""log""net/http"
)var rdb *redis.Clientfunc init() {// 初始化Redis客户端rdb = redis.NewClient(&redis.Options{Addr: "localhost:6379", // Redis服务器地址和端口Password: "", // 密码,如果没有设置则留空DB: 0, // 使用默认数据库})
}
func setKeyValue(c *gin.Context) {key := c.Query("key")value := c.Query("value")err := rdb.Set(context.Background(), key, value, 0).Err()if err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "设置键值对失败"})return}c.JSON(http.StatusOK, gin.H{"message": "设置成功"})
}func getKey(c *gin.Context) {key := c.Query("key")val, err := rdb.Get(context.Background(), key).Result()if err == redis.Nil {c.JSON(http.StatusNotFound, gin.H{"message": "键不存在"})} else if err != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": "获取键值对失败"})} else {c.JSON(http.StatusOK, gin.H{"key": key, "value": val})}
}
func main() {ctx := context.Background()// 测试Redis连接_, err := rdb.Ping(ctx).Result()if err != nil {log.Fatalf("无法连接到Redis: %v", err)}router := gin.Default()// http://localhost:8080/set?key=aaa&value=123456router.GET("/set", setKeyValue)// http://localhost:8080/get?key=aaarouter.GET("/get", getKey)router.Run(":8080")
}
二、Cookie&Session
在Go语言中,使用Gin框架处理Cookie和Session是Web开发中的常见需求。下面我将分别介绍如何在Gin中使用Cookie和Session
1、Cookie
HTTP 是无状态协议,简单地说,当浏览了一个页面,然后转到同一个网站的另一个页面,服务器无法认识到这是同一个浏览器在访问同一个网站,每一次的访问,都是没有任何关系的,如果要实现多个页面之间共享数据的话就可以使用 Cookie 或者 Session 实现cookie 是存储于访问者计算机的浏览器中,可以用同一个浏览器访问同一个域名的时候共享数据。
Cookie是一种在客户端存储数据的技术,它允许服务器通过HTTP响应头向客户端发送一些数据,客户端之后的请求会自动带上这些数据到服务器 。
(1)、设置获取Cookie
设置和获取 Cookie | Gin Web Framework
c.SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool)
SetCookie
函数用于设置Cookie,参数依次为:
Cookie名称、值、过期时间(秒)、路径、域名、是否只通过HTTPS传输、是否只用于HTTP请求
(2)、 示例代码一,设置和获取
package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()// http://localhost:8080/setcookier.GET("/setcookie", func(c *gin.Context) {// 设置一个名为"mycookie"的Cookie,值为"value", 过期时间为24小时后c.SetCookie("mycookie", "value", 3600*24, "/", "localhost", false, true)c.String(http.StatusOK, "Cookie设置成功")})// http://localhost:8080/getcookier.GET("/getcookie", func(c *gin.Context) {cookie, err := c.Cookie("mycookie")if err != nil {c.String(http.StatusBadRequest, "读取Cookie失败: %s", err)} else {c.String(http.StatusOK, "Cookie的值为: %s", cookie)}})r.Run(":8080")
}
(3)、 示例代码二,共享域名
要在Go语言的Gin框架中实现多个二级域名共享Cookie,关键在于设置Cookie时正确地使用
Domain
字段。当希望多个二级域名能够访问同一份Cookie时,你需要将Domain
设置为它们共同的顶级域名(不包含任何子域名部分)
设置共享 cookie
当你设置 cookie 时,你需要将 Domain
设置为所有子域名共享的父域名(不包括子域名本身)。例如,如果你的子域名是 a.example.com
和 b.example.com
,你可以将 Domain
设置为 .example.com
(注意前面的点号)
package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()r.GET("/setcookie", func(c *gin.Context) {cookie := &http.Cookie{Name: "shared_cookie",Value: "some_value",Domain: ".example.com", // 注意前面的点号Path: "/",MaxAge: 86400, // 一天HttpOnly: true,}c.SetCookie(cookie.Name, cookie.Value, cookie.MaxAge, cookie.Path, cookie.Domain, cookie.Secure, cookie.HttpOnly)c.String(200, "Cookie set successfully")})// ... 其他路由r.Run(":8080") // 假设你在本地开发,并且使用 8080 端口
}
通过二级域名访问共享 cookie
package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()// 设置路由处理函数,用于在响应中设置共享的Cookie// http://localhost:8080/getSharedCookier.GET("/setSharedCookie", func(c *gin.Context) {// 注意:将Domain设置为顶级域名,例如 ".example.com",前面的点表示任何子域名都可以访问此Cookiec.SetCookie("sharedCookie", "sharedValue", 3600, "/", ".example.com", false, true)c.String(http.StatusOK, "Shared Cookie 设置成功")})// 正常访问:http://localhost:8080/getSharedCookie// 使用二级域名访问:http://二级域名:8080/getSharedCookie// 如:http://a.example.com:8080/getSharedCookie// 如:http://b.example.com:8080/getSharedCookier.GET("/getSharedCookie", func(c *gin.Context) {cookie, err := c.Cookie("sharedCookie")if err != nil {c.String(http.StatusBadRequest, "读取Cookie失败: %s", err)} else {c.String(http.StatusOK, "Cookie的值为: %s", cookie)}})// 启动服务器r.Run(":8080")
}
通过c.SetCookie
函数设置了一个名为sharedCookie
的Cookie,它的Domain
被设为.example.com
。这里的点(.
)是必要的,它表明这个Cookie对于.example.com
下的所有子域名都是可见的,比如a.example.com
和b.example.com
都能访问这个Cookie
注意事项
a、确保你的应用可以在所有子域名上访问,或者确保只有需要访问共享 cookie 的子域名上有你的应用。
b、出于安全考虑,你应该始终通过 HTTPS 传输 cookie,并设置 Secure
属性为 true
。但请注意,在本地开发时,你可能无法使用 HTTPS,因此可以在开发环境中禁用它。
c、 不要将敏感信息存储在客户端 cookie 中。即使你使用了加密,也不能保证 cookie 的安全性。对于敏感信息,应该使用服务器端会话或安全的数据库存储。
二级域名在项目中的使用
通过二级域名访问共享 cookie 的地址实际上取决于你的应用部署在哪个二级域名下,并且你希望在哪个路由下访问这个 cookie。在 Gin Web 框架中,你定义了一个或多个路由(endpoints)来处理 HTTP 请求,并在这些路由的处理函数中访问或设置 cookie。
例如,如果你的 Gin 应用部署在 sub1.example.com
和 sub2.example.com
这两个二级域名下,并且你想通过一个特定的路由 /getcookie
来访问共享的 cookie,那么对于 sub1.example.com
,访问地址将是 http://sub1.example.com/getcookie
,对于 sub2.example.com
,访问地址将是 http://sub2.example.com/getcookie
。
这里是一个简化的例子,展示了如何在 Gin 应用中定义这样一个路由来访问共享的 cookie:
package main import ( "github.com/gin-gonic/gin"
) func main() { r := gin.Default() // 设置共享 cookie 的路由(这里只是一个示例,实际设置可能在其他地方) r.GET("/setcookie", func(c *gin.Context) { // ... 设置 cookie 的代码 ... c.String(200, "Cookie set successfully") }) // 访问共享 cookie 的路由 r.GET("/getcookie", func(c *gin.Context) { cookie, err := c.Cookie("shared_cookie") if err != nil { c.String(400, "Cookie not found") return } c.String(200, "Cookie value: "+cookie) }) // 启动服务,这里假设你已经在两个二级域名下部署了这个应用 // 你需要分别在这两个二级域名下启动服务,或者使用反向代理等技术来将请求路由到同一个应用实例 r.Run(":8080") // 这只是一个示例端口,实际应用中需要配置为正确的监听地址和端口
}
请注意,r.Run(":8080")
这行代码只会在本地主机的 8080 端口上启动服务。在实际部署中,你需要在两个二级域名下分别部署你的 Gin 应用,或者使用反向代理(如 Nginx)将两个二级域名的请求转发到同一个 Gin 应用实例。
此外,由于 cookie 的 Domain
属性设置为 .example.com
,所以只要 cookie 已经被正确设置,并且浏览器支持跨域 cookie(即没有遇到跨域策略的限制),那么无论是通过 sub1.example.com/getcookie
还是 sub2.example.com/getcookie
访问,都应该能够获取到共享的 cookie。
另外:如何在两个二级域名下分别部署你的 Gin 应用
在两个二级域名下分别部署 Gin 应用通常涉及在两台不同的服务器或两个不同的服务实例上运行你的 Gin 应用,或者配置一个反向代理(如 Nginx)来根据请求的域名将流量路由到同一个 Gin 应用实例的不同配置。
以下是两种常见的方法:
方法一:在两个不同的服务器或服务实例上部署
-
准备两个服务器或服务实例:确保你有两个独立的服务器或容器实例,例如两台云服务器或两个 Kubernetes Pod。
-
部署 Gin 应用:在两个服务器上分别部署你的 Gin 应用。你可以使用 Docker、Kubernetes、Ansible、Chef、Puppet 等工具来自动化部署过程。
-
配置域名:确保你的 DNS 记录已经正确设置,将
sub1.example.com
解析到第一个服务器的 IP 地址,将sub2.example.com
解析到第二个服务器的 IP 地址。 -
启动 Gin 应用:在每个服务器上启动你的 Gin 应用,并监听相应的端口(例如 80 或 443,取决于你是否使用 HTTPS)。
方法二:使用反向代理(如 Nginx)
-
准备服务器:准备一台服务器来运行 Nginx 和你的 Gin 应用。
-
安装 Nginx:在服务器上安装 Nginx。
-
配置 Nginx:编辑 Nginx 的配置文件(通常是
/etc/nginx/nginx.conf
或/etc/nginx/sites-available/
目录下的某个文件),添加两个 server 块来分别处理sub1.example.com
和sub2.example.com
的请求。在每个 server 块中,使用proxy_pass
指令将请求转发到你的 Gin 应用实例。示例 Nginx 配置可能如下所示:
server { listen 80; server_name sub1.example.com; location / { proxy_pass http://localhost:8080; # 假设 Gin 应用在 8080 端口上运行 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 其他必要的 proxy_set_header 指令 } } server { listen 80; server_name sub2.example.com; location / { proxy_pass http://localhost:8080; # 同样的 Gin 应用实例处理两个域名的请求 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 其他必要的 proxy_set_header 指令 } }
注意:在这个配置中,我们假设 Gin 应用在服务器的 8080 端口上运行,并且处理来自两个域名的请求。在实际部署中,你可能需要根据你的实际情况调整端口和配置。
-
启动 Nginx 和 Gin 应用:首先启动你的 Gin 应用实例,并监听一个端口(例如 8080)。然后启动 Nginx,它将根据你的配置文件来处理来自
sub1.example.com
和sub2.example.com
的请求,并将它们转发到你的 Gin 应用实例。 -
配置域名:确保你的 DNS 记录已经正确设置,将
sub1.example.com
和sub2.example.com
都解析到运行 Nginx 的服务器的 IP 地址。
使用反向代理的方法通常更加灵活和可维护,因为它允许你在一个集中的地方管理路由和流量分配。然而,它也可能增加系统的复杂性和性能开销。根据你的具体需求和资源限制,选择最适合你的方法。
2、Session
Session是一种服务器端存储用户状态的机制,相比Cookie更安全,因为它不直接暴露在客户端。在Gin中使用Session,通常需要借助中间件,如
github.com/gin-contrib/sessions
。
(1)、Session 的工作流程
当客户端浏览器第一次访问服务器并发送请求时,服务器端会创建一个 session 对象,生成一个类似于 key,value 的键值对,然后将 value 保存到服务器 将 key(cookie)返回到浏览器(客户)端,浏览器下次访问时会携带 key(cookie),找到对应的 session(value)
(2)、安装session包
go get -u github.com/gin-contrib/sessions
go get -u github.com/go-redis/redis/v8
(3)、设置session&获取session&删除session
package mainimport ("github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/cookie""github.com/gin-gonic/gin""net/http"
)func main() {// 加载引擎r := gin.Default()//创建基于cookie的存储引擎,mySessionKey参数是用于加密的密钥store := cookie.NewStore([]byte("mySessionKey"))//设置session中间件,参数mySession,指的是session的名字,也是cookie的名字//store是前面创建的存储引擎,我们可以替换成其他存储引擎r.Use(sessions.Sessions("mySession", store))// http://127.0.0.1:8080/setSessionr.GET("/setSession", func(c *gin.Context) {//设置sessionsession := sessions.Default(c)session.Set("username", "张三")//设置过期时间session.Options(sessions.Options{//MaxAge: 3600 * 6, //6hrsMaxAge: 30, //30s})session.Save() // 设置session的时候必须调用c.JSON(http.StatusOK, gin.H{"title": "设置session成功",})})// http://127.0.0.1:8080/getSessionr.GET("/getSession", func(c *gin.Context) {//获取session//初始化session对象session := sessions.Default(c)username := session.Get("username")if username == nil {c.JSON(http.StatusOK, gin.H{"username": username,"title": "不存在该session",})return}c.JSON(http.StatusOK, gin.H{"title": "获取session成功","username": username,})})// http://127.0.0.1:8080/deleteSessionr.GET("/deleteSession", func(c *gin.Context) {//删除sessionsession := sessions.Default(c)username := session.Get("username")if username == nil {c.JSON(http.StatusOK, gin.H{"username": username,"title": "不存在该session",})return}session.Delete("username")session.Save()c.JSON(http.StatusOK, gin.H{"sessionKey": "username","title": "删除session成功",})})r.Run(":8080")
}
(4)、session存储后端,如memory、redis、mysql
在Go语言中使用Gin框架来设置、获取和删除session,通常需要借助一些第三方的session管理中间件,比如
github.com/gin-contrib/sessions
。这个库支持多种session存储后端,如memory、redis、mysql等。下面以内存存储(memory)为例,介绍如何设置、获取和删除session
1). 安装依赖
首先,你需要安装gin
和gin-contrib/sessions
以及其内存存储引擎gin-contrib/sessions/mongo
(这里以mongo为例,实际可根据需求选择其他存储引擎):
注意:上述命令中的
mongo
应替换为你打算使用的存储引擎,如redis
,mysql
等。如果使用内存存储,应为cookie
或memory
。
如:如果想将 session 数据保存到 redis 中,只要将 session 的存储引擎改成 redis 即可
go get -u github.com/gin-gonic/gin
go get -u github.com/gin-contrib/sessions
go get -u github.com/gin-contrib/sessions/mongo
go get -u github.com/gin-contrib/sessions/redis
2). 初始化Gin与Session
package mainimport ("github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/mongo""github.com/gin-gonic/gin"
)func main() {r := gin.Default()// 使用Mongo存储session,如果是内存存储,将mongo改为cookie或memorystore, _ := mongo.NewStore(10, "tcp", "localhost:27017", "test_session", "", []byte("secret"))// 注册session中间件r.Use(sessions.Sessions("mysession", store))r.GET("/set", func(c *gin.Context) {session := sessions.Default(c)session.Set("key", "value")session.Save()c.JSON(200, gin.H{"message": "session set"})})r.GET("/get", func(c *gin.Context) {session := sessions.Default(c)value := session.Get("key")c.JSON(200, gin.H{"message": value})})r.GET("/delete", func(c *gin.Context) {session := sessions.Default(c)session.Delete("key")session.Save()c.JSON(200, gin.H{"message": "session deleted"})})r.Run(":8080")
}
3). 功能说明
r.Use(sessions.Sessions("mysession", store))
:这行代码注册了session中间件,"mysession"是session的名称,可以自定义,store则是具体的session存储实例。/set
路由:设置session。通过session.Set("key", "value")
设置session的键值对,并通过session.Save()
保存到存储引擎。/get
路由:获取session。通过session.Get("key")
获取之前设置的session值。/delete
路由:删除session。通过session.Delete("key")
删除指定的session键值对,并保存更改。
在Go Gin框架中,选择不同的session存储方式(MongoDB、内存、Cookie、Redis)各有其优缺点,具体如下:
3、选择存储引擎
MongoDB
-
优点:
- 持久化:数据存储在MongoDB数据库中,即使服务器重启,session数据依然保留。
- 扩展性:MongoDB支持水平扩展,适合大量数据和高并发访问。
- 灵活性:支持复杂查询,便于管理和分析session数据。
-
缺点:
- 性能:相较于内存存储,MongoDB的读写速度相对较慢。
- 依赖:增加了对MongoDB数据库的依赖,需要维护数据库的稳定运行。
内存(Memory)
-
优点:
- 速度:内存访问速度快,能够提供极高的读写性能。
- 简单:实现简单,无需配置额外的存储服务。
-
缺点:
- 非持久化:服务器重启后,所有session数据丢失。
- 扩展性:不适合分布式部署,因为session数据不能跨服务器共享。
Cookie
-
优点:
- 无服务器存储:减轻服务器存储负担,所有数据存储在客户端。
- 简单配置:实现简单,不需要额外的后端存储配置。
-
缺点:
- 安全性:数据暴露在客户端,容易被篡改或盗窃,不适合存储敏感信息。
- 大小限制:受HTTP协议限制,Cookie大小有限,不适合存储大量数据。
Redis
-
优点:
- 高性能:基于内存存储,读写速度快,接近原生内存操作。
- 持久化:支持数据持久化到磁盘,保证数据安全。
- 扩展性:易于扩展,支持主从复制和集群模式,适合分布式系统。
- 成熟方案:广泛应用于session存储,社区支持丰富。
-
缺点:
- 运维成本:需要维护Redis服务器,增加了运维工作量。
- 额外依赖:引入了新的组件,增加了系统的复杂度。
相关文章:
10、Go Gin 连接Redis以及CookieSession
一、Redis 在Go语言中,使用Gin框架结合Redis数据库可以构建高性能的Web应用程序。Gin是一个轻量级的HTTP框架,提供了快速构建RESTful API的能力;而Redis则是一个高性能的键值存储系统,常用于缓存、消息队列、计数器等多种场景 1、…...

Electron-Vue 脚手架避坑实录,兼容Win11,升级electron22,清理控制台错误
去年的还是有用的,大家继续看,今年再补充一些Electron-Vue 异常处理方案 M1 和 Window10_electron异常处理-CSDN博客 代码gitee.com地址 electron-demo: electron 22 初始代码开发和讲解 升级electron为22版本(这个版本承上启下,…...

国外新闻媒体推广:多元化媒体分发投放-大舍传媒
前言 :随着全球化的进程,国外新闻市场呈现出快速发展的趋势。在这个趋势下,国外新闻媒体推广成为了各行业企业宣传业务的重要一环。本文将重点介绍大舍传媒的多元化媒体分发投放服务,以及对国外新闻媒体推广的意义。 1. 多元化媒…...

【Windows】回忆Win98
回忆Win98,又看到了这个Excel界面,上次还是十多年前的计算机课上 1、安装环境 Win11家庭版,23H2,VMware Workstation Pro 16 , 2、安装步骤及参考 虚拟机里的硬盘设置成SATA(否则各种错误),安装MSDOS7.1ÿ…...
探索QChart:Qt中的数据可视化艺术
目录标题 1. QChart概述2. 创建QChart对象3. 添加数据系列(Series)4. 定制图表外观5. 交互与动画6. 图表布局与管理7. 实例代码与解析8. 总结 在数字化的世界里,数据是新的石油。然而,原始数据本身往往难以理解,数据可…...

【Linux】线程机制解析:理解、优势与Linux系统应用
文章目录 前言:1. 线程概念1.1. 什么是线程1.2. 线程得优点:1.3. 线程的缺点线程异常线程的用途 2. 线程的理解(Linux 系统为例)2.1. 为什么要设计Linux“线程"?2.2. 什么是进程?2.3. 关于调度的问题2…...
java中简单工厂模式,工厂方法模式和抽象工厂模式的区别和联系?
在Java中,简单工厂模式、工厂方法模式和抽象工厂模式都是创建型设计模式,用于解耦对象的创建过程,提高系统的灵活性和可扩展性。它们之间既有相似之处也有明显的区别: 简单工厂模式(Simple Factory Pattern࿰…...
SERVER_DOWN 表示该服务器已经宕机或无法访问
[{"type":"MASTER","host":"/nodes/master/ds-master-0.ds-master-headless:5678","event":"SERVER_DOWN","warningLevel":"SERIOUS"}] 该JSON数据描述了一个事件通知,具体地&am…...

深度论证-高速走线控制100欧姆阻抗一定是最好的选择吗?
高速先生成员--黄刚 对于高速差分信号到底需要控制多少欧姆的阻抗,高速先生相信大部分工程师首先都会看下例如信号的协议文档或者芯片的文档,看看里面有没有推荐的控制阻抗值。例如像PCIE信号,在4.0之后的阻抗会明确要求按照85欧姆来控制&…...

【文末福利送资料】深度探索GPT模型,竟然10个字都不会说?
目录 导读 自回归模型 那么什么时候停下呢? 该停下来,但是概率不让啊 GPT欠缺的两种能力 目录 导读 自回归模型 那么什么时候停下呢? 该停下来,但是概率不让啊 GPT欠缺的两种能力 缺少规划 反省和修订 所有的人工智能…...

一些近来对内网攻防的思考
我知道我最近托更托了很久了,其实也不是小编懒啊 这小编也是一直在写,但是遇到的问题比较多(我太菜了),所以一直拖着。 但是总不能不更吧 那就讲一下进来的一些内网攻防的思考吧 1.CrossC2上线Linux到CS(成功) …...

数据结构--顺序表和链表的区别
顺序表和链表之间各有优劣,我们不能以偏概全,所以我们在使用时要关注任务的注重点,以此来确定我们要使用两者中的哪一个。 不同点: 存储空间上: 顺序表在物理结构上是一定连续的,而链表(这里以带头双向循环…...

【技术分享】 OPC UA安全策略证书简述
那什么是OPC UA证书?用途是什么? 简单来说它是身份验证和权限识别。 OPC UA使用X.509证书标准,该标准定义了标准的公钥格式。建立UA会话的时候,客户端和服务器应用程序会协商一个安全通信通道。数字证书(X.509&#x…...

【Neo4jJDK开箱即用的安装全流程】
neo4j:命令行本地访问loclhost neo4j:命令行本地访问loclhost2 neo4j操作 Neo4j桌面版数据库导出导入 Neo4j安装与配置以及JDK安装与配置教程(超详细) Neo4j 安装、使用教程 Neo4j安装教程 Neo4J桌面版的配置和连接Pycharm jdk-neo对应版本 JDK ORACLE中…...

Linux 操作系统多路IO复用
1.多路IO复用 多路I/O复用是通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。 这个机制能够通过select/poll/eroll等来使用。这些函数都可以同时监视多…...
读取shape文件中数据
读取shape文件中数据 pom文件中引入依赖 <dependency><groupId>org.geotools</groupId><artifactId>gt-shapefile</artifactId><version>26.4</version></dependency>如果jar包下载不下来,在pom中添加下geotools的仓库 <…...

基于STM32F401RET6智能锁项目(使用库函数点灯、按键)
点灯硬件原理图 1、首先,我们查看一下原理图,找到相对应的GPIO口 LED_R低电平导通,LED4亮,所以LED_R的GPIO口需要配置一个低电平才能亮; LED_G低电平导通,LED3亮,所以LED_R的GPIO口需要配置一…...

网络层协议之 IP 协议
IP 协议格式 4 位版本:此处的取值只有两个,4(IPv4)和 6(IPv6),即指定 IP 协议的版本。 4 位首部长度:描述了 IP 报头多长,IP 报头是变长的,因为报头中的选项部…...

SpringBoot 实现对提供的接口进行 AES (加密,解密)
业务来源: 最近工作中,领导要求给别的项目组的小伙伴提供几个接口,要求对接口的参数进行解密操作,然后对返回的数据进行加密操作。 这时我想到了AES AES 是对称加密算法,优点:加密速度快;缺点…...

ASP.NET学生成绩管理系统
摘要 本系统依据开发要求主要应用于教育系统,完成对日常的教育工作中学生成绩档案的数字化管理。开发本系统可使学院教职员工减轻工作压力,比较系统地对教务、教学上的各项服务和信息进行管理,同时,可以减少劳动力的使用…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

EasyRTC音视频实时通话功能在WebRTC与智能硬件整合中的应用与优势
一、WebRTC与智能硬件整合趋势 随着物联网和实时通信需求的爆发式增长,WebRTC作为开源实时通信技术,为浏览器与移动应用提供免插件的音视频通信能力,在智能硬件领域的融合应用已成必然趋势。智能硬件不再局限于单一功能,对实时…...
简单介绍C++中 string与wstring
在C中,string和wstring是两种用于处理不同字符编码的字符串类型,分别基于char和wchar_t字符类型。以下是它们的详细说明和对比: 1. 基础定义 string 类型:std::string 字符类型:char(通常为8位)…...
当下AI智能硬件方案浅谈
背景: 现在大模型出来以后,打破了常规的机械式的对话,人机对话变得更聪明一点。 对话用到的技术主要是实时音视频,简称为RTC。下游硬件厂商一般都不会去自己开发音视频技术,开发自己的大模型。商用方案多见为字节、百…...