天天看点

GoFrame系列:5、项目配置、服务路由及运行方式

GoFrame系列:5、项目配置、服务路由及运行方式

文章目录

  • ​​GoFrame系列:5、项目配置、服务路由及运行方式​​
  • ​​1. 项目配置​​
  • ​​1.1 go.mod​​
  • ​​1.2 配置文件​​
  • ​​1.3 启动设置​​
  • ​​2. 服务路由​​
  • ​​2.1 路由注册​​
  • ​​2.2 分组路由​​
  • ​​2.3 中间件注册​​
  • ​​3. 运行​​
  • ​​3.1 配置引入​​
  • ​​3.2 `main`包​​
  • ​​3.3 编译运行​​
  • ​​3.4 接口测试​​
  • ​​3.4.1 用户注册 - `/user/signup`​​
  • ​​3.4.2 用户登录 - `/user/signin`​​
  • ​​4. 最后​​

1. 项目配置

我们推荐使用​

​go.mod​

​来管理项目依赖,这也是Golang官方推荐的包管理方式。

1.1 go.mod

​​https://github.com/gogf/gf-demos/blob/master/go.mod​​

module github.com/gogf/gf-demos

require github.com/gogf/gf latest

go 1.12      

其中注意​

​module​

​​名称设置为​

​github.com/gogf/gf-demos​

​​。这里我们只需要依赖​

​GF​

​​框架即可。其中的​

​go 1.12​

​​表示运行该项目所需的最低​

​Go​

​​版本,这里也可以不设置。​

​Goland​

​​会自动帮我们设置为当前使用的​

​Go​

​版本。

1.2 配置文件

​GF​

​​框架的核心组件均实现了便捷的文件配置管理方式,包括​

​Server​

​​、日志组件、数据库​

​ORM​

​​、模板引擎等等,非常强大便捷。具体的配置项可以查看后续对应的章节介绍。​

​GF​

​框架大部分的核心组件配置项是不区分大小写的,但是为保证规范统一,我们建议在配置文件中统一使用小驼峰形式。

​​https://github.com/gogf/gf-demos/blob/master/config/config.example.toml​​

需要注意哦,仓库中提供的​

​config.example.toml​

​​为配置文件示例,如果想要正常运行示例程序,你可以将其拷贝或者重命名为​

​config.toml​

​。

配置文件中如果存在文件路径相关的配置,建议统一使用绝对路径配置,会少踩很多坑。如果使用了相对路径,你得清楚知道该配置的路径相对的是哪个路径(不同的部署方式,工作目录可能不可预知)。

# HTTP Server.
[server]
    address        = ":8199"
    serverRoot     = "public"
    serverAgent    = "gf-demos"
    logPath        = "/tmp/log/gf-demos/server"
    nameToUriType  = 2
    routeOverWrite = true

# Logger configurations.
[logger]
    path   = "/tmp/log/gf-demos"
    level  = "all"
    stdout = true

# Template view configurations.
[viewer]
    path        = "template"
    defaultFile = "index.html"

# Database configurations.
[database]
    link  = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
    debug = true
    # 数据库日志对象配置
    [database.logger]
        Path   = "/tmp/log/gf-demos/sql"
        Level  = "all"
        Stdout = true

# GF-CLI工具配置
[gfcli]
    # 自定义DAO生成配置(默认是读取database配置)
    [[gfcli.gen.dao]]
        link   = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
        tables = "user"      

1.3 启动设置

在​

​boot​

​包中执行代码层级的初始化,比如一些组件模块的设置。

​​https://github.com/gogf/gf-demos/blob/master/boot/boot.go​​

package boot

import (
    _ "github.com/gogf/gf-demos/packed"

    "github.com/gogf/gf/frame/g"
    "github.com/gogf/swagger"
)

// 用于应用初始化。
func init() {
    s := g.Server()
    s.Plugin(&swagger.Swagger{})
}      

可以看到,我们的包初始化管理使用了包初始化方法​

​init​

​​来做隐式初始化,这样做的好处是可以在​

​boot​

​​目录中使用不同的​

​go​

​​文件注册不同的​

​init​

​来分别实现不同的初始化配置管理,在业务比较复杂的项目中比较实用。

2. 服务路由

2.1 路由注册

这里使用了分组路由的注册方式,分组路由也是推荐的路由注册方式。由于​

​gf-demos​

​项目包含其他的示例功能,因此该路由中包含了其他的一些路由注册项,仅供参考。

