设为首页 加入收藏

TOP

用go设计开发一个自己的轻量级登录库/框架吧(拓展篇)(一)
2023-07-23 13:28:02 】 浏览:52
Tags:计开发

给自己的库/框架拓展一下吧(拓展篇)

主库:weloe/token-go: a light login library.

扩展库:weloe/token-go-extensions (github.com)

本篇给主库扩展一个Adapter提供简单的外部数据存储。

思路

一个库/框架往往不能完成所有事情,需要其他库/框架的支持才能达到更加完善的效果。本篇会对token-go框架的Adapter进行简单的拓展。

首先我们应该想想Adapter是用来干什么的?

从第一篇我们就明确其职责,就是存储数据。我们在token-go里提供了一个内置的adapter:default_adapter,用于框架底层的数据存储,但是这种内存的数据存储有着很多的缺陷,并且没有经过实际的生产测试使用。也因此,我们应该提供更成熟的存储方案来提供给使用者去替代它。

这就是本篇要实现的redis_adapter了

实现

这里还有一个点要注意,将数据存储到外部需要确定数据的序列化和反序列化方法。因此,我们加了一个SerializerAdapter接口,要求新的Adapter选择实现。

token-go/serializer_adapter.go at master · weloe/token-go · GitHub

package persist

import "github.com/weloe/token-go/model"

type SerializerAdapter interface {
	Adapter
	Serialize(*model.Session) ([]byte, error)
	UnSerialize([]byte) (*model.Session, error)
}

具体的调用则是在enforcer对session进行存储或者取出数据的时候进行调用。

func (e *Enforcer) GetSession(id string) *model.Session {
	if v := e.adapter.Get(e.spliceSessionKey(id)); v != nil {
		if s := e.sessionUnSerialize(v); s != nil {
			return s
		} else {
			session, ok := v.(*model.Session)
			if !ok {
				return nil
			}
			return session
		}
	}
	return nil
}

这里的sessionUnSerialize()实际上就是尝试调用了adapter实现的反序列化方法。同理SetSession()也是一样的。

最后就是RedisAdapter了

token-go-extensions/adapter.go at master · weloe/token-go-extensions · GitHub

并不难,只要实现我们之前的Adapter和SerializerAdapter两个接口就行了。

序列化方法使用json,方便查看

package redis_adapter

import (
	"context"
	"encoding/json"
	"github.com/go-redis/redis/v8"
	"github.com/weloe/token-go/model"
	"github.com/weloe/token-go/persist"
	"time"
)

var _ persist.Adapter = (*RedisAdapter)(nil)

var _ persist.SerializerAdapter = (*RedisAdapter)(nil)

type RedisAdapter struct {
	client *redis.Client
}

func (r *RedisAdapter) Serialize(session *model.Session) ([]byte, error) {
	return json.Marshal(session)
}

func (r *RedisAdapter) UnSerialize(bytes []byte) (*model.Session, error) {
	s := &model.Session{}
	err := json.Unmarshal(bytes, s)
	if err != nil {
		return nil, err
	}
	return s, nil
}

func (r *RedisAdapter) GetStr(key string) string {
	res, err := r.client.Get(context.Background(), key).Result()
	if err != nil {
		return ""
	}
	return res
}

func (r *RedisAdapter) SetStr(key string, value string, timeout int64) error {
	err := r.client.Set(context.Background(), key, value, time.Duration(timeout)*time.Second).Err()
	if err != nil {
		return err
	}
	return nil
}

func (r *RedisAdapter) UpdateStr(key string, value string) error {
	err := r.client.Set(context.Background(), key, value, 0).Err()
	if err != nil {
		return err
	}
	return nil
}

func (r *RedisAdapter) DeleteStr(key string) error {
	err := r.client.Del(context.Background(), key).Err()
	if err != nil {
		return err
	}
	return nil
}

func (r *RedisAdapter) GetStrTimeout(key string) int64 {
	duration, err := r.client.TTL(context.Background(), key).Result()
	if err != nil {
		return -1
	}
	return int64(duration.Seconds())
}

func (r *RedisAdapter) UpdateStrTimeout(key string, timeout int64) error {
	var duration time.Duration
	if timeout < 0 {
		duration = -1
	} else {
		duration = time.Duration(timeout) * time.Second
	}
	err := r.client.Expire(context.Background(), k
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇协程并发下数据汇总:除了互斥锁.. 下一篇用go封装一下封禁功能

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目