gozero,是一个常见的微服务框架,这里分享一下整合mysql,redis,jwt的相关的代码
1.配置配置文件
Name: shop-api
Host: 0.0.0.0
Port: 8888
MySql:
DataSource: root:123456@tcp(127.0.0.1:3306)/gozero?charset=utf8mb4&parseTime=true&loc=Local
Auth:
JwtSecret: "this is jwt secret"
Expire: 36000
RedisConfig:
Host: 127.0.0.1:6379
Type: node
Pass: "123456"
2.编写一个api文件
syntax = "v1"
// 类型定义块 - 定义焦点图相关数据结构
type CommonResponse {
Message string `json:"message"`
code int `json:"code"`
success bool `json:"success"`
Data interface{} `json:"data,omitempty"`
}
type (
UserRequest {
Id int `form:"id"`
}
AddUserRequest {
Id int `form:"id"`
Username string `form "username"`
Age int `form:"age"`
Email string `form:"email"`
}
UpdateUserRequest {
Id int `form:"id"`
Username string `form "username"`
Age int `form:"age"`
Email string `form:"email"`
}
)
type (
OneArticleReq {
Id int64 `form:"id"` // Get传值只保留form tag
}
OneArticleResp {
Result Article `json:"result"`
}
// 分类详情请求
OneCateReq {
Id int64 `path:"id"` // 使用path参数获取分类ID
}
ArticleResp {
Result []*Article `json:"result"`
}
Article {
Id int64 `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Status int `json:"content"`
}
// 文章分类结构体 - 包含关联的文章列表
ArticleCate {
Id int `json:"id"`
Title string `json:"title"`
State int `json:"state"`
Articles []Article `json:"articles,omitempty"` // 关联的文章列表(可选)
}
)
type (
//Request
FocusRequest {
Id int `form:"id"` //Get Delete传值
}
// FocusResp 焦点图列表响应结构
FocusResp {
// Result 焦点图列表
Result []*Focus `json:"result"`
}
FocusOneceResp {
// Result 焦点图列表
Result *Focus `json:"result"`
}
AddFocusRequest {
//title
Title string `form:"title"`
// position 焦点图位置
Position int `form:"position"`
// url 焦点图名称
Url string `form:"url"`
// Pic 焦点图图片地址
Pic string `form:"pic"`
}
UpdateFocusRequest {
//id
Id int `form:"id"`
//title
Title string `form:"title"`
// position 焦点图位置
Position int `form:"position"`
// url 焦点图名称
Url string `form:"url"`
// Pic 焦点图图片地址
Pic string `form:"pic"`
}
// Focus 焦点图数据结构
Focus {
// Id 焦点图ID
Id int64 `json:"id"`
// Name 焦点图名称
Title string `json:"title"`
// Pic 焦点图图片地址
Pic string `json:"pic"`
// Url 焦点图跳转链接
Url string `json:"url"`
// Position 焦点图显示位置
Position int `json:"position"`
}
)
@server (
group: user
prefix: /api/user
)
service shop-api {
@handler getUser
get / returns (CommonResponse)
@handler getUserById
get /oneUser (UserRequest) returns (CommonResponse)
@doc "增加用户"
@handler AddUser
post /addUser (AddUserRequest) returns (CommonResponse)
@doc "更新用户"
@handler UpdateUser
post /updateUser (UpdateUserRequest) returns (CommonResponse)
@doc "删除用户"
@handler DeleteUser
post /deleteUser (UserRequest) returns (CommonResponse)
}
@server (
// group: 指定路由分组,生成的代码会被放到 focus 目录下
group: focus
// prefix: 路由前缀,所有该服务下的路由都会以 /api/focus 开头
prefix: /api/focus
)
// 服务定义 - 商城API服务
service shop-api {
// @handler 指定处理器名称,对应生成的 Go 代码中的方法名
// get /list 定义 GET 请求路由,路径为 /api/focus/list
// returns 定义返回类型为 FocusResp
@handler GetFocusList
get /list returns (CommonResponse)
@handler GetOneFocus
get /details (FocusRequest) returns (CommonResponse)
}
@server (
group: article // 代表当前 service 代码块下的路由生成代码时都会被放到 article 目录下
prefix: /api/article
)
service shop-api {
@handler GetOneArticle
get /details (OneArticleReq) returns (CommonResponse)
@handler GetArticleList
get /list returns (CommonResponse)
@handler GetArticleLByWhere
get /where returns (CommonResponse)
@handler GetArticleLBySql
get /sql returns (CommonResponse)
}
@server (
group: cate // 分类相关的路由
prefix: /api/cate
)
service shop-api {
// 分类详情
@handler GetOneCate
get /details/:id (OneCateReq) returns (CommonResponse)
// 分类列表
@handler GetCateList
get /list returns (CommonResponse)
// 分类详情(包含关联的文章列表)
@handler GetCateWithArticles
get /:id/with-articles (OneCateReq) returns (CommonResponse)
}
type (
LoginReq {
Username string `json:"username"`
Password string `json:"password"`
}
LoginResp {
Token string `json:"token"`
}
)
@server (
group: account
//路由前缀
prefix: "/api"
)
//影响配置文件名称和主文件名称
service shop-api {
@handler login
post /user/login (LoginReq) returns (CommonResponse)
}
type (
Address {
Id int64 `json:"id"`
Address string `json:"address"`
phone string `json:"phone"`
name string `json:"name"`
}
)
@server (
group: address
//路由前缀
prefix: "/api"
)
//影响配置文件名称和主文件名称
service shop-api {
//handler中的函数名称
@handler address
get /address/list returns (CommonResponse)
}
3.使用go-ctl创建gozero工程。
goctl api go --api shop.api --dir .
4.安装redis和gorm的依赖。
go get github.com/redis/go-redis/v9
5.在config配置文件,映射相关配置。
// Code scaffolded by goctl. Safe to edit.
// goctl 1.10.2
package config
import (
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/rest"
)
type Config struct {
rest.RestConf
MySql struct {
DataSource string
}
RedisConfig redis.RedisConf
Auth struct {
JwtSecret string
Expire int64
}
}
6.创建一个redis连接
package cache
import "github.com/zeromicro/go-zero/core/stores/redis"
func NewRedis(con redis.RedisConf) *redis.Redis {
return redis.MustNewRedis(con)
}
7.在serviceContext文件设置相关连接对象
// Code scaffolded by goctl. Safe to edit.
// goctl 1.10.2
package svc
import (
"zsshop/internal/cache"
"zsshop/internal/config"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/redis"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type ServiceContext struct {
Config config.Config
DB *gorm.DB
Redis *redis.Redis
}
func NewServiceContext(c config.Config) *ServiceContext {
//初始化数据库连接
dbClient, err := gorm.Open(mysql.Open(c.MySql.DataSource), &gorm.Config{})
redisConn := cache.NewRedis(c.RedisConfig)
if err != nil {
logx.Error(err)
return nil
}
return &ServiceContext{
DB: dbClient,
Config: c,
Redis: redisConn,
}
}
8.编写一个jwt工具类
package biz
import "github.com/golang-jwt/jwt/v4"
// @secretKey: JWT 加解密密钥
// @iat: 时间戳
// @seconds: 过期时间,单位秒
// @payload: 数据载体
func GetJwtToken(secretKey string, iat, seconds int64, payload string) (string,
error) {
claims := make(jwt.MapClaims)
claims["exp"] = iat + seconds
claims["iat"] = iat
claims["payload"] = payload
token := jwt.New(jwt.SigningMethodHS256)
token.Claims = claims
return token.SignedString([]byte(secretKey))
}
9.模拟一个登录接口,生成token存入redis中
// Code scaffolded by goctl. Safe to edit.
// goctl 1.10.2
package account
import (
"context"
"fmt"
"time"
"zsshop/internal/biz"
"zsshop/internal/svc"
"zsshop/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type LoginLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginLogic {
return &LoginLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *LoginLogic) Login(req *types.LoginReq) (resp *types.CommonResponse, err error) {
// todo: add your logic here and delete this line
//生成token
token, err := biz.GetJwtToken(l.svcCtx.Config.Auth.JwtSecret,
time.Now().Unix(), l.svcCtx.Config.Auth.Expire, req.Username)
fmt.Println(token)
logx.Info(token)
if err != nil {
return biz.Error(biz.ServerError), nil
}
l.svcCtx.Redis.Set(req.Username, token)
return biz.Success(types.LoginResp{
Token: token,
}), nil
}