​​https://github.com/gogf/gf-demos/blob/master/router/router.go​​

package router

import (
    "github.com/gogf/gf-demos/app/api"
    "github.com/gogf/gf-demos/app/service"
    "github.com/gogf/gf/frame/g"
    "github.com/gogf/gf/net/ghttp"
)

func init() {
    s := g.Server()
    // 分组路由注册方式
    s.Group("/", func(group *ghttp.RouterGroup) {
        group.Middleware(
            service.Middleware.Ctx,
            service.Middleware.CORS,
        )
        group.ALL("/chat", api.Chat)
        group.ALL("/user", api.User)
        group.Group("/", func(group *ghttp.RouterGroup) {
            group.Middleware(service.Middleware.Auth)
            group.ALL("/user/profile", api.User.Profile)
        })
    })
}      

可以看到,我们的路由注册管理也使用了包初始化方法​

​init​

​​实现隐式初始化,这样做的好处是可以在​

​router​

​​目录中使用不同的​

​go​

​​文件注册不同的​

​init​

​​来分别实现不同的路由注册。当项目的路由比较多的时候,可以采用不同的​

​go​

​文件管理不同的路由,这在团队协作的项目中也比较方便。

2.2 分组路由

这里通过​

​s.Group​

​​方法使用了分组路由实现路由注册,并通过​

​group.All​

​​来实现具体的路由注册,分组路由请参考后续 ​​路由注册-分组路由​​ 章节。

如果您对​

​HTTP Method​

​​没有特殊的需求,建议统一使用​

​ALL​

​​方法注册路由,使得该路由可以被任意的​

​HTTP Method​

​​访问。特别是在跨域场景中,可能会同一个路由接口需要同时满足​

​POST​

​​和​

​OPTIONS​

​​请求,这种情况只有使用​

​ALL​

​方法注册路由。

2.3 中间件注册

这里使用了​

​group.Middleware​

​​方法注册中间件,可以将中间件看做请求的拦截器,可以在中间件中实现特定的请求处理后转发给下一层请求继续执行。中间件可以注册多个,​

​WebServer​

​​会按照中间件注册的顺序执行。中间件的具体介绍请参考后续 ​​路由管理-中间件/拦截器​​ 章节。

在该路由的配置中,所有接口均绑定了两个中间件:

  • ​service.Middleware.Ctx​

    ​初始化上下文变量
  • ​service.Middleware.CORS​

    ​允许跨域请求的中间件

其中​

​/user/profile​

​​路由绑定了鉴权中间件​

​service.Middleware.Auth​

​,需要鉴权控制才能访问。

3. 运行

3.1 配置引入

由于​

​boot​

​​和​

​router​

​​包使用了​

​init​

​包初始化方式来进行相关配置,因此我们需要使用:

import _ "PATH"      

方式来引入。

需要注意,由于​

​Go​

​​的​

​import​

​​存在先后顺序,往往需要将这两个包置于​

​main.go​

​所有业务包的最上方引入。

3.2 ​

​main​

​包

每个项目至少存在一个​

​package main​

​,用于程序的入口执行。

/main.go      
package main

import (
    _ "github.com/gogf/gf-demos/boot"
    _ "github.com/gogf/gf-demos/router"

    "github.com/gogf/gf/frame/g"
)

func main() {
    g.Server().Run()
}      

需要非常注意:​

​boot​

​​包的引入往往需要在​

​main​

​​包中的最顶层位置,以保证应用的初始化最开始进行。特别是一些单例对象的初始化/配置管理操作往往放在​

​boot​

​包中,这样其他包才能正常使用到这些单例对象。

这里建议引入​

​boot​

​​包、​

​router​

​​包和其他包之间加入一个空行以作区分,特别是​

​Goland​

​​ IDE的​

​import​

​插件不会将引入包进行自动排序。

3.3 编译运行

我们可以使用​

​IDE​

​执行运行,也可以使用以下命令编译运行。

$ go build main.go
$ ./main      

执行后,终端输出的路由表如下:

