一、OmitEmpty空值过滤
空值会影响于写入/更新操作方法,如Insert, Replace, Update, Save操作。
当 map/struct 中存在空值如 nil,"",0 时,默认情况下,gdb将会将其当做正常的输入参数,因此这些参数也会被更新到数据表。
针对空值情况,我们可以通过OmitEmpty方法来过滤掉这些空值。
示例:db.Table("user").OmitEmpty().Data(user).Insert()
二、数据返回-模板解析
Response支持模板文件/内容解析输出,或者模板文件/内容解析返回。与直接使用模板对象解析模板功能不同的是,Response的解析支持一些请求相关的内置变量。模板解析包含以下方法:
WriteTpl*方法用于模板输出,解析并输出模板文件,也可以直接解析并输出给定的模板内容。
ParseTpl*方法用于模板解析,解析模板文件或者模板内容,返回解析后的内容。
解析模板时组件底层会自动通过Request对象获取当前链路的Context上下文变量并传递给模板引擎,因此开发者不用显示给模板引擎传递Context上下文变量。
内置变量:
1、Config:访问默认的配置管理(config.toml)对象配置项。
使用方式:{{.Config.配置项}}
2、Cookie:访问当前请求的Cookie对象参数值。
使用方式:{{.Cookie.键名}}
3、Session:访问当前请求的Session对象参数值。
使用方式:{{.Session.键名}}
4、Query:访问当前Query String中的请求参数值。
使用方式:{{.Query.键名}}
5、Form:访问当前表单请求参数值。
使用方式:{{.Form.键名}}
6、Request:访问当前请求参数值(不区分参数提交方式)。
使用方式:{{.Request.键名}}
三、请求输入-Context
请求流程往往会在上下文中共享一些自定义设置的变量,例如在请求开始之前通过中间件设置一些变量,随后在路由服务方法中可以获取该变量并相应对一些处理。这种需求非常常见。在GoFrame框架中,我们推荐使用Context上下文对象来处理流程共享的上下文变量,甚至将该对象进一步传递到依赖的各个模块方法中。该Context对象类型实现了标准库的context.Context接口,该接口往往会作为模块间调用方法的第一个参数,该接口参数也是Golang官方推荐的在模块间传递上下文变量的推荐方式。
方法列表:
func(r*Request)GetCtx()context.Context
func(r*Request)SetCtx(ctx context.Context)
func(r*Request)GetCtxVar(keyinterface{},def...interface{})*gvar.Var
func(r*Request)SetCtxVar(keyinterface{},valueinterface{})
简要说明:
GetCtx方法用于获取当前的context.Context对象,作用同Context方法。
SetCtx方法用于设置自定义的context.Context上下文对象。
GetCtxVar方法用于获取上下文变量,并可给定当该变量不存在时的默认值。
SetCtxVar方法用于设置上下文变量。
可以通过SetCtxVar和GetCtxVar来设置和获取自定义的变量,该变量生命周期仅限于当前请求流程。
四、HTTPClient-文件上传
在服务端通过Request对象获取上传文件:
funcUpload(r*ghttp.Request){
files:=r.GetUploadFiles("upload-file")
names,err:=files.Save("/tmp/")
iferr!=nil{
r.Response.WriteExit(err)
}
r.Response.WriteExit("upload successfully: ",names)}
关键代码说明
我们在服务端可以通过r.GetUploadFiles方法获得上传的所有文件对象,也可以通过r.GetUploadFile获取单个上传的文件对象。
在r.GetUploadFiles("upload-file")中的参数"upload-file"为本示例中客户端上传时的表单文件域名称,开发者可以根据前后端约定在客户端中定义,以方便服务端接收表单文件域参数。
通过files.Save可以将上传的多个文件方便地保存到指定的目录下,并返回保存成功的文件名。如果是批量保存,只要任意一个文件保存失败,都将会立即返回错误。此外,Save方法的第二个参数支持随机自动命名上传文件。
通过group.POST("/", Upload)注册的路由仅支持POST方式访问。
文件上传参数格式使用了 参数名=@file:文件路径 ,HTTP客户端将会自动解析文件路径对应的文件内容并读取提交给服务端。原本复杂的文件上传操作被gf进行了封装处理,用户只需要使用 @file:+文件路径 来构成参数值即可。其中,文件路径请使用本地文件绝对路径。
多个文件上传提交参数格式为参数名=@file:xxx&参数名=@file:xxx...,也可以使用参数名[]=@file:xxx&参数名[]=@file:xxx...的形式。
五、Session
任何时候都可以通过ghttp.Request获取Session对象,因为Cookie和Session都是和请求会话相关,因此都属于Request的成员对象,并对外公开。GoFrame框架的Session默认过期时间是24小时。
SessionId默认通过Cookie来传递,并且也支持客户端通过Header传递SessionId,SessionId的识别名称可以通过ghttp.Server的SetSessionIdName进行修改。Session的操作是支持并发安全的,这也是框架在对Session的设计上不采用直接以map的形式操作数据的原因。在HTTP请求流程中,我们可以通过ghttp.Request对象来获取Session对象,并执行相应的数据操作。
gsession模块
Session的管理功能由独立的gsession模块实现,并已完美整合到了ghttp.Server中。由于该模块是解耦独立的,因此可以应用到更多不同的场景中,例如:TCP通信、gRPC接口服务等等。在gsession模块中有比较重要的三个对象/接口:
gsession.Manager:管理Session对象、Storage持久化存储对象、以及过期时间控制。
gsession.Session:单个Session会话管理对象,用于Session参数的增删查改等数据管理操作。
gsession.Storage:这是一个接口定义,用于Session对象的持久化存储、数据写入/读取、存活更新等操作,开发者可基于该接口实现自定义的持久化存储特性。
Session的初始化
以常见的HTTP请求为例。ghttp.Request中的Session对象采用了"懒初始化(LazyInitialization)"设计方式,默认在Request中有一个Session属性对象,但是并未初始化(一个空对象),只有在使用Session属性对象的方法时才会真正执行初始化。这样的设计既保障了未使用Session特性的请求执行性能,也保证了组件使用的易用性。
Session的销毁/注销
用户Session不再使用,例如用户注销登录状态,需要从存储中硬删除,那么可以调用RemoveAll方法。
在默认情况下,ghttp.Server的Session存储使用了内存+文件的方式,使用StorageFile对象实现。具体原理为:
Session的数据操作完全基于内存;
使用gcache进程缓存模块控制数据过期;
使用文件存储持久化存储管理Session数据;
当且仅有当Session被标记为dirty时(数据有更新)才会执行Session序列化并执行文件持久化存储;
当且仅当内存中的Session不存在时,才会从文件存储中反序列化恢复Session数据到内存中,降低IO调用;
序列化/反序列化使用的是标准库的json.Marshal/UnMarshal方法;
六、日志管理
使用配置文件的方式来管理服务配置以及日志配置。 一个参考的日志配置内容示例(以yaml格式为例):
logger:
path:"/var/log/"# 日志文件路径。默认为空,表示关闭,仅输出到终端
file:"{Y-m-d}.log"# 日志文件格式。默认为"{Y-m-d}.log"
prefix:""# 日志内容输出前缀。默认为空
level:"all"# 日志输出级别
ctxKeys:[]# 自定义Context上下文变量名称,自动打印Context的变量到日志中。默认为空
header:true# 是否打印日志的头信息。默认true
stdout:true# 日志是否同时输出到终端。默认true
rotateSize:0# 按照日志文件大小对文件进行滚动切分。默认为0,表示关闭滚动切分特性
rotateExpire:0# 按照日志文件时间间隔对文件滚动切分。默认为0,表示关闭滚动切分特性
rotateBackupLimit:0# 按照切分的文件数量清理切分文件,当滚动切分特性开启时有效。默认为0,表示不备份,切分则删除
rotateBackupExpire:0# 按照切分的文件有效期清理切分文件,当滚动切分特性开启时有效。默认为0,表示不备份,切分则删除
rotateBackupCompress:0# 滚动切分文件的压缩比(0-9)。默认为0,表示不压缩
rotateCheckInterval:"1h"# 滚动切分的时间检测间隔,一般不需要设置。默认为1小时
stdoutColorDisabled:false# 关闭终端的颜色打印。默认开启
writerColorEnable:false# 日志文件是否带上颜色。默认false,表示不带
七、自定义状态码处理
我们可以对WebServer指定的状态码进行自定义处理,例如针对常见的404/403/500等错误,我们可以展示自定义的错误信息、页面内容,或者跳转到一个特定的页面。
我们可以使用BindStatusHandler或者BindStatusHandlerMap来实现针对指定的状态码进行自定义的回调函数处理,并且该特性也支持针对特定的域名绑定。
我们来看几个简单的示例:
s.BindStatusHandler(404,func(r*ghttp.Request){
r.Response.Writeln("This is customized 404 page")
})
执行后,当我们访问没有绑定的路由页面,可以看到,页面显示了我们期望的返回结果:This is customized 404 page。
s.BindStatusHandler(404,func(r*ghttp.Request){
r.Response.RedirectTo("/status/404")
})
执行后,我们手动通过浏览器访问一个不存在的页面,可以看到,页面被引导跳转到了 http://127.0.0.1:8199/status/404 页面,并且可以看到页面返回内容:woops, status 404 found
八、数据校验-校验规则
required
格式: required
说明:必需参数,除了支持常见的字符串,也支持Slice/Map类型。
示例:姓名字段Name为必需参数且不能为空。
typeBizReqstruct{
IDuint`v:"required"`
Namestring`v:"required"`
}
格式:email
说明:EMAIL邮箱地址
phone
格式:phone
说明:手机号
phone-loose
格式: phone
说明:宽松的手机号验证,只要满足 13、14、15、16、17、18、19开头的11位数字都可以通过验证。
passport
格式: passport
说明:通用帐号规则(字母开头,只能包含字母、数字和下划线,长度在6~18之间)。
password
格式: password
说明:通用密码规则(任意可见字符,长度在6~18之间)。
json
格式: json
说明:判断数据格式为JSON
same
格式: same:field
说明:参数值必需与field参数的值相同
示例:在用户注册时,提交密码Password和确认密码Password2必须相等(服务端校验)。
typeBizReqstruct{
Namestring`v:"required"`
Passwordstring`v:"required|same:Password2"`
Password2string`v:"required"`
}
regex
格式: regex:pattern
说明:参数值应当满足正则匹配规则pattern
网友评论