beego源码解析之session

目录

 

组件 package session

Store

Provoider

Register

manager

流程

session开启

session回收


组件 package session

目前session提供了memory、mysql、redis 、file引擎的provider , 下文非特殊标记都是指的memory

Store

session存储仓库的顶级接口

 

type Store interface {
   Set(key, value interface{}) error     //set session value
   Get(key interface{}) interface{}      //get session value
   Delete(key interface{}) error         //delete session value
   SessionID() string                    //back current sessionID
   SessionRelease(w http.ResponseWriter) // release the resource & save data to provider & return the data
   Flush() error                         //delete all data
}

 

Provoider

提供了session的访问方法,并保存session store , 我们可以通过sessionId , 操作session

type Provider interface {
   SessionInit(gclifetime int64, config string) error
   SessionRead(sid string) (Store, error)
   SessionExist(sid string) bool
   SessionRegenerate(oldsid, sid string) (Store, error)
   SessionDestroy(sid string) error
   SessionAll() int //get all active session
   SessionGC()
}

 

Register

这是一个方法,提供了注册session provoider的功能。

//这是session provider的集合
var provides = make(map[string]Provider)
//这是注册的方法
type Provider interface {
   SessionInit(gclifetime int64, config string) error
   SessionRead(sid string) (Store, error)
   SessionExist(sid string) bool
   SessionRegenerate(oldsid, sid string) (Store, error)
   SessionDestroy(sid string) error
   SessionAll() int //get all active session
   SessionGC()
}
//这是具体的session provider的初始化方法
func init() {
    Register("memory", mempder)
}

 

manager

session全局管理器

//session全局管理器对象
type Manager struct {
   provider Provider
   config   *managerConfig
}
//全局管理器的配置
type managerConfig struct {
    CookieName      string `json:"cookieName"`
    EnableSetCookie bool   `json:"enableSetCookie,omitempty"`
    Gclifetime      int64  `json:"gclifetime"`
    Maxlifetime     int64  `json:"maxLifetime"`
    Secure          bool   `json:"secure"`
    CookieLifeTime  int    `json:"cookieLifeTime"`
    ProviderConfig  string `json:"providerConfig"`
    Domain          string `json:"domain"`
    SessionIDLength int64  `json:"sessionIDLength"`
}

 

流程

全局管理器的初始化 , 以下是代码片段

//1、beego启动
func Run(params ...string) {
   //初始化hooks
   initBeforeHTTPRun()
   //后续代码省略
}
//2、初始化hooks ,并逐个调用
func initBeforeHTTPRun() {
    //我们只关注这个,其他的省略
    AddAPPStartHook(registerSession)
    for _, hk := range hooks {
        if err := hk(); err != nil {
            panic(err)
        }
    }
}
//3、初始化globalSession管理器
func registerSession() error {
    //其他的代码省略了
    if GlobalSessions, err = session.NewManager(BConfig.WebConfig.Session.SessionProvider, sessionConfig); err != nil {
            return err
    }
    //开启session回收
    go GlobalSessions.GC()
}
//4、这里是new全局管理器的核心方法了
func NewManager(provideName string, cf *ManagerConfig) (*Manager, error) {
    //获取具体的provider
    provider, ok := provides[provideName]
    if !ok {
        return nil, fmt.Errorf("session: unknown provide %q (forgotten import?)", provideName)
    }
    //初始化provider
    err := provider.SessionInit(cf.Maxlifetime, cf.ProviderConfig)
    if err != nil {
        return nil, err
    }
​
    if cf.SessionIDLength == 0 {
        cf.SessionIDLength = 16
    }
    //返回全局管理器对象
    return &Manager{
        provider,
        cf,
    }, nil
}

 

session开启

 

func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (session Store, err error) {
   sid, errs := manager.getSid(r)
   if errs != nil {
      return nil, errs
   }
    //sessionId 存在,则直接返回 Store的具体实现
   if sid != "" && manager.provider.SessionExist(sid) {
      return manager.provider.SessionRead(sid)
   }
​
   // 不存在则new一个session
   sid, errs = manager.sessionID()
   if errs != nil {
      return nil, errs
   }
​
   session, err = manager.provider.SessionRead(sid)
   if err != nil {
      return nil, err
   }
   cookie := &http.Cookie{//省略}
   if manager.config.CookieLifeTime > 0 {
      cookie.MaxAge = manager.config.CookieLifeTime
      cookie.Expires = time.Now().Add(time.Duration(manager.config.CookieLifeTime) * time.Second)
   }
   if manager.config.EnableSetCookie {
      http.SetCookie(w, cookie)
   }
   r.AddCookie(cookie)
​
   if manager.config.EnableSidInHTTPHeader {
      r.Header.Set(manager.config.SessionNameInHTTPHeader, sid)
      w.Header().Set(manager.config.SessionNameInHTTPHeader, sid)
   }
​
   return
}

 

session回收

// 1、session管理器初始化的时候 , 启动该方法,该方法会定期执行
func (manager *Manager) GC() {
    //回收session
   manager.provider.SessionGC()
   //Gc时间间隔递归执行
   time.AfterFunc(time.Duration(manager.config.Gclifetime)*time.Second, func() { manager.GC() })
}
// 2、回收
func (pder *MemProvider) SessionGC() {
    pder.lock.RLock()
    for {
        //provider的具体实现里 有两个session集合 , 
        //一个是map类型,方便存取
        //一个是list.List类型,方便遍历,我们在开始session的时候,每次访问都会将session移动到list的首位置,所以,GC的时候            是倒序开始
        element := pder.list.Back()
        if element == nil {
            break
        }
        if (element.Value.(*MemSessionStore).timeAccessed.Unix() + pder.maxlifetime) < time.Now().Unix() {
            //找到超过生命周期的,直接干掉,另外要干掉map集合的数据
            pder.lock.RUnlock()
            pder.lock.Lock()
            pder.list.Remove(element)
            delete(pder.sessions, element.Value.(*MemSessionStore).sid)
            pder.lock.Unlock()
            pder.lock.RLock()
        } else {
            //如果找到的是生命周期内的,那么该session之前的对象券都是生命周期内的,就不用处理了,直接退出
            break
        }
    }
    pder.lock.RUnlock()
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值