beego源码解析之session
Posted better_hui
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了beego源码解析之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() }
以上是关于beego源码解析之session的主要内容,如果未能解决你的问题,请参考以下文章