Создание пользовательского шлюза API
cd
прибытьFoodGuides
Под содержанием. Создайтеapi
папка
mkdir -p usermanage/api && cd usermanage/api
Создайтеuser.api
документ
goctl api -o user.api
определениеapi
Служить
info(
title: // UserApi
desc: // 用户服务相关API
)
type LoginRequest struct {
Email string `json:"email"`
Password string `json:"password"`
}
type LoginResponse struct {
UserReply
}
type RegisterRequest struct {
Username string `json:"username"`
Email string `json:"email"`
Password string `json:"password"`
}
type RegisterResponse struct {
UserReply
}
type UserinfoRequest struct {
Userid string `json:"userid"`
Token string `json:"token"`
}
type UserinfoResponse struct {
UserReply
}
type UserReply {
Id int64 `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
JwtToken
}
type JwtToken {
AccessToken string `json:"accessToken,omitempty"`
AccessExpire int64 `json:"accessExpire,omitempty"`
RefreshAfter int64 `json:"refreshAfter,omitempty"`
}
service user-api {
@handler Login // 用户登录
post /users/login(LoginRequest) returns(LoginResponse)
@handler Register // 用户注册
post /users/register(RegisterRequest) returns(RegisterResponse)
@handler UserInfo // 用户信息
post /users/userinfo(UserinfoRequest) returns(UserinfoResponse)
}
Мы определяем триuser-api
:Login
Register
UserInfo
генерироватьuser-api
Служить
goctl api go -api user.api -dir .
Проверьте этоapi
содержание
➜ api git:(master) ✗ tree
.
├── etc
│ └── user-api.yaml
├── internal
│ ├── config
│ │ └── config.go
│ ├── handler
│ │ ├── loginhandler.go
│ │ ├── registerhandler.go
│ │ ├── routes.go
│ │ └── userinfohandler.go
│ ├── logic
│ │ ├── loginlogic.go
│ │ ├── registerlogic.go
│ │ └── userinfologic.go
│ ├── svc
│ │ └── servicecontext.go
│ └── types
│ └── types.go
├── user.api
└── user.go
Запускаем службу, обратите внимание, что при запуске службы нужно убедиться, что та, что использовалась в предыдущей статьеningxi-compose
беги нормально.
go run user.go -f etc/user-api.yaml
Понять, как работает сервис
goctl
Инструменты могут легко и быстро помочь нам создатьapi
Служить. Но если вы не можете понятьapi
Как работает сервис, глядя на структуру проекта будет очень запутанно.
-
api/etc
внизuser-api.yaml
документ. Этот файл настраиваетapi
Некоторые переменные, требуемые службой, например имя службы.Name
,адрес интерфейсаHost
,Номер портаPort
и другая информация,MySQL
,Redis
,rpc
Другие конфигурации также написаны здесь. -
api
внизuser.api
документ. Этот файл определяетapi
Информация об интерфейсе, предоставляемая службой, и последующие добавления интерфейса также обрабатываются здесь. тогда позвониgoctl
Восстановите службу. -
api
внизuser.go
документ. Файлapi
Входной файл для службы, здесь все начинается.
внутренняя папка
api
Внутренний код реализации сервиса находится в этой папке.
internal/config
внизconfig.go
документ. Вы обнаружите, что файл определяет иuser-api.yaml
определение аналогичное. да.user-api.yaml
существуетuser.go
Входной файл находится вmain
метод, он анализируется какconfig
объект. Так что их значения взаимно однозначно соответствуют.
internal/handler
внизrouters.go
документ. Файлapi
Файл маршрутизации службы определяет метод запроса каждого интерфейса, путь к интерфейсу и метод, запускаемый интерфейсом. Например: клиент начинается сpost
запрошенный способhttp://localhost:8888/users/register,ноapi
служба сработаетRegisterHandler()
метод.
func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext) {
engine.AddRoutes(
[]rest.Route{
{
Method: http.MethodPost,
Path: "/users/login",
Handler: LoginHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/users/register",
Handler: RegisterHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/users/userinfo",
Handler: UserInfoHandler(serverCtx),
},
},
)
}
internal/handler
внизxxxhandler.go
документ. В этом файле записывается конкретная реализация каждого метода триггера интерфейса.
func RegisterHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.RegisterRequest
if err := httpx.Parse(r, &req); err != nil {
httpx.Error(w, err)
return
}
l := logic.NewRegisterLogic(r.Context(), ctx)
resp, err := l.Register(req)
if err != nil {
httpx.Error(w, err)
} else {
httpx.OkJson(w, resp)
}
}
}
можно увидетьRegisterHandler
Сначала анализируются полученные параметры. а потом позвонилlogic.NewRegisterLogic()
, его можно найтиRegisterHandler
Это не окончательная реализация, окончательная обработка бизнеса фактически находится в стадии разработки.logic
под каждой папкойlogic.go
в файле.
internal/logic
внизxxxlogic.go
документ. мы в конце концовlogic
в методе реализации вызвать соответствующийrpc
Служить.
internal/svc
внизservicecontext.go
документ. Файл сохраненapi
Услугиconfig
объект и создать экземпляр каждогоrpc
Объект услуги. потомsvc
объект будет изhandle
перейти кlogic
метод. В конце концовlogic
вызовrpc
также через сервисsvc
объект для достижения.
func (l *LoginLogic) Login(req types.LoginRequest) (*types.LoginResponse, error) {
resp,err := l.svcCtx.User.Login(l.ctx, &user.LoginRequest{ // 通过svcCtx 来调用了user rpc服务
Email: req.Email,
Password: req.Password,
});
}
internal/types
внизtypes.go
документ. Этот файл определяет нашуuser.api
Каждая структура объявлена в файле шаблона.
Подведение итогов процесса вызова
позвонить как клиентlogin
Возьмем для примера интерфейс.
user.go
входной файл черезyaml
конфигурационный файл, экземплярconfig
объект.
var configFile = flag.String("f", "etc/user-api.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
}
создавать экземплярServiceContext
объект
ctx := svc.NewServiceContext(c)
ctx
хранится внутриconfig
объект. и инициализированuser rpx
Служить. тогдаctx
позвониrpc
умение служить.
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
User: userclient.NewUser(zrpc.MustNewClient(c.User)),
}
}
создавать экземплярServer
объект.
server := rest.MustNewServer(c.RestConf)
Реализация маршрутизации, примечаниеctx
передаетсяhandlers
Наизнанку.
handler.RegisterHandlers(server, ctx)
api
служба работает
server.Start()
когда клиент звонитlogin
интерфейс. вызыватьLoginHandler
метод
func LoginHandler(ctx *svc.ServiceContext) http.HandlerFunc {
l := logic.NewLoginLogic(r.Context(), ctx)
resp, err := l.Login(req)
}
потомLoginHandler
перечислитьLoginLogic
метод
func (l *LoginLogic) Login(req types.LoginRequest) (*types.LoginResponse, error) {
resp,err := l.svcCtx.User.Login(l.ctx, &user.LoginRequest{
Email: req.Email,
Password: req.Password,
});
}
существуетLogin
внутри. мы проходим l.svcCtx.
называетсяUser rpc
в сервисеLogin
метод.
После обработки данных интерфейс отвечает слой за слоем и, наконец, завершает вызов клиентского интерфейса.
В процессе осмысленияrpc
вызов. Это содержимое, которое еще не появилось в приведенном выше примере.Прочитав последующий текст, вы сможете лучше понять процесс вызова.
Последняя статья "Учебник по переходу на ноль - сервисное подразделение и создание проекта"