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 框架的话,需要自己做如下事情:
- 规范项目分层,在
目录下,新增一个用户接口层/internal
(DDD思想)/interfaces
- 通过gin编写自己的请求处理、响应
- 通过gin定义路由
- kratos 集成 gin
- 注入 wire set 中
规范项目分层
PS :kratos 的 biz 层更多是DDD 中 domain + repo接口定义 ,但是官方该层给的后缀却是 XXUseCase,个人感觉不太对啊, 还是自己的知识错了?
在
/internal
目录下新建
/interfaces
目录
之后的处理请求、编写路由、wire Provider 都在该目录下定义,最终结果如图:
处理请求处理、响应
在用户接口层
/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 即可
亲测可以~