| DOMAIN  | ADDRESS | METHOD |        ROUTE        |                          HANDLER                          |                                                  MIDDLEWARE                                                    
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /chat               | github.com/gogf/gf-demos/app/api.(*apiChat).Index         | service.(*serviceMiddleware).Ctx-fm,service.(*serviceMiddleware).CORS-fm                                       
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /chat/index         | github.com/gogf/gf-demos/app/api.(*apiChat).Index         | service.(*serviceMiddleware).Ctx-fm,service.(*serviceMiddleware).CORS-fm                                       
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /chat/setname       | github.com/gogf/gf-demos/app/api.(*apiChat).SetName       | service.(*serviceMiddleware).Ctx-fm,service.(*serviceMiddleware).CORS-fm                                       
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /chat/websocket     | github.com/gogf/gf-demos/app/api.(*apiChat).WebSocket     | service.(*serviceMiddleware).Ctx-fm,service.(*serviceMiddleware).CORS-fm                                       
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /swagger/*          | github.com/gogf/swagger.(*Swagger).Install.func1.1        | HOOK_BEFORE_SERVE                                                                                              
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /user/checknickname | github.com/gogf/gf-demos/app/api.(*apiUser).CheckNickName | service.(*serviceMiddleware).Ctx-fm,service.(*serviceMiddleware).CORS-fm                                       
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /user/checkpassport | github.com/gogf/gf-demos/app/api.(*apiUser).CheckPassport | service.(*serviceMiddleware).Ctx-fm,service.(*serviceMiddleware).CORS-fm                                       
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /user/issignedin    | github.com/gogf/gf-demos/app/api.(*apiUser).IsSignedIn    | service.(*serviceMiddleware).Ctx-fm,service.(*serviceMiddleware).CORS-fm                                       
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /user/profile       | github.com/gogf/gf-demos/app/api.(*apiUser).Profile-fm    | service.(*serviceMiddleware).Ctx-fm,service.(*serviceMiddleware).CORS-fm,service.(*serviceMiddleware).Auth-fm  
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /user/signin        | github.com/gogf/gf-demos/app/api.(*apiUser).SignIn        | service.(*serviceMiddleware).Ctx-fm,service.(*serviceMiddleware).CORS-fm                                       
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /user/signout       | github.com/gogf/gf-demos/app/api.(*apiUser).SignOut       | service.(*serviceMiddleware).Ctx-fm,service.(*serviceMiddleware).CORS-fm                                       
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------
  default | default | :8199   | ALL    | /user/signup        | github.com/gogf/gf-demos/app/api.(*apiUser).SignUp        | service.(*serviceMiddleware).Ctx-fm,service.(*serviceMiddleware).CORS-fm                                       
----------|---------|---------|--------|---------------------|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------      

3.4 接口测试

我们通过​

​curl​

​命令来对其中两个接口执行简单的测试。

3.4.1 用户注册 - ​

​/user/signup​

注册一个账号​

​test001​

​​,昵称为​

​john​

​​,密码为​

​123456​

​。

curl -d 'nickname=john&passport=test001&password=123456&password2=123456'      
{"data":null,"code":0,"message":"ok"}      

我们再次使用刚才的信息注册一次试试。

curl -d 'nickname=john&passport=test001&password=123456&password2=123456'      
{"data":null,"code":1,"message":"账号 test001 已经存在"}      

可以看到注册失败了,相同名称只能注册一个账号。

3.4.2 用户登录 - ​

​/user/signin​

我们先访问获取用户信息的接口,验证鉴权中间件是否生效。

curl      
Forbidden      

我们用刚才注册的账号登录。

curl -i -d 'passport=test001&password=123456'      
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Origin,Content-Type,Accept,User-Agent,Cookie,Authorization,X-Auth-Token,X-Requested-With
Access-Control-Allow-Methods: GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3628800
Content-Type: application/json
Server: gf-demos
Set-Cookie: gfsessionid=BZT1SP2OX980EHALYV; Path=/; Expires=Sun, 10 Jan 2021 14:56:36 GMT
Date: Sat, 11 Jan 2020 14:56:36 GMT
Content-Length: 37

{"code":0,"message":"ok","data":null}      

我们这里使用了​

​-i​

​​选项用于终端打印出服务端返回的​

​Header​

​​信息,目的是为了获取​

​sessionid​

​​。​

​GF​

​​框架默认的​

​sessionid​

​​名称为​

​gfsessionid​

​​,我们看到返回的​

​Header​

​​中已经有了,并且是通过​

​Cookie​

​方式返回的。

随后我们再次访问获取用户信息接口,并且这次提交​

​gfsessionid​

​​,该信息可以通过​

​Header​

​​也可以通过​

​Cookie​

​提交,服务端都是能够自动识别的。

curl -H 'gfsessionid:BZT1SP2OX980EHALYV'      
{"code":0,"message":"","data":{"id":1,"passport":"test001","password":"123456","nickname":      

4. 最后