kratos如何在自建的模板上快速构建一个用户微服务 22 days ago
kratos如何在自建的模板上快速构建一个用户微服务
1. 定义proto文件
syntax = "proto3";
package api.v1;
import "google/protobuf/any.proto";
import "google/api/annotations.proto";
import "google/protobuf/struct.proto";
option go_package = "kratos_blog/api/v1;v1";
option java_multiple_files = true;
option java_package = "api.v1";
service User {
rpc CreateUser (SignupRequest) returns (ResponseMessage){
option (google.api.http) = {
post: "/api/v1/user/create"
body: "*"
};
};
rpc Login(LoginRequest) returns (ResponseMessage){
option (google.api.http) = {
post: "/api/v1/user/login"
body: "*"
};
};
}
message LoginRequest {
string username = 1;
string password = 2;
}
message SignupRequest {
string username = 1;
string password = 2;
string re_password = 3;
string email = 4;
string nickname = 5;
}
message ResponseMessage {
int32 code = 1; // 状态码
string message = 2; // 状态信息
// google.protobuf.Any data = 3; // 响应数据,可以是任意类型
oneof dt { //one of data
google.protobuf.Any any_data = 3; // 保留原始 Any 功能
google.protobuf.Value data = 4; // 使用更灵活的 JSON 结构
}
}
2. ent定义user schema并生成CURD代码
user.go
package schema
import (
"entgo.io/ent"
"entgo.io/ent/schema/field"
)
// User holds the schema definition for the User entity.
type User struct {
ent.Schema
}
// Fields of the User.
func (User) Fields() []ent.Field {
return []ent.Field{
field.String("username").Unique(),
field.String("password"),
field.String("email"),
field.String("nickname"),
field.Int64("create_time"),
field.Bool("is_deleted"),
field.Bool("allowed_login"),
}
}
// Edges of the User.
func (User) Edges() []ent.Edge {
return nil
}
3. biz
package biz
import (
"context"
"kratos_blog/ent"
"github.com/go-kratos/kratos/v2/log"
)
//request
// 实体类
type User struct {
//table各字段
Username string `json:"username"`
Password string `json:"password"`
RePassword string `json:"re_password"`
Email string `json:"email"`
Nickname string `json:"nickname"`
CreateTime int64 `json:"create_time"`
IsDeleted bool `json:"is_deleted"`
AllowedLogin bool `json:"allowed_login"`
}
type LoginForm struct{
Username string `json:"username"`
Password string `json:"password"`
}
//repo抽象类接口
type UserRepo interface {
Create(context.Context, *User) (*ent.User, error)
Login(context.Context,*LoginForm)(bool,int,error)
}
// UserUsecase is a User usecase.
type UserUsecase struct {
repo UserRepo
log *log.Helper
}
// NewUserUsecase new a User usecase.
func NewUserUsecase(repo UserRepo, logger log.Logger) *UserUsecase {
return &UserUsecase{repo: repo, log: log.NewHelper(logger)}
}
func (u *UserUsecase) CreateUser(ctx context.Context, user *User) (*ent.User, error) {
u.log.Info("creating user...")
return u.repo.Create(ctx,user)
}
func (u *UserUsecase) VerifyLoginPassword(ctx context.Context, form *LoginForm) (bool, int, error) {
u.log.Info("login...")
return u.repo.Login(ctx,form)
}
4. data
package data
import (
"context"
"time"
"kratos_blog/ent"
"kratos_blog/ent/user"
"kratos_blog/internal/biz"
"github.com/go-kratos/kratos/v2/log"
)
type userRepo struct {
data *Data
log *log.Helper
}
// NewUserRepo
func NewUserRepo(data *Data, logger log.Logger) biz.UserRepo {
return &userRepo{
data: data,
log: log.NewHelper(logger),
}
}
func (u *userRepo) Create(ctx context.Context, user *biz.User) (*ent.User, error) {
_user,err:=u.data.client.User.Create().SetUsername(user.Username).
SetPassword(user.Password).
SetEmail(user.Email).
SetNickname(user.Nickname).
SetCreateTime(time.Now().Unix()).
SetIsDeleted(false).
SetAllowedLogin(false).Save(ctx)
if err!=nil{
return nil, err
}
return _user, nil
}
func (u *userRepo) Login(ctx context.Context, form *biz.LoginForm) (bool, int, error) {
//query user
_u, err:=u.data.client.User.Query().Where(user.UsernameEQ(form.Username)).Only(ctx)
if err!=nil{
return false,0,err
}
if _u.Password == form.Password {
return true, _u.ID,nil
}
return false,0,nil
}
5. service
package service
import (
"context"
"os"
"time"
pb "kratos_blog/api/v1"
"kratos_blog/internal/biz"
"kratos_blog/internal/conf"
"kratos_blog/pkg/jwt"
"github.com/go-kratos/kratos/v2/log"
"google.golang.org/protobuf/types/known/structpb"
)
type UserService struct {
pb.UnimplementedUserServer
uc *biz.UserUsecase
jwt *conf.Jwt // 添加JWT配置字段
}
func NewUserService(uc *biz.UserUsecase, jwt *conf.Jwt) *UserService {
return &UserService{
uc: uc,
jwt: jwt,
}
}
func (s *UserService) CreateUser(ctx context.Context, req *pb.SignupRequest) (*pb.ResponseMessage, error) {
logger := log.NewStdLogger(os.Stdout)
helper := log.NewHelper(logger)
helper.Infof("received request to create user %v",req)
u, err:=s.uc.CreateUser(ctx,&biz.User{
Username: req.Username,
Password :req.Password,
Email :req.Email,
Nickname :req.Nickname,
})
if err!=nil{
helper.Errorf("creating user error: %v",err)
return &pb.ResponseMessage{
Code: 2001,
Message: "创建用户失败",
}, nil
}
// 使用 Value 而不是 Any
data, _ := structpb.NewValue(map[string]interface{}{
"id": u.ID,
"username": u.Username,
})
return &pb.ResponseMessage{
Code: 200,
Message: "创建用户成功",
Dt: &pb.ResponseMessage_Data{
Data: data,
},
}, nil
}
func (s *UserService) Login(ctx context.Context,req *pb.LoginRequest) (*pb.ResponseMessage, error) {
flag,uid,err:=s.uc.VerifyLoginPassword(ctx,&biz.LoginForm{
Username: req.Username,
Password: req.Password,
})
if !flag || err!=nil{
return &pb.ResponseMessage{
Code: 2001,
Message: "登录失败",
},nil
}
expiresDuration:= time.Duration(s.jwt.Expires)* time.Second
// 生成JWT
token, err := jwt.GenerateToken(s.jwt.Secret, expiresDuration, int64(uid))
if err != nil {
return &pb.ResponseMessage{
Code: 2001,
Message: "生成token失败",
},nil
}
data, _ := structpb.NewValue(map[string]interface{}{
"token": token,
})
return &pb.ResponseMessage{
Code: 200,
Message: "登录成功",
Dt: &pb.ResponseMessage_Data{
Data: data,
},
}, nil
}
- 上一篇: macos搭建kong
- 下一篇: 如何删除tag