User service
User service, providing login, registration, password modification and other functions.
New service
micro new shopping/user
Finishing structure
Add the model directory and repository directory, delete the default example folder in proto, and create the user folder.
Development steps: 1. Define interface - > 2. Generate interface code - > 3. Write model layer code - > 4. Write repository data operation code - > 5. Implement interface - > 6. Modify main.go
Because this is the first microservice, the process of creating a microservice will be described in as much detail as possible
Define user service interface
syntax = "proto3"; package go.micro.srv.user; service UserService { rpc Register (RegisterRequest) returns (Response){} rpc Login (LoginRequest) returns (Response){} rpc UpdatePassword (UpdatePasswordRequest) returns (Response){} } message User { uint32 id = 1; string name = 2; string phone = 3; string password = 4; } message RegisterRequest{ User user = 1; } message LoginRequest{ string phone = 1; string password = 2; } message UpdatePasswordRequest{ uint32 uid = 1; string oldPassword = 2; string newPassword = 3; string confirmPassword = 4; } message Response { string code = 1; string msg = 2; }
Generate interface code
Execute the command protoc -- proto_path =. - micro_out =. - go_out =. Proto / user / user.proto
Write model.user
package model import "github.com/jinzhu/gorm" type User struct { gorm.Model Name string Phone string `gorm:"type:char(11);` Password string }
Write repository.user
package repository import ( "github.com/jinzhu/gorm" "shopping/user/model" ) type Repository interface { Find(id int32) (*model.User, error) Create(*model.User) error Update(*model.User, int64) (*model.User, error) FindByField(string, string, string) (*model.User, error) } type User struct { Db *gorm.DB } func (repo *User) Find(id uint32) (*model.User, error) { user := &model.User{} user.ID = uint(id) if err := repo.Db.First(user).Error; err != nil { return nil, err } return user, nil } func (repo *User) Create(user *model.User) error { if err := repo.Db.Create(user).Error; err != nil { return err } return nil } func (repo *User) Update(user *model.User) (*model.User, error) { if err := repo.Db.Model(user).Updates(&user).Error; err != nil { return nil, err } return user, nil } func (repo *User) FindByField(key string, value string, fields string) (*model.User, error) { if len(fields) == 0 { fields = "*" } user := &model.User{} if err := repo.Db.Select(fields).Where(key+" = ?", value).First(user).Error; err != nil { return nil, err } return user, nil }
Implement interface handler.user
package handler import ( "context" "github.com/micro/go-log" "github.com/micro/go-micro/errors" "golang.org/x/crypto/bcrypt" "shopping/user/model" "shopping/user/repository" user "shopping/user/proto/user" ) type User struct{ Repo *repository.User } // Call is a single request handler called via client.Call or the generated client code func (e *User) Register(ctx context.Context, req *user.RegisterRequest, rsp *user.Response) error { hashedPwd, err := bcrypt.GenerateFromPassword([]byte(req.User.Password), bcrypt.DefaultCost) if err != nil { return err } user := &model.User{ Name:req.User.Name, Phone:req.User.Phone, Password:string(hashedPwd), } if err := e.Repo.Create(user);err != nil{ log.Log("create error") return err } rsp.Code = "200" rsp.Msg = "login was successful" return nil } func (e *User)Login(ctx context.Context, req *user.LoginRequest, rsp *user.Response) error { user , err := e.Repo.FindByField("phone" , req.Phone , "id , password") if err != err{ return err } if user == nil{ return errors.Unauthorized("go.micro.srv.user.login", "The mobile number does not exist") } if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)); err != nil { return errors.Unauthorized("go.micro.srv.user.login", "Password error") } rsp.Code = "200" rsp.Msg = "Login successfully" return nil } func (e *User)UpdatePassword(ctx context.Context, req *user.UpdatePasswordRequest, rsp *user.Response) error { user,err := e.Repo.Find(req.Uid) if user == nil{ return errors.Unauthorized("go.micro.srv.user.login", "The user does not exist") } if err != nil { return err } //Verify whether the old password is normal if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.OldPassword)); err != nil { return errors.Unauthorized("go.micro.srv.user.login", "Old password authentication failed") } //After verification, save the new password hash hashedPwd, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost) if err != nil { return err } user.Password = string(hashedPwd) e.Repo.Update(user) rsp.Code = "200" rsp.Msg =user.Name+",Your password has been updated successfully" return nil }
Modify main.go
Because you need to establish a database connection in main.go, create database.go in the root directory
package main import ( "fmt" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) func CreateConnection() (*gorm.DB, error) { host := "192.168.0.111" user := "mytestroot" dbName := "shopping" password := "mytestroot" return gorm.Open("mysql", fmt.Sprintf( "%s:%s@tcp(%s:3306)/%s?charset=utf8&parseTime=True&loc=Local", user, password, host, dbName, ), ) }
Then modify main.go
package main import ( "github.com/micro/go-log" "github.com/micro/go-micro" "github.com/micro/go-grpc" "shopping/user/handler" "shopping/user/model" "shopping/user/repository" user "shopping/user/proto/user" ) func main() { db,err := CreateConnection() defer db.Close() db.AutoMigrate(&model.User{}) if err != nil { log.Fatalf("connection error : %v \n" , err) } repo := &repository.User{db} // New Service service := grpc.NewService( micro.Name("go.micro.srv.user"), micro.Version("latest"), ) // Initialise service service.Init() // Register Handler user.RegisterUserServiceHandler(service.Server(), &handler.User{repo}) // Register Struct as Subscriber //micro.RegisterSubscriber("go.micro.srv.user", service.Server(), new(subscriber.Example)) // Register Function as Subscriber //micro.RegisterSubscriber("go.micro.srv.user", service.Server(), subscriber.Handler) // Run service if err := service.Run(); err != nil { log.Fatal(err) } }
Start service, verify interface
go run main.go database.go and micro api --namespace=go.micro.srv
Registration interface
Logon interface
Modify password interface