golang,gin框架的请求参数(一)--推荐
golang,gin框架的请求参数(一)
gin框架的重要性不过多的强调,重点就gin使用中的参数传递,获取进行梳理文件,满足使用需求。
获取前端请求参数的几种方法:
一、获取参数【浏览器地址获取参数】
1.浏览器地址栏获取参数
1.获取 URL (query)参数
例如:/user/search?username=zhangsan&address=北京。 获取请求的query参数的方法如下:
URL 参数可以通过DefaultQuery() 和 Query() 两个参数获取
这两个【DefaultQuery() 和 Query() 】的区别就是,DefaultQuery()可以放个默认参数,如果没有存参数那么就是使用默认参数,
Query()如果不给参数,就是默认为“”
示例:
1.1后端代码:
package mainimport ("github.com/gin-gonic/gin""net/http"
)// /user/search?username=zhangsan&address=北京
// urlQuery 获取 url中?后面携带的参数
func urlQueryHandle(ctx *gin.Context) {// 如果指定的key 没有对应的值就使用默认值username1 := ctx.DefaultQuery("username", "lisi")// 根据key 获取值username2 := ctx.Query("username")address := ctx.Query("address")// 返回JSON 字符串ctx.JSON(http.StatusOK, gin.H{"message": "ok","username1": username1,"username2": username2,"address": address,})
}
func main() {// 创建默认路由r := gin.Default()// 绑定路由规则r.GET("/user/search", urlQueryHandle)// 监听端口r.Run(":9000")
}
1.2浏览器访问,从中可以看到我们没有给任何参数,后端Query查询的都是为“”
1.3带参数的访问
http://127.0.0.1:9000/user/search?username=tom&address=xian&username=jerry
?username=tom&address=xian&username=jerry
1.3.1postman获取参数
2.获取参数【获取Path参数(RestFul风格)】
请求的参数通过URL路径传递,例如:/user/search/lisi/北京。 获取请求URL路径中的参数的方式如下。
以下代码是上述两种浏览器获取参数的办法,具体看代码品味下;
package mainimport ("github.com/gin-gonic/gin""net/http"
)// /user/search?username=zhangsan&address=北京
// urlQuery 获取 url中?后面携带的参数
func urlQueryHandle(ctx *gin.Context) {// 如果指定的key 没有对应的值就使用默认值username1 := ctx.DefaultQuery("username", "lisi")// 根据key 获取值username2 := ctx.Query("username")address := ctx.Query("address")// 返回JSON 字符串ctx.JSON(http.StatusOK, gin.H{"message": "ok","username1": username1,"username2": username2,"address": address,})
}// /user/search/lisi/北京。 获取请求URL路径中的参数的方式如下
// paramsPathHandle 获取url path中参数
func paramsPathHandle(ctx *gin.Context) {// 获取参数值username := ctx.Param("username")address := ctx.Param("address")// 数据返回ctx.JSON(http.StatusOK, gin.H{"message": "ok","username": username,"address": address,})
}func main() {// 创建默认路由r := gin.Default()//两种浏览器地址获取参数的办法// 绑定路由规则 /user/search?username=zhangsan&address=北京r.GET("/user/search", urlQueryHandle)// 2. 绑定路由规则/user/search/lisi/北京。 获取请求URL路径中的参数的方式如下r.GET("/user/search/:username/:address", paramsPathHandle)// 监听端口r.Run(":9000")
}
二、表单获取参数获取 Form参数
表单提交POST请求时,http常见的传输格式有四种application/json (json格式)
- text/plain (text格式)
- application/x-www-form-urlencode(表单默认提交格式)
- application./xml (xml格式)
- multipart/form-data( 文件上传)
可以通过 DefaultPostForm() 和 PostForm() 两个方法获取(默认解析的是 x-www-form-urlencode 和 form-data 格式的参数)
2.1获取form表单数据
2.1.1application/x-www-form-urlencode(表单默认提交格式)
因为发起post请求,前端只能用postman模拟了
返回结果
2.1.2form-data表单提交方式
2.2获取json参数【ctx.GetRowData()】
2.2.1请求数据application./json(json格式)
2.2.2 application./xml (xml格式)
2.3文件上传事项
2.3.1文件上传接收的文件格式要求:
格式是: multipart/form-data
2.3.2多文件上传
2.4表单数据获取的代码
package mainimport ("encoding/json""fmt""github.com/gin-gonic/gin""net/http"
)// /user/search?username=zhangsan&address=北京
// urlQuery 获取 url中?后面携带的参数
func urlQueryHandle(ctx *gin.Context) {// 如果指定的key 没有对应的值就使用默认值username1 := ctx.DefaultQuery("username", "lisi")// 根据key 获取值username2 := ctx.Query("username")address := ctx.Query("address")// 返回JSON 字符串ctx.JSON(http.StatusOK, gin.H{"message": "ok","username1": username1,"username2": username2,"address": address,})
}// /user/search/lisi/北京。 获取请求URL路径中的参数的方式如下
// paramsPathHandle 获取url path中参数
func paramsPathHandle(ctx *gin.Context) {// 获取参数值username := ctx.Param("username")address := ctx.Param("address")// 数据返回ctx.JSON(http.StatusOK, gin.H{"message": "ok","username": username,"address": address,})
}//=================================// formParamsHandle 获取form表单提交数据
func formParamsHandle(ctx *gin.Context) {// 获取不到值时就是用默认值username1 := ctx.DefaultPostForm("username", "lisi")username2 := ctx.PostForm("username")address := ctx.PostForm("address")// 以Json 字符串的形式返回ctx.JSON(http.StatusOK, gin.H{"message": "ok","username1": username1,"username2": username2,"address": address,})
}// json参数
// paramsJsonHandle 获取json字符串相关的参数
func paramsJsonHandle(ctx *gin.Context) {// 获取request.Body() 中的数据(这里没有进行错误处理)// 返回的是字节数组dataBytes, _ := ctx.GetRawData()// 定义一个mapvar m map[string]interface{}// 反序列化 别忘了&_ = json.Unmarshal(dataBytes, &m)// 数据返回ctx.JSON(http.StatusOK, m)}//文件上传
/*单个文件上传文件上传接收的文件格式是: multipart/form-data
*/// singleFileUploadHandle 当文件上传
func singleFileUploadHandle(ctx *gin.Context) {// 获取文件// 根据上传时的参数名获取上传的文件内容 --> 返回对象为 *multipart.FileHeaderfileHeader, err := ctx.FormFile("file")if err != nil {ctx.JSON(http.StatusInternalServerError, gin.H{"message": err.Error(),})return}// 保存文件内容// 拼接文件名, 这里直接写死了targetFileName := fmt.Sprintf("C:/Users/黑熊精/Pictures/%s", fileHeader.Filename)//targetFileName := fmt.Sprintf("%s", fileHeader.Filename)// 将文件保存到指定的目录err = ctx.SaveUploadedFile(fileHeader, targetFileName)if err != nil {ctx.JSON(http.StatusInternalServerError, gin.H{"message": err.Error(),})} else {ctx.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("%s upload success!", fileHeader.Filename),})}
}//多文件上传/**多文件上传
*/// multiFileUploadHandle 多文件上传
func multiFileUploadHandle(ctx *gin.Context) {// form 是一个存储文件信息的结构体/**type Form struct {Value map[string][]stringFile map[string][]*FileHeader*/form, err := ctx.MultipartForm()if err != nil {ctx.JSON(http.StatusInternalServerError, gin.H{"message": err.Error(),})return}// 获取文件列表,并保存, 返回的是一个切片 []*FileHeaderfiles := form.File["file"]for i, file := range files {targetFileName := fmt.Sprintf("C:/Users/黑熊精/Pictures/%d_%s", i, file.Filename)err = ctx.SaveUploadedFile(file, targetFileName)if err != nil {ctx.JSON(http.StatusInternalServerError, gin.H{"message": err.Error(),})return}}ctx.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("upload success!"),})
}func main() {// 创建默认路由r := gin.Default()//两种浏览器地址获取参数的办法// 绑定路由规则 /user/search?username=zhangsan&address=北京r.GET("/user/search", urlQueryHandle)// 2. 绑定路由规则/user/search/lisi/北京。 获取请求URL路径中的参数的方式如下r.GET("/user/search/:username/:address", paramsPathHandle)//========================表单提交方法======================// 绑定路由规则r.POST("/user/search", formParamsHandle)//json// 绑定路由规则r.POST("/user/json", paramsJsonHandle)//// 绑定路由规则--文件上传r.POST("/upload/single", singleFileUploadHandle)绑定路由规则--多文件上传r.POST("/upload/multi", multiFileUploadHandle)// 监听端口r.Run(":9000")
}
2.5参数绑定--优化数据方式
使用 ShouldBind() 方法, 根据请求方式,自动提取 JSON, form表单 和 Query 类型的参数,放入结构体中
2.5.1url query参数解析
2.5.2form表单参数解析
2.5.3json 数据解析
三、程序的所有代码
package mainimport ("encoding/json""fmt""github.com/gin-gonic/gin""net/http"
)// /user/search?username=zhangsan&address=北京
// urlQuery 获取 url中?后面携带的参数
func urlQueryHandle(ctx *gin.Context) {// 如果指定的key 没有对应的值就使用默认值username1 := ctx.DefaultQuery("username", "lisi")// 根据key 获取值username2 := ctx.Query("username")address := ctx.Query("address")// 返回JSON 字符串ctx.JSON(http.StatusOK, gin.H{"message": "ok","username1": username1,"username2": username2,"address": address,})
}// /user/search/lisi/北京。 获取请求URL路径中的参数的方式如下
// paramsPathHandle 获取url path中参数
func paramsPathHandle(ctx *gin.Context) {// 获取参数值username := ctx.Param("username")address := ctx.Param("address")// 数据返回ctx.JSON(http.StatusOK, gin.H{"message": "ok","username": username,"address": address,})
}//=================================// formParamsHandle 获取form表单提交数据
func formParamsHandle(ctx *gin.Context) {// 获取不到值时就是用默认值username1 := ctx.DefaultPostForm("username", "lisi")username2 := ctx.PostForm("username")address := ctx.PostForm("address")// 以Json 字符串的形式返回ctx.JSON(http.StatusOK, gin.H{"message": "ok","username1": username1,"username2": username2,"address": address,})
}// json参数
// paramsJsonHandle 获取json字符串相关的参数
func paramsJsonHandle(ctx *gin.Context) {// 获取request.Body() 中的数据(这里没有进行错误处理)// 返回的是字节数组dataBytes, _ := ctx.GetRawData()// 定义一个mapvar m map[string]interface{}// 反序列化 别忘了&_ = json.Unmarshal(dataBytes, &m)// 数据返回ctx.JSON(http.StatusOK, m)}//文件上传
/*单个文件上传文件上传接收的文件格式是: multipart/form-data
*/// singleFileUploadHandle 当文件上传
func singleFileUploadHandle(ctx *gin.Context) {// 获取文件// 根据上传时的参数名获取上传的文件内容 --> 返回对象为 *multipart.FileHeaderfileHeader, err := ctx.FormFile("file")if err != nil {ctx.JSON(http.StatusInternalServerError, gin.H{"message": err.Error(),})return}// 保存文件内容// 拼接文件名, 这里直接写死了targetFileName := fmt.Sprintf("C:/Users/黑熊精/Pictures/%s", fileHeader.Filename)//targetFileName := fmt.Sprintf("%s", fileHeader.Filename)// 将文件保存到指定的目录err = ctx.SaveUploadedFile(fileHeader, targetFileName)if err != nil {ctx.JSON(http.StatusInternalServerError, gin.H{"message": err.Error(),})} else {ctx.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("%s upload success!", fileHeader.Filename),})}
}//多文件上传/**多文件上传
*/// multiFileUploadHandle 多文件上传
func multiFileUploadHandle(ctx *gin.Context) {// form 是一个存储文件信息的结构体/**type Form struct {Value map[string][]stringFile map[string][]*FileHeader*/form, err := ctx.MultipartForm()if err != nil {ctx.JSON(http.StatusInternalServerError, gin.H{"message": err.Error(),})return}// 获取文件列表,并保存, 返回的是一个切片 []*FileHeaderfiles := form.File["file"]for i, file := range files {targetFileName := fmt.Sprintf("C:/Users/黑熊精/Pictures/%d_%s", i, file.Filename)err = ctx.SaveUploadedFile(file, targetFileName)if err != nil {ctx.JSON(http.StatusInternalServerError, gin.H{"message": err.Error(),})return}}ctx.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("upload success!"),})
}// shuldbind数据的绑定的办法
// 使用 ShouldBind() 方法, 根据请求方式,自动提取 JSON, form表单 和 Query 类型的参数,放入结构体中
// 用户信息信息结构体
// 加上 binding:"required" 标签,说明该参数是必填的,如果不填就会报错
type UserInfo struct {Username string `json:"username" form:"username" binding:"required"`Address string `json:"address" form:"address" binding:"required"`
}// 获取query参数
func queryHandle(ctx *gin.Context) {var userInfo UserInfo// 获取数据err := ctx.ShouldBind(&userInfo)if err == nil {ctx.JSON(http.StatusOK, gin.H{"message": "ok","username": userInfo.Username,"address": userInfo.Address,})} else {ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}
}func jsonHandle(ctx *gin.Context) {var userInfo UserInfo// 获取数据err := ctx.ShouldBind(&userInfo)if err == nil {ctx.JSON(http.StatusOK, gin.H{"message": "ok","username": userInfo.Username,"address": userInfo.Address,})} else {ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}
}func fromHandle(ctx *gin.Context) {var userInfo UserInfo// 获取数据err := ctx.ShouldBind(&userInfo)if err == nil {ctx.JSON(http.StatusOK, gin.H{"message": "ok","username": userInfo.Username,"address": userInfo.Address,})} else {ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}
}func main() {// 创建默认路由r := gin.Default()//两种浏览器地址获取参数的办法// 绑定路由规则 /user/search?username=zhangsan&address=北京r.GET("/user/search", urlQueryHandle)// 2. 绑定路由规则/user/search/lisi/北京。 获取请求URL路径中的参数的方式如下r.GET("/user/search/:username/:address", paramsPathHandle)//========================表单提交方法======================// 绑定路由规则r.POST("/user/search", formParamsHandle)//json// 绑定路由规则r.POST("/user/json", paramsJsonHandle)//// 绑定路由规则--文件上传r.POST("/upload/single", singleFileUploadHandle)绑定路由规则--多文件上传r.POST("/upload/multi", multiFileUploadHandle)//使用 ShouldBind() 方法, 根据请求方式,自动提取 JSON, form表单 和 Query 类型的参数,放入结构体中// 绑定路由规则r.GET("/user/query", queryHandle)r.POST("/user/form", fromHandle)r.POST("/user/jsons", jsonHandle)// 监听端口r.Run(":9000")
}
相关文章:

golang,gin框架的请求参数(一)--推荐
golang,gin框架的请求参数(一) gin框架的重要性不过多的强调,重点就gin使用中的参数传递,获取进行梳理文件,满足使用需求。 获取前端请求参数的几种方法: 一、获取参数【浏览器地址获取参数】…...

ardupilot 遥控的输入控制模式
目录 本节主要记录自己整理ardupilot的遥控器的输入控制模式:正常模式、简单模式、超简单模式的理解。 1.正常模式(有头模式) 在不用简单和超简单的模式的情况下,无人机操作员操作的控制输入是对应着不断旋转着的飞行器进行操作的。如上方图所示举例,当无人机操作员进行…...
Unity UGUI的StandaloneInputModule (标准输入模块)组件的介绍及使用
Unity UGUI的StandaloneInputModule (标准输入模块)组件的介绍及使用 1. 什么是StandaloneInputModule组件? StandaloneInputModule是Unity UGUI系统中的一个标准输入模块组件,用于处理鼠标和键盘的输入事件。它可以将鼠标和键盘的输入转化为UGUI系统中…...

惠普HP Color Laser 150a开机红色感叹号闪烁不打印故障解决方法
故障描述: 惠普HP Color Laser 150a开机红色感叹号闪烁,不能打印,电脑提示C3-6140。 检测分析: 在解决C3-6140错误代码之前,我们需要先检查打印机是否连接正常。如果打印机连接不正常,也可能会出现这个错误…...

CVE-2023-1454注入分析复现
简介 JeecgBoot的代码生成器是一种可以帮助开发者快速构建企业级应用的工具,它可以通过一键生成前后端代码,无需写任何代码,让开发者更多关注业务逻辑。 影响版本 Jeecg-Boot<3.5.1 环境搭建 idea 后端源码: https://git…...
MFC使用png做背景图片
在MFC中使用png图片作为背景,你需要使用GDI库。以下是一个简单的示例: 首先,你需要在你的项目中包含GDI头文件和库。在你的stdafx.h(或者你的项目预编译头文件)中添加以下代码: #include <GdiPlus.h&g…...
Java开发的基石:JDK
Java开发的基石:JDK 前言一、引入二、JDK的发展历程三、JDK主要目录结构解析四、JDK的使用 前言 本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注博主!也许一个人独行,可以走的很快&…...

使用langchain与你自己的数据对话(三):检索(Retrieval)
之前我已经完成了使用langchain与你自己的数据对话的前两篇博客,还没有阅读这两篇博客的朋友可以先阅读一下: 使用langchain与你自己的数据对话(一):文档加载与切割使用langchain与你自己的数据对话(二):向量存储与嵌入 今天我们…...

DEVICENET转ETHERNET/IP网关devicenet协议
捷米JM-EIP-DNT,你听说过吗?这是一款自主研发的ETHERNET/IP从站功能的通讯网关,它能够连接DEVICENET总线和ETHERNET/IP网络,从而解决生产管理系统中协议不同造成的数据交换互通问题。 这款产品在工业自动化领域可谓是一大利器&…...

GPT一键化身「AI助理」——自定义指令功能
最近GPT又更新了一个超实用的功能——自定义指令,启用后,你可以给GPT设置一些固定指令,让它记住或扮演某个角色,比如客服、律师、投资管理师、老师、营养师...... 这样,我们就不再需要每次都要打开新的聊天,…...
深入理解Promise
原文合集地址如下,有需要的朋友可以关注 本文地址 合集地址 什么是Promise 当谈论 Promise 时,可以将其比喻为一种承诺或契约,用于处理异步操作的结果。异步操作是指那些不会立即完成的操作,比如从服务器获取数据、读取文件、发送网络请求等等。通常情况下,这些操作需…...

【2023 年第二届钉钉杯大学生大数据挑战赛】 初赛 B:美国纽约公共自行车使用量预测分析 问题三时间序列预测Python代码分析
2023 年第二届钉钉杯大学生大数据挑战赛 初赛 B:美国纽约公共自行车使用量预测分析 问题三时间序列预测Python代码分析 相关链接 【2023 年第二届钉钉杯大学生大数据挑战赛】 初赛 B:美国纽约公共自行车使用量预测分析 问题一Python代码分析 【2023 年…...

redis-cluster 创建及监控
集群命令 cluster info:打印集群的信息。 cluster nodes:列出集群当前已知的所有节点(node)的相关信息。 cluster meet <ip> <port>:将ip和port所指定的节点添加到集群当中。 cluster addslots <slot…...

vue+ivew model框 select校验遇到的问题
iview model 点击关闭,校验没有通过也会关闭 解决办法: 第一步:自定义页脚内容 <div slot"footer"><Button type"primary" click"confirmCarryOver()">确认</Button><Button click&qu…...

mybatis_分页
目的: 减少数据处理量,提高效率 普通sql: 语法:select * from user limit startIndex,pageSize; SELECT * from user limit 3; #[0,n] mybatis_sql: 接口: //分页查询List<User> getUserByLimit(Map<…...

轻量级Firefox Send替代方案Gokapi
想不到一个域名的变动会影响这么大,访问量出现断崖式下跌。由此可见,平时的访问应该只是一些 RSS 的访问而已。 上面是 Pageviews,下面是 Uniques 今天略有回升 难怪那些大公司要花钱买域名了,不过老苏是个佛系的人,一…...
多次发请求优化为发一次请求
优化 getUserInfo 请求 要求 getUserInfo 是个通用接口,在各个模块里面都有可能使用 requestUserInfo 模拟的是请求服务端真正获取用户信息的方法 业务背景 在一个页面有 A, B, C 等多个功能模块,A, B, C 模块渲染执行顺序不可控每个模块都会调用 get…...

彻底搞懂CPU的特权等级
x86 处理器中,提供了4个特权级别:0,1,2,3。数字越小,特权级别越高! 一般来说,操作系统是的重要性、可靠性是最高的,需要运行在 0 特权级; 应用程序工作在最上层,来源广泛、可靠性最低,工作在 3 特权级别。 中间的1 和 2 两个特权级别,一般很少使用。 理论上来讲,…...

JVM对象在堆内存中是否如何分配?
1:指针碰撞:内存规整的情况下 2:空闲列表: 内存不规整的情况下 选择那种分配方式 是有 java堆是否规整而决定的。而java堆是否规整是否对应的垃圾回收器是否带有空间压缩整理的能力决定的。 因此当使用Serial,ParNew等带有压缩整理过程的收…...

【小白慎入】还在手动撸浏览器?教你一招分分钟自动化操作浏览器(Python进阶)
大家好啊,辣条哥又来猛货了! 小白慎入! 目录 环境安装1 测试样例2 基本配置2.0 基本参数2.1 设置窗口2.2 添加头部2.3 网页截图2.4 伪装浏览器 绕过检测2.5案例演示 触发JS2.6 boss直聘cookie反爬绕过实践2. 7滚动到页面底部 3 进阶使用4 数…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...
【实施指南】Android客户端HTTPS双向认证实施指南
🔐 一、所需准备材料 证书文件(6类核心文件) 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...
ThreadLocal 源码
ThreadLocal 源码 此类提供线程局部变量。这些变量不同于它们的普通对应物,因为每个访问一个线程局部变量的线程(通过其 get 或 set 方法)都有自己独立初始化的变量副本。ThreadLocal 实例通常是类中的私有静态字段,这些类希望将…...
Docker、Wsl 打包迁移环境
电脑需要开启wsl2 可以使用wsl -v 查看当前的版本 wsl -v WSL 版本: 2.2.4.0 内核版本: 5.15.153.1-2 WSLg 版本: 1.0.61 MSRDC 版本: 1.2.5326 Direct3D 版本: 1.611.1-81528511 DXCore 版本: 10.0.2609…...