「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。
B站视频讲解地址
Github源码
2. 用户模块
2.1 数据库配置
- user/conf/conf.ini
文件配置,配置mysql,service服务等等...
[service]
AppMode = debug
HttpPort = :3000
[mysql]
Db = mysql
DbHost = 127.0.0.1
DbPort = 3306
DbUser = root
DbPassWord = root
DbName = todo_list
- user/model/
加载配置
func Init() {
file, err := ini.Load("./conf/config.ini")
if err != nil {
fmt.Println("配置文件读取错误,请检查文件路径:", err)
}
LoadMysqlData(file)
path := strings.Join([]string{DbUser, ":", DbPassWord, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8&parseTime=true"}, "")
model.Database(path)
}
- user/model/user.go
定义数据库模型
type User struct {
gorm.Model
UserName string `gorm:"unique"`
PasswordDigest string
}
- user/model/migration.go
数据库模型迁移
func migration() {
//自动迁移模式
DB.Set("gorm:table_options", "charset=utf8mb4").
AutoMigrate(&User{})
}
2.2 proto文件编写
- user/services/protos/userModels.proto
定义user的proto模型,注意这里一定要大写!!不然后面网关是绑定不到的!
syntax="proto3";
package services;
option go_package ="./;protos";
message UserModel{
// @inject_tag: json:"id"
uint32 ID=1;
// @inject_tag: json:"user_name"
string UserName=2;
// @inject_tag: json:"avatar"
string Avatar=3;
// @inject_tag: json:"email"
string Email=4;
// @inject_tag: json:"nickname"
string NickName=5;
// @inject_tag: json:"status"
string Status=6;
// @inject_tag: json:"limit"
uint32 Limit=7;
// @inject_tag: json:"created_at"
int64 CreatedAt=8;
// @inject_tag: json:"updated_at"
int64 UpdatedAt=9;
// @inject_tag: json:"deleted_at"
int64 DeletedAt=10;
}
在proto目录下执行
protoc --proto_path=. --micro_out=. --go_out=. userModel.proto
- user/services/protos/userService.proto
这里定义了用户请求的参数UserRequest和UserResponse的信息
syntax="proto3";
package services;
import "userModels.proto";
option go_package ="./;protos";
message UserRequest{
// @inject_tag: json:"user_name" form:"user_name" uri:"user_name"
string UserName=1;
// @inject_tag: json:"password" form:"password" uri:"password"
string Password=2;
// @inject_tag: json:"password_confirm" form:"password_confirm" uri:"password_confirm"
string PasswordConfirm=3;
}
message UserDetailResponse{
UserModel UserDetail=1;
uint32 Code=2;
}
service UserService{
rpc UserLogin(UserRequest) returns(UserDetailResponse);
rpc UserRegister(UserRequest) returns(UserDetailResponse);
}
在proto目录下执行
protoc --proto_path=. --micro_out=. --go_out=. userService.proto
生成这些四个文件即可,然后可以移动到services文件中。
2.3 实现用户模块业务逻辑
定义用户服务的结构体
//UserService 用户服务
type UserService struct {
}
2.3.1 用户注册方法
这里传入的参数是上下文信息,还有services层的 UserRequest 和 UserDetailResponse
// UserRegister 用户注册
func (*UserService) UserRegister(ctx context.Context, req *services.UserRequest, res *services.UserDetailResponse) error {
if req.Password != req.PasswordConfirm {
err := errors.New("两次密码输入不一致")
return err
}
count := 0
if err := model.DB.Model(&model.User{}).Where("user_name=?", req.UserName).Count(&count).Error; err != nil {
return err
}
if count > 0 {
err := errors.New("用户名已存在")
return err
}
user := model.User{
UserName: req.UserName,
}
// 加密密码
if err := user.SetPassword(req.Password); err != nil {
return err
}
// 创建用户
if err := model.DB.Create(&user).Error; err != nil {
return err
}
res.UserDetail = BuildUser(user)
return nil
}
2.3.2 登录服务方法
一样的逻辑方法,这里实现了UserLogin方法,同样地传入上下文,请求参数,响应参数
//UserLogin 实现用户服务接口 用户登录
func (*UserService) UserLogin(ctx context.Context, req *services.UserRequest, res *services.UserDetailResponse) error {
var user model.User
res.Code = 200
if err := model.DB.Where("user_name = ?", req.UserName).First(&user).Error; err != nil {
//如果查询不到,返回相应错误
if gorm.IsRecordNotFoundError(err) {
res.Code = 10003
return nil
}
res.Code = 30001
return nil
}
if user.CheckPassword(req.Password) == false {
res.Code = 10004
return nil
}
res.UserDetail = BuildUser(user)
return nil
}
2.4 接入etcd服务发现
- 注册etcd
etcdReg := etcd.NewRegistry(
registry.Addrs("127.0.0.1:2379"),
)
- 得到微服务实例
// 1. 得到微服务实例
microService := micro.NewService(
micro.Name("rpcUserService"), // 设置微服务名字,用来访问的
micro.Address("127.0.0.1:8082"),
micro.Registry(etcdReg),
)
- 初始化
microService.Init()
- 服务注册 将用户服务注册到etcd中
_ = services.RegisterUserServiceHandler(microService.Server(), new(core.UserService))
- 启动微服务
_ = microService.Run()
查看etcd中http://localhost:8080/etcdkeeper/是否有该模块的注册信息
至此,用户端的微服务已经完成了,我们接入网关,调用服务。