我们通过一个系列文章跟大家详细展示一个 go-zero 微服务实例,整个系列分十三篇文章,目录结构如下:
- go-zero 实战 - 服务划分与项目创建
- go-zero 实战 - User API Gateway
- go-zero 实战 - User Login
- go-zero 实战 - User Register
- go-zero 实战 - User Userinfo
- go-zero 实战 - Food API Gateway
- go-zero 实战 - Food Search
- go-zero 实战 - Food AddFood
- go-zero 实战 - Food DeleteFood
- go-zero 实战 - Food Foodlist
- go-zero 实战进阶 - rpc 服务
- go-zero 实战进阶 - 用户管理 rpc 服务
- go-zero 实战进阶 - 食材管理 rpc 服务
期望通过本系列文章带你在本地利用 go-zero 快速开发一个《食谱指南》系统,让你快速上手微服务。
在上一篇 《go-zero 实战 - User Login》 文章中我们完成登录接口的搭建。有了前面文章的介绍,接下来我们会加快开发进度。本文将向我们介绍如何搭建用户注册接口。
修改 Response 返回格式
$ vim usermanage/api/internal/handler/registerhandler.go
package handler
import (
"FoodGuides/common/responsex"
"net/http"
"FoodGuides/service/usermanage/api/internal/logic"
"FoodGuides/service/usermanage/api/internal/svc"
"FoodGuides/service/usermanage/api/internal/types"
"github.com/zeromicro/go-zero/rest/httpx"
)
func RegisterHandler(svcCtx *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.OkJson(w, responsex.FailureResponse(nil, err.Error(), 1000))
return
}
l := logic.NewRegisterLogic(r.Context(), svcCtx)
resp, err := l.Register(&req)
if err != nil {
httpx.OkJson(w, responsex.FailureResponse(nil, err.Error(), 1000))
} else {
httpx.OkJson(w, responsex.SuccessResponse(resp, "注册成功"))
}
}
}
添加用户注册逻辑
用户注册流程:先判断注册邮箱是否已经被注册,邮箱未被注册,将用户信息写入数据库,用户密码需要进行加密存储。
$ vim usermanage/api/internal/logic/registerlogic.go
package logic
import (
"FoodGuides/common/cryptx"
"FoodGuides/common/jwtx"
"FoodGuides/service/usermanage/model"
"context"
"errors"
"time"
"FoodGuides/service/usermanage/api/internal/svc"
"FoodGuides/service/usermanage/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type RegisterLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewRegisterLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RegisterLogic {
return &RegisterLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *RegisterLogic) Register(req *types.RegisterRequest) (*types.RegisterResponse, error) {
// 判断邮箱是否已经被注册
_, err := l.svcCtx.UserModel.FindOneByEmail(l.ctx, req.Email)
if err == nil {
return nil, errors.New("该邮箱已注册")
}
if err != model.ErrNotFound {
return nil, err
}
user := model.User{
Name: req.Username,
Password: cryptx.PasswordEncrypt(l.svcCtx.Config.Salt, req.Password),
Email: req.Email,
}
// 插入一条新的用户数据
res, err := l.svcCtx.UserModel.Insert(l.ctx, &user)
if err != nil {
return nil, err
}
user.Id, err = res.LastInsertId()
if err != nil {
return nil, err
}
now := time.Now().Unix()
accessExpire := l.svcCtx.Config.Auth.AccessExpire
var jwtToken string
jwtToken, err = jwtx.GetJwtToken(
l.svcCtx.Config.Auth.AccessSecret,
now,
accessExpire,
user.Id,
)
if err != nil {
return nil, err
}
token := types.JwtToken{
AccessToken: jwtToken,
AccessExpire: now + accessExpire,
RefreshAfter: now + accessExpire/2,
}
response := types.UserReply{
Id: user.Id,
Username: user.Name,
Email: user.Email,
JwtToken: token,
}
return &types.RegisterResponse{UserReply: response}, nil
}
启动服务
启动 user api 服务, 运行成功后,user api 则运行在本机的 8888 端口
➜ FoodGuides:
$ go run usermanage/api/user.go -f usermanage/api/etc/user-api.yaml
Starting server at 0.0.0.0:8888...
我们用 Postman 尝试请求注册接口,有如下截图的响应说明服务运行正常。
查看本地数据库 user 表,发现已经成功插入了一条新的用户记录。
至此,我们就完成了注册服务的开发。我们将会在下一篇中介绍如何搭建一个更具挑战性的接口 - UserInfo。