天天看点

Kratos 集成Gin

Kratos 集成 Gin

    • 规范项目分层
    • 处理请求处理、响应
    • 编写路由route
    • Kratos 集成gin
    • 注入 wire set中

Kratos 可以在

.proto

文件定义请求类型,URL,响应等等,如官方示例:

service BlogService {
    rpc CreateArticle (CreateArticleRequest) returns (CreateArticleReply) {
        option (google.api.http) = {
            post: "/v1/article/"
            body: "*"
        };
    }
    rpc UpdateArticle (UpdateArticleRequest) returns (UpdateArticleReply) {
        option (google.api.http) = {
            put: "/v1/article/{id}"
            body: "*"
        };
    }
    rpc DeleteArticle (DeleteArticleRequest) returns (DeleteArticleReply) {
        option (google.api.http) = {
            delete: "/v1/article/{id}"
        };
    }
    rpc GetArticle (GetArticleRequest) returns (GetArticleReply) {
        option (google.api.http) = {
            get: "/v1/article/{id}"
        };
    }
    rpc ListArticle (ListArticleRequest) returns (ListArticleReply) {
        option (google.api.http) = {
            get: "/v1/article/"
        };
    }
}
           

通过使用命令行工具 kratos 可以生成相关 http 请求处理、路由定义等,省略了自己去处理请求、响应等过程。

Kratos 的项目分层借鉴了 DDD 的思想,在官方推荐的 project layout 中,用户接口层(interfaces)的作用体现在了 api 层。

如果我们不使用官方自带的 http 处理方案(通过

.proto

生成样板代码),而是使用 gin 框架的话,需要自己做如下事情:

  1. 规范项目分层,在

    /internal

    目录下,新增一个用户接口层

    /interfaces

    (DDD思想)
  2. 通过gin编写自己的请求处理、响应
  3. 通过gin定义路由
  4. kratos 集成 gin
  5. 注入 wire set 中

规范项目分层

PS :kratos 的 biz 层更多是DDD 中 domain + repo接口定义 ,但是官方该层给的后缀却是 XXUseCase,个人感觉不太对啊, 还是自己的知识错了?

/internal

目录下新建

/interfaces

目录

之后的处理请求、编写路由、wire Provider 都在该目录下定义,最终结果如图:

Kratos 集成Gin

处理请求处理、响应

在用户接口层

/interfaces

编写请求处理的方法,写了个最简单的

SayHi

// user.go 
package interfaces

import (
	"context"
	"kratos-admin/internal/service"

	"github.com/go-kratos/kratos/v2/log"

	"github.com/gin-gonic/gin"
)

type UserUseCase struct {
	userService *service.UserService
	log         *log.Helper
}

func NewUserUseCase(us *service.UserService, logger log.Logger) *UserUseCase {
	return &UserUseCase{userService: us, log: log.NewHelper(logger)}
}

func (u *UserUseCase) SayHi(c *gin.Context) {
	c.JSON(200, gin.H{
		"msg": "hello world",
	})
}
           

编写路由route

// routes.go 

package interfaces

import (
	"github.com/gin-gonic/gin"
)

func RegisterHTTPServer(
	us *UserUseCase) *gin.Engine {
	router := gin.New()

	rootGrp := router.Group("/api")
	{
		userGrp := rootGrp.Group("/user")
		userGrp.GET("/sayhi", us.Get)
	}

	return router
}
           

Kratos 集成gin

/server/http.go

中注册路由:

// server/http.go

// NewHTTPServer new a HTTP server.
func NewHTTPServer(c *conf.Server,
	user *interfaces.UserUseCase,  // 新增参数
	logger log.Logger) *transHttp.Server {
	var opts = []transHttp.ServerOption{
		transHttp.Middleware(
			recovery.Recovery(),
			tracing.Server(),
			logging.Server(logger),
			metrics.Server(),
			validate.Validator(),
		),
	}
	if c.Http.Network != "" {
		opts = append(opts, transHttp.Network(c.Http.Network))
	}
	if c.Http.Addr != "" {
		opts = append(opts, transHttp.Address(c.Http.Addr))
	}
	if c.Http.Timeout != nil {
		opts = append(opts, transHttp.Timeout(c.Http.Timeout.AsDuration()))
	}
	srv := transHttp.NewServer(opts...)

    // 调用 interfaces.RegisterHTTPServer 注入到 srv 中
	srv.HandlePrefix("/", interfaces.RegisterHTTPServer(user))

	return srv
}
           

注入 wire set中

1. 编写 ProviderSet

// interfaces.go
package interfaces

import "github.com/google/wire"

// ProviderSet is interfaces providers.
var ProviderSet = wire.NewSet(NewUserUseCase)
           

2. 增加到 wire.go中

// initApp init kratos application.
func initApp(*conf.Server, *conf.Data, log.Logger) (*kratos.App, func(), error) {
	panic(wire.Build(
		server.ProviderSet,
		data.ProviderSet,
		biz.ProviderSet,
		service.ProviderSet,
		interfaces.ProviderSet, // 新增的 interfaces provider set
		newApp))
}
           

3. 执行 wire 命令,生成新的 wire_gen.go 文件

# cd 到 mian.go 所在的目录中
cd  cmd/XXXX  

# 执行 wire
wire
           

接下来自己启动项目,测试接口 : http://127.0.0.1:8000/api/user/sayhi 即可

亲测可以~