前面《kratos微服务实战(六)kratos项目之接入gorm操作mysql》我们在kratos微服务项目中接入了gorm操作mysql,由于接口请求的token还不能自定义,所以这里的话我们再接入redis,实现登录成功生成一个token,并且把用户信息存储到redis中。操作步骤如下:
一、安装依赖
使用redis的话,我们需要引入redis的依赖
#安装redis依赖 go get github.com/redis/go-redis/v9 #安装uuid,md5依赖 go get crypto/md5 go get encoding/hex go get github.com/google/uuid
二、修改配置文件
这里由于我们的redis是需要密码的,因此这里我们需要修改redis的配置。
1、打开configs/config.yaml文件,修改redis的信息,并且添加password字段
2、这里我们添加的password字段是无法被识别的,所以需要修改读取该胚子文件的utils类,首先我们删除internal/conf/conf.pb.proto这个文件,因为我们要重新生成一个
3、修改internal/conf/conf.proto文件,在里面添加上password字段,并且把顺序调整下
4、接下来打开终端,重新生成pb文件
kratos proto client internal/conf/conf.proto
执行完成后,可以看到新的conf.pb.go文件生成了
三、初始化redis连接
上一篇我们初始化mysql连接实在internal/data/data.go文件中操作的,这里操作redis也是一样的。打开internal/data/data.go文件,首先在data的stuct中添加redis变量:
type Data struct { db *gorm.DB rdb *redis.Client }
然后改写NewData,把redis的变量进行赋值
func NewData(c *conf.Data, logger log.Logger, db *gorm.DB, rdb *redis.Client) (*Data, func(), error) { cleanup := func() { log.NewHelper(logger).Info("closing the data resources") } return &Data{ db: db, rdb: rdb, }, cleanup, nil }
然后创建一个redis初始化连接的方法,示例代码如下:
func NewRedisEngine(c *conf.Data) (rdb *redis.Client) { rdb = redis.NewClient(&redis.Options{ Addr: c.Redis.Addr, Password: c.Redis.Password, }) return }
最后记得把NewRedisEngine给注册下
var ProviderSet = wire.NewSet(NewData, NewGreeterRepo, NewDbEngine, NewAccountRepo, NewRedisEngine)
最后完整的data.go文件代码示例如下:
package data import ( "github.com/redis/go-redis/v9" "gorm.io/driver/mysql" "gorm.io/gorm" "user-center/internal/conf" "github.com/go-kratos/kratos/v2/log" "github.com/google/wire" ) // ProviderSet is data providers. 注册mysqlengine var ProviderSet = wire.NewSet(NewData, NewGreeterRepo, NewDbEngine, NewAccountRepo, NewRedisEngine) // Data .添加mysql操作的客户端 type Data struct { db *gorm.DB rdb *redis.Client } // NewData .实例化mysql连接 func NewData(c *conf.Data, logger log.Logger, db *gorm.DB, rdb *redis.Client) (*Data, func(), error) { cleanup := func() { log.NewHelper(logger).Info("closing the data resources") } return &Data{ db: db, rdb: rdb, }, cleanup, nil } /* * 注册mysql初始化 */ func NewDbEngine(c *conf.Data) (db *gorm.DB, err error) { db, err = gorm.Open(mysql.Open(c.Database.Source), &gorm.Config{}) return db, err } func NewRedisEngine(c *conf.Data) (rdb *redis.Client) { rdb = redis.NewClient(&redis.Options{ Addr: c.Redis.Addr, Password: c.Redis.Password, }) return }
四、定义repo操作redis的方法
这里回到internal/biz/account.go文件,在前面的repo interface中添加两个操作redis的方法,一个是设置值的方法,一个是获取值的方法,示例如下:
type AccountRepo interface { FindByUsernameAndPassword(ctx context.Context, loginReq *pb.LoginRequest) (acc *Account, err error) RedisSetAccount(ctx context.Context, key string, value interface{}, expiration time.Duration) (err error) RedisGetAccount(ctx context.Context, key string) (res string, err error) }
同时这里还需要编写访问dao层的方法,示例如下:
func (uc *AccountUseCase) RedisSetAccountInfo(ctx context.Context, key string, value interface{}, expiration time.Duration) (err error) { err = uc.acc.RedisSetAccount(ctx, key, value, expiration) if err != nil { return err } return nil } func (uc *AccountUseCase) RedisGetAccount(ctx context.Context, key string) (res string, err error) { res, err = uc.acc.RedisGetAccount(ctx, key) if err != nil { return "", err } return res, nil }
五、编写操作redis的实现方法
上面第4步定义了操作redis的方法,接下来去dao层编写实现方法。打开internal/data/account.go文件,来实现这两个方法
这两个方法主要是做redis的存取的,编写实现后的代码时:
func (acc accountRepo) RedisSetAccount(ctx context.Context, key string, value interface{}, expiration time.Duration) (err error) { fmt.Println("准备向redis中存储值,key是:", key) err = acc.data.rdb.Set(ctx, key, value, expiration).Err() if err != nil { return err } return nil } func (acc accountRepo) RedisGetAccount(ctx context.Context, key string) (res string, err error) { fmt.Println("准备从redis中取值,key是:", key) result, err := acc.data.rdb.Get(ctx, key).Result() return result, err }
六、改造service
继续回到internal/service/account.go文件中,改造login方法,这里我们如果登录成功了,则直接生成一个token,并且把用户信息保存到redis中。所以最后的login方法实现代码如下:
func (s *AccountService) Login(ctx context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) { acc, err := s.uc.GetAccountInfoByUsernameAndPassword(ctx, req) if err != nil || len(acc.Username) == 0 { return &pb.LoginResponse{Code: 401, Msg: "用户不存在", }, nil } marshal, err := json.Marshal(acc) if err != nil { return &pb.LoginResponse{Code: 401, Msg: "用户不存在", }, nil } fmt.Println("查询用户是:", string(marshal)) hash := md5.Sum([]byte(uuid.New().String())) token := hex.EncodeToString(hash[:]) err = s.uc.RedisSetAccountInfo(ctx, "user_"+token, string(marshal), time.Second*300) if err != nil { return &pb.LoginResponse{Code: 401, Msg: "用户不存在", }, nil } return &pb.LoginResponse{Code: 200, Msg: "请求成功", Token: token}, nil }
七、自动注入
这里由于添加了redis,所以也需要把redis进行自动注入,前面第三步已经实现了redis的注册了,所以这里直接自动注入即可
#进入cmd cd cmd/user-center #注入 wire
八、启动测试
最后我们把项目启动起来,测试下,首先输入正确的用户名和密码
可以看到返回了token,并且把数据也存储到redis了
再输入一个错误的密码
可以看到这里返回了用户不存在,说明对应的redis和mysql的逻辑执行都完全没问题。
以上就是kratos项目融入redis的案例,最后按照惯例,附上本案例的源码,登陆后即可下载。
还没有评论,来说两句吧...