使用gin封装一个web脚手架(六):实现session(中

设计好session的数据结构后开始存放初始session值

先在context.go中定义好session的结构体

package context

//context/context.go

import (
	"github.com/gin-gonic/gin"
	"strings"
)

type Context struct {
	*gin.Context
}

type HandlerFunc func(*Context)

func (c *Context) Domain() string {

	return c.Request.Host[:strings.Index(c.Request.Host, ":")]
}

type Session struct {
	Cookie      string                 `json:"cookie"`
	ExpireTime  int64                  `json:"expire_time"`
	SessionList map[string]interface{} `json:"session_list"`
}

复制代码

接下来在session中间件中存储初始化数据

package session

import (
	context2 "context"
	"encoding/json"
	uuid "github.com/satori/go.uuid"
	"myGin/context"
	"myGin/redis"
	"time"
)

var cookieName = "my_gin"

var lifeTime = 3600

func Session(c *context.Context) {

	sessionKey := uuid.NewV4().String()

	c.SetCookie(cookieName, sessionKey, lifeTime, "/", c.Domain(), false, true)

	session := context.Session{
		Cookie:      sessionKey,
		ExpireTime:  time.Now().Unix() + int64(lifeTime),
		SessionList: make(map[string]interface{}),
	}

	jsonString, _ := json.Marshal(session)

	redis.Client().Set(context2.TODO(), sessionKey, jsonString, time.Second*time.Duration(lifeTime))

}
复制代码

运行浏览器后,在redis中出现

image.png

问题出现了,虽然数据存储进去了,但是每刷新一次浏览器就会重新存储一次session,这显然不是我们想要的。正确的逻辑应该是,cookie存在并且能够在redis中找到这个值就不需要重新设置了。

修改一下代码

package session

import (
	context2 "context"
	"encoding/json"
	uuid "github.com/satori/go.uuid"
	"myGin/context"
	"myGin/redis"
	"time"
)

var cookieName = "my_gin"

var lifeTime = 3600

func Session(c *context.Context) {

	cookie, err := c.Cookie(cookieName)

	if err == nil {

		sessionString, err := redis.Client().Get(context2.TODO(), cookie).Result()

		if err == nil {

			var session context.Session

			json.Unmarshal([]byte(sessionString), &session)

			return
		}

	}

	sessionKey := uuid.NewV4().String()

	c.SetCookie(cookieName, sessionKey, lifeTime, "/", c.Domain(), false, true)

	session := context.Session{
		Cookie:      sessionKey,
		ExpireTime:  time.Now().Unix() + int64(lifeTime),
		SessionList: make(map[string]interface{}),
	}

	jsonString, _ := json.Marshal(session)

	redis.Client().Set(context2.TODO(), sessionKey, jsonString, time.Second*time.Duration(lifeTime))

}
复制代码

为了防止二次查询,将session结果存储到gin的context中

package session

import (
	context2 "context"
	"encoding/json"
	uuid "github.com/satori/go.uuid"
	"myGin/context"
	"myGin/redis"
	"time"
)

var cookieName = "my_gin"

var lifeTime = 3600

func Session(c *context.Context) {

	cookie, err := c.Cookie(cookieName)

	if err == nil {

		sessionString, err := redis.Client().Get(context2.TODO(), cookie).Result()

		if err == nil {

			var session context.Session

			json.Unmarshal([]byte(sessionString), &session)

			//存储到context中,方便当前请求中的其他函数好操作session
			c.Set("_session", session)

			return
		}

	}

	sessionKey := uuid.NewV4().String()

	c.SetCookie(cookieName, sessionKey, lifeTime, "/", c.Domain(), false, true)

	session := context.Session{
		Cookie:      sessionKey,
		ExpireTime:  time.Now().Unix() + int64(lifeTime),
		SessionList: make(map[string]interface{}),
	}

	//这里也要
	c.Set("_session", session)

	jsonString, _ := json.Marshal(session)

	redis.Client().Set(context2.TODO(), sessionKey, jsonString, time.Second*time.Duration(lifeTime))

}
复制代码