当前位置:网站首页>Kratos战神微服务框架(二)
Kratos战神微服务框架(二)
2022-07-06 08:59:00 【~庞贝】
Kratos战神微服务框架(二)
项目结构
api编写
protobuf编写
syntax = "proto3";
package realworld.v1;
import "google/api/annotations.proto";
option go_package = "realworld/api/realworld/v1;v1";
// The greeting service definition.
service RealWorld {
rpc Login(LoginRequest) returns (UserReply) {
option (google.api.http) = {
post: "/api/users/login",
body: "*", // 注意post请求一定交加body项
};
}
}
message LoginRequest{
message User {
string email = 1;
string password = 2;
}
User user = 1;
}
message UserReply {
message User {
string email = 1;
string token = 2;
string username = 3;
string bio = 4;
string image = 5;
}
User user = 1;
}
使用makefile
注:需要安装make指令
GOPATH:=$(shell go env GOPATH)
VERSION=$(shell git describe --tags --always)
INTERNAL_PROTO_FILES=$(shell find internal -name *.proto)
API_PROTO_FILES=$(shell find api -name *.proto)
.PHONY: init
# init env
init:
go install google.golang.org/protobuf/cmd/[email protected]
go install google.golang.org/grpc/cmd/[email protected]
go install github.com/go-kratos/kratos/cmd/kratos/[email protected]
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/[email protected]
go install github.com/google/gnostic/cmd/[email protected]
.PHONY: config
# generate internal proto
config:
protoc --proto_path=./internal \
--proto_path=./third_party \
--go_out=paths=source_relative:./internal \
./internal/conf/*.proto
# $(INTERNAL_PROTO_FILES)
.PHONY: api
# generate api proto
api:
protoc --proto_path=./api \
--proto_path=./third_party \
--go_out=paths=source_relative:./api \
--go-http_out=paths=source_relative:./api \
--go-grpc_out=paths=source_relative:./api \
--openapi_out=fq_schema_naming=true,default_response=false:. \
./api/realworld/v1/*.proto
# $(API_PROTO_FILES)
.PHONY: build
# build
build:
mkdir -p bin/ && go build -ldflags "-X main.Version=$(VERSION)" -o ./bin/ ./...
.PHONY: generate
# generate
generate:
go mod tidy
go get github.com/google/wire/cmd/[email protected]
go generate ./...
.PHONY: wire
# wire
wire:
cd cmd/realworld/ && wire
.PHONY: run
# run
run:
kratos run
.PHONY: all
# generate all
all:
make api;
make config;
make generate;
# show help
help:
@echo ''
@echo 'Usage:'
@echo ' make [target]'
@echo ''
@echo 'Targets:'
@awk '/^[a-zA-Z\-\_0-9]+:/ { \
helpMessage = match(lastLine, /^# (.*)/); \
if (helpMessage) { \
helpCommand = substr($$1, 0, index($$1, ":")-1); \
helpMessage = substr(lastLine, RSTART + 2, RLENGTH); \
printf "\033[36m%-22s\033[0m %s\n", helpCommand,helpMessage; \
} \
} \
{ lastLine = $$0 }' $(MAKEFILE_LIST)
.DEFAULT_GOAL := help
注:默认是linux命令,windwos需要修改路径
service层接口实现
进入internal/service目录
service.go
package service
import (
"github.com/go-kratos/kratos/v2/log"
"github.com/google/wire"
v1 "helloworld/api/realworld/v1"
"helloworld/internal/biz"
)
// ProviderSet is service providers.
var ProviderSet = wire.NewSet(NewRealWorldService) //依赖注入
type RealWorldService struct {
v1.UnimplementedRealWorldServer
pu *biz.SocialUsecase
uc *biz.UserUsecase
log *log.Helper
}
func NewRealWorldService(uc *biz.UserUsecase, logger log.Logger) *RealWorldService {
return &RealWorldService{
uc: uc, log: log.NewHelper(logger)}
}
//实现方法
func (s *RealWorldService) Login(ctx context.Context, req *v1.LoginRequest) (*v1.UserReply, error) {
return &v1.UserReply{
User: &v1.UserReply_User{
Username: "jtyyds",
},
}, nil
}
biz层
package biz
import "github.com/google/wire"
// ProviderSet is biz providers.
var ProviderSet = wire.NewSet(NewSocialUsecase, NewUserUsecase) //依赖注入
type User struct {
Email string
Username string
Bio string
Image string
PasswordHash string
}
type UserLogin struct {
Email string
Username string
Token string
Bio string
Image string
}
// bcrypt方法加密
func hashPassword(pwd string) string {
password, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)
if err != nil {
panic(err)
}
fmt.Printf("%v", password)
return string(password)
}
// 密码进行比较
func verifyPassword(hashed, input string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hashed), []byte(input))
if err != nil {
return false
}
return true
}
// 接口方法
type UserRepo interface {
CreateUser(ctx context.Context, user *User) error
GetUserByEmail(ctx context.Context, email string) (*User, error)
}
type ProfileRepo interface {
}
type UserUsecase struct {
ur UserRepo
pr ProfileRepo
jwtc *conf.JWT
log *log.Helper
}
func NewUserUsecase(ur UserRepo, pr ProfileRepo, jwtc *conf.JWT, logger log.Logger) *UserUsecase {
return &UserUsecase{
ur: ur, pr: pr, jwtc: jwtc, log: log.NewHelper(logger)}
}
func (uc *UserUsecase) generateToken(username string) string {
return auth.GenerateToken(uc.jwtc.Token, username)
}
// 注册的业务逻辑
func (uu *UserUsecase) Register(ctx context.Context, username, email, password string) (*UserLogin, error) {
u := &User{
Email: email,
Username: username,
PasswordHash: hashPassword(password),
}
if err := uu.ur.CreateUser(ctx, u); err != nil {
return nil, err
}
return &UserLogin{
Email: email,
Username: username,
Token: uu.generateToken(username),
}, nil
}
// 登录的业务逻辑实现
func (uu *UserUsecase) Login(ctx context.Context, email, password string) (*UserLogin, error) {
u, err := uu.ur.GetUserByEmail(ctx, email)
if err != nil {
return nil, err
}
b := verifyPassword(u.PasswordHash, password)
if b == true {
return nil, errors.New("Loin")
}
return &UserLogin{
Email: u.Email,
Username: u.Username,
Bio: u.Bio,
Image: u.Image,
Token: uu.generateToken(u.Username),
}, nil
}
data层
data.go
package data
import (
"fmt"
"github.com/go-kratos/kratos/v2/log"
"github.com/google/wire"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"helloworld/internal/conf"
)
// ProviderSet is data providers.
var ProviderSet = wire.NewSet(NewData, NewDB, NewUserRepo, NewProfileRepo) //依赖注入
// Data .
type Data struct {
// TODO wrapped database client
db *gorm.DB
}
// NewData .
func NewData(c *conf.Data, logger log.Logger, db *gorm.DB) (*Data, func(), error) {
cleanup := func() {
log.NewHelper(logger).Info("closing the data resources")
}
return &Data{
db: db}, cleanup, nil
}
// 连接mysql数据库
func NewDB(c *conf.Data) *gorm.DB {
fmt.Println(c.Database.Dsn)
db, err := gorm.Open(mysql.Open(c.Database.Dsn), &gorm.Config{
})
if err != nil {
panic("failed")
}
if err := db.AutoMigrate(); err != nil {
panic(err)
}
return db
}
package data
import (
"context"
"github.com/go-kratos/kratos/v2/log"
"helloworld/internal/biz"
)
type userRepo struct {
data *Data
log *log.Helper
}
func NewUserRepo(data *Data, logger log.Logger) biz.UserRepo {
return &userRepo{
data: data,
log: log.NewHelper(logger),
}
}
func (r *userRepo) CreateUser(ctx context.Context, g *biz.User) error {
// 可以实现操作数据库,这个并没有实现
return nil
}
func (r *userRepo) GetUserByEmail(ctx context.Context, email string) (*biz.User, error) {
// 可以实现操作数据库,这个并没有实现
return nil, nil
}
configs配置文件
server:
http:
addr: 0.0.0.0:8000
timeout: 1s
grpc:
addr: 0.0.0.0:9000
timeout: 1s
data:
database:
driver: mysql
dsn: "root:[email protected](127.0.0.1:3306)/realworld?charset=utf8mb4&parseTime=True&loc=Local"
jwt:
secret : "hello"
修改配置文件后,需要修改internal/conf下的conf.proto
syntax = "proto3";
package kratos.api;
option go_package = "helloworld/internal/conf;conf";
import "google/protobuf/duration.proto";
message Bootstrap {
Server server = 1;
Data data = 2;
JWT jwt = 3;
}
message Server {
message HTTP {
string network = 1;
string addr = 2;
google.protobuf.Duration timeout = 3;
}
message GRPC {
string network = 1;
string addr = 2;
google.protobuf.Duration timeout = 3;
}
HTTP http = 1;
GRPC grpc = 2;
}
message Data {
message Database {
string driver = 1;
string dsn = 2;
}
Database database = 1;
}
message JWT {
string token = 1;
}
使用make config生成conf.pb.go
注:是否需要修改config的makefile
边栏推荐
- LeetCode:836. 矩形重叠
- Connexion d'initialisation pour go redis
- AcWing 2456. 记事本
- CUDA implementation of self defined convolution attention operator
- IJCAI2022论文合集(持续更新中)
- MongoDB 的安装和基本操作
- Chapter 1 :Application of Artificial intelligence in Drug Design:Opportunity and Challenges
- Leetcode: Sword Finger offer 42. Somme maximale des sous - tableaux consécutifs
- LeetCode:673. 最长递增子序列的个数
- LeetCode:34. Find the first and last positions of elements in a sorted array
猜你喜欢
Mathematical modeling 2004b question (transmission problem)
BN folding and its quantification
I-BERT
Multivariate cluster analysis
[today in history] February 13: the father of transistors was born The 20th anniversary of net; Agile software development manifesto was born
Nacos installation and service registration
An article takes you to understand the working principle of selenium in detail
In depth analysis and encapsulation call of requests
MySQL uninstallation and installation methods
[MySQL] limit implements paging
随机推荐
Ijcai2022 collection of papers (continuously updated)
Mathematical modeling 2004b question (transmission problem)
在QWidget上实现窗口阻塞
What is an R-value reference and what is the difference between it and an l-value?
Li Kou daily question 1 (2)
CSP salary calculation
Selenium+pytest automated test framework practice
LeetCode:劍指 Offer 42. 連續子數組的最大和
Pytest之收集用例规则与运行指定用例
After reading the programmer's story, I can't help covering my chest...
注意力机制的一种卷积替代方式
SimCLR:NLP中的对比学习
LeetCode:39. Combined sum
Selenium+pytest automated test framework practice (Part 2)
Connexion d'initialisation pour go redis
CUDA realizes focal_ loss
BN折叠及其量化
ant-design的走马灯(Carousel)组件在TS(typescript)环境中调用prev以及next方法
Basic usage of xargs command
数学建模2004B题(输电问题)