6.3 session存储

上一节我们介绍了Session管理器的实现原理,定义了存储session的接口,这小节我们将示例一个基于内存的session存储接口的实现,其他的存储方式,读者可以自行参考示例来实现,内存的实现请看下面的例子代码


    package memory

    import (
        "container/list"
        "github.com/astaxie/session"
        "sync"
        "time"
    )

    var pder = &Provider{list: list.New()}

    type SessionStore struct {
        sid          string                      //session id唯一标示
        timeAccessed time.Time                   //最后访问时间
        value        map[interface{}]interface{} //session里面存储的值
    }

    func (st *SessionStore) Set(key, value interface{}) error {
        st.value[key] = value
        pder.SessionUpdate(st.sid)
        return nil
    }

    func (st *SessionStore) Get(key interface{}) interface{} {
        pder.SessionUpdate(st.sid)
        if v, ok := st.value[key]; ok {
            return v
        } else {
            return nil
        }
        return nil
    }

    func (st *SessionStore) Delete(key interface{}) error {
        delete(st.value, key)
        pder.SessionUpdate(st.sid)
        return nil
    }

    func (st *SessionStore) SessionID() string {
        return st.sid
    }

    type Provider struct {
        lock     sync.Mutex               //用来锁
        sessions map[string]*list.Element //用来存储在内存
        list     *list.List               //用来做gc
    }

    func (pder *Provider) SessionInit(sid string) (session.Session, error) {
        pder.lock.Lock()
        defer pder.lock.Unlock()
        v := make(map[interface{}]interface{}, 0)
        newsess := &SessionStore{sid: sid, timeAccessed: time.Now(), value: v}
        element := pder.list.PushBack(newsess)
        pder.sessions[sid] = element
        return newsess, nil
    }

    func (pder *Provider) SessionRead(sid string) (session.Session, error) {
        if element, ok := pder.sessions[sid]; ok {
            return element.Value.(*SessionStore), nil
        } else {
            sess, err := pder.SessionInit(sid)
            return sess, err
        }
        return nil, nil
    }

    func (pder *Provider) SessionDestroy(sid string) error {
        if element, ok := pder.sessions[sid]; ok {
            delete(pder.sessions, sid)
            pder.list.Remove(element)
            return nil
        }
        return nil
    }

    func (pder *Provider) SessionGC(maxlifetime int64) {
        pder.lock.Lock()
        defer pder.lock.Unlock()

        for {
            element := pder.list.Back()
            if element == nil {
                break
            }
            if (element.Value.(*SessionStore).timeAccessed.Unix() + maxlifetime) < time.Now().Unix() {
                pder.list.Remove(element)
                delete(pder.sessions, element.Value.(*SessionStore).sid)
            } else {
                break
            }
        }
    }

    func (pder *Provider) SessionUpdate(sid string) error {
        pder.lock.Lock()
        defer pder.lock.Unlock()
        if element, ok := pder.sessions[sid]; ok {
            element.Value.(*SessionStore).timeAccessed = time.Now()
            pder.list.MoveToFront(element)
            return nil
        }
        return nil
    }

    func init() {
        pder.sessions = make(map[string]*list.Element, 0)
        session.Register("memory", pder)
    }

上面这个代码实现了一个内存存储的session机制。通过init函数注册到session管理器中。这样就可以方便的调用了。我们如何来调用该引擎呢?请看下面的代码


    import (
        "github.com/astaxie/session"
        _ "github.com/astaxie/session/providers/memory"
    )

当import的时候已经执行了memory函数里面的init函数,这样就已经注册到session管理器中,我们就可以使用了,通过如下方式就可以初始化一个session管理器:


    var globalSessions *session.Manager

    //然后在init函数中初始化
    func init() {
        globalSessions, _ = session.NewManager("memory", "gosessionid", 3600)
        go globalSessions.GC()
    }

results matching ""

    No results matching ""