mirror of
https://gitee.com/johng/gf
synced 2026-06-24 08:48:09 +08:00
cookie,session解耦
This commit is contained in:
@ -9,7 +9,6 @@ package gmvc
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
"gitee.com/johng/gf/g/net/gsession"
|
||||
)
|
||||
|
||||
// 控制器基类
|
||||
@ -18,7 +17,7 @@ type Controller struct {
|
||||
Request *ghttp.ClientRequest // 请求数据对象
|
||||
Response *ghttp.ServerResponse // 返回数据对象
|
||||
Cookie *ghttp.Cookie // COOKIE操作对象
|
||||
Session *gsession.Session // SESSION操作对象
|
||||
Session *ghttp.Session // SESSION操作对象
|
||||
View *View // 视图对象
|
||||
}
|
||||
|
||||
@ -27,9 +26,9 @@ func (c *Controller) Init(s *ghttp.Server, r *ghttp.ClientRequest, w *ghttp.Serv
|
||||
c.Server = s
|
||||
c.Request = r
|
||||
c.Response = w
|
||||
c.Cookie = ghttp.NewCookie(c.Request, c.Response)
|
||||
c.View = NewView(c)
|
||||
c.Session = gsession.Get(c.Cookie.SessionId())
|
||||
c.View = NewView(w)
|
||||
c.Cookie = r.Cookie
|
||||
c.Session = r.Session
|
||||
}
|
||||
|
||||
// 控制器结束请求接口方法
|
||||
|
||||
@ -11,22 +11,23 @@ import (
|
||||
"html/template"
|
||||
"gitee.com/johng/gf/g/os/gview"
|
||||
"gitee.com/johng/gf/g/frame/gins"
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
// 视图对象(一个请求一个视图对象,用完即销毁)
|
||||
type View struct {
|
||||
mu sync.RWMutex // 并发互斥锁
|
||||
ctl *Controller // 所属控制器
|
||||
view *gview.View // 底层视图对象
|
||||
data map[string]interface{} // 视图数据
|
||||
mu sync.RWMutex // 并发互斥锁
|
||||
view *gview.View // 底层视图对象
|
||||
data map[string]interface{} // 视图数据
|
||||
response *ghttp.ServerResponse // 数据返回对象
|
||||
}
|
||||
|
||||
// 创建一个MVC请求中使用的视图对象
|
||||
func NewView(c *Controller) *View {
|
||||
func NewView(w *ghttp.ServerResponse) *View {
|
||||
return &View{
|
||||
ctl : c,
|
||||
view : gins.View(),
|
||||
data : make(map[string]interface{}),
|
||||
view : gins.View(),
|
||||
data : make(map[string]interface{}),
|
||||
response : w,
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,10 +70,10 @@ func (view *View) Display(files...string) error {
|
||||
file = files[0]
|
||||
}
|
||||
if content, err := view.Parse(file); err != nil {
|
||||
view.ctl.Response.WriteString("Tpl Parsing Error: " + err.Error())
|
||||
view.response.WriteString("Tpl Parsing Error: " + err.Error())
|
||||
return err
|
||||
} else {
|
||||
view.ctl.Response.Write(content)
|
||||
view.response.Write(content)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
"net/url"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
@ -18,13 +17,6 @@ type Client struct {
|
||||
http.Client
|
||||
}
|
||||
|
||||
// 请求对象
|
||||
type ClientRequest struct {
|
||||
http.Request
|
||||
id uint64 // 请求id(唯一)
|
||||
getvals *url.Values // GET参数
|
||||
}
|
||||
|
||||
// 客户端请求结果对象
|
||||
type ClientResponse struct {
|
||||
http.Response
|
||||
|
||||
@ -7,13 +7,19 @@ package ghttp
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"gitee.com/johng/gf/g/encoding/gjson"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"gitee.com/johng/gf/g/util/gconv"
|
||||
"gitee.com/johng/gf/g/encoding/gjson"
|
||||
)
|
||||
|
||||
// 获取当前请求的id
|
||||
func (r *ClientRequest) Id() uint64 {
|
||||
return r.id
|
||||
// 请求对象
|
||||
type ClientRequest struct {
|
||||
http.Request
|
||||
getvals *url.Values // GET参数
|
||||
Id uint64 // 请求id(唯一)
|
||||
Cookie *Cookie // 与当前请求绑定的Cookie对象(并发安全)
|
||||
Session *Session // 与当前请求绑定的Session对象(并发安全)
|
||||
}
|
||||
|
||||
// 获得指定名称的get参数列表
|
||||
|
||||
@ -45,7 +45,7 @@ var cookies = gmap.NewUintInterfaceMap()
|
||||
|
||||
// 创建一个cookie对象,与传入的请求对应
|
||||
func NewCookie(r *ClientRequest, w *ServerResponse) *Cookie {
|
||||
if r := GetCookie(r.Id()); r != nil {
|
||||
if r := GetCookie(r.Id); r != nil {
|
||||
return r
|
||||
}
|
||||
c := &Cookie {
|
||||
@ -55,7 +55,7 @@ func NewCookie(r *ClientRequest, w *ServerResponse) *Cookie {
|
||||
response : w,
|
||||
}
|
||||
c.init()
|
||||
cookies.Set(uint(r.Id()), c)
|
||||
cookies.Set(uint(r.Id), c)
|
||||
return c
|
||||
}
|
||||
|
||||
@ -67,11 +67,6 @@ func GetCookie(requestid uint64) *Cookie {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 请求完毕后删除已经存在的Cookie对象
|
||||
func RemoveCookie(requestid uint64) {
|
||||
cookies.Remove(uint(requestid))
|
||||
}
|
||||
|
||||
// 获取默认的domain参数
|
||||
func defaultDomain(r *ClientRequest) string {
|
||||
return strings.Split(r.Host, ":")[0]
|
||||
@ -90,7 +85,12 @@ func (c *Cookie) init() {
|
||||
|
||||
// 获取SessionId
|
||||
func (c *Cookie) SessionId() string {
|
||||
return c.Get(SESSION_ID_NAME)
|
||||
v := c.Get(SESSION_ID_NAME)
|
||||
if v == "" {
|
||||
v = makeSessionId()
|
||||
c.SetSessionId(v)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// 设置SessionId
|
||||
@ -132,6 +132,11 @@ func (c *Cookie) Remove(key, domain, path string) {
|
||||
c.SetCookie(key, "", domain, path, -86400)
|
||||
}
|
||||
|
||||
// 请求完毕后删除已经存在的Cookie对象
|
||||
func (c *Cookie) Close() {
|
||||
cookies.Remove(uint(c.request.Id))
|
||||
}
|
||||
|
||||
// 输出到客户端
|
||||
func (c *Cookie) Output() {
|
||||
c.mu.RLock()
|
||||
|
||||
@ -16,7 +16,6 @@ import (
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"gitee.com/johng/gf/g/net/gsession"
|
||||
"gitee.com/johng/gf/g/encoding/ghtml"
|
||||
)
|
||||
|
||||
@ -39,7 +38,7 @@ func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
// 构造请求/返回参数对象
|
||||
request := &ClientRequest{}
|
||||
response := &ServerResponse{}
|
||||
request.id = s.increServed()
|
||||
request.Id = s.increServed()
|
||||
request.Request = *r
|
||||
response.ResponseWriter = w
|
||||
if h := s.getHandler(gDEFAULT_DOMAIN, r.Method, r.URL.Path); h != nil {
|
||||
@ -55,13 +54,10 @@ func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// 初始化控制器
|
||||
func (s *Server)callHandler(h *HandlerItem, r *ClientRequest, w *ServerResponse) {
|
||||
// 会话处理,每个请求必定有一个sessionid
|
||||
cookie := NewCookie(r, w)
|
||||
sessionid := cookie.SessionId()
|
||||
if sessionid == "" {
|
||||
sessionid = gsession.Id()
|
||||
cookie.SetSessionId(sessionid)
|
||||
}
|
||||
// 会话处理
|
||||
r.Cookie = NewCookie(r, w)
|
||||
r.Session = GetSession(r.Cookie.SessionId())
|
||||
|
||||
// 请求处理
|
||||
if h.faddr == nil {
|
||||
// 新建一个控制器对象处理请求
|
||||
@ -80,13 +76,15 @@ func (s *Server)callHandler(h *HandlerItem, r *ClientRequest, w *ServerResponse)
|
||||
}
|
||||
|
||||
// 输出Cookie
|
||||
cookie.Output()
|
||||
r.Cookie.Output()
|
||||
|
||||
// 输出缓冲区
|
||||
w.OutputBuffer()
|
||||
|
||||
// 删除当前会话的Cookie
|
||||
RemoveCookie(r.Id())
|
||||
// 关闭当前会话的Cookie
|
||||
go r.Cookie.Close()
|
||||
// 更新Sssion会话超时时间
|
||||
go r.Session.UpdateExpire()
|
||||
}
|
||||
|
||||
// 处理静态文件请求
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
package gsession
|
||||
// 并发安全的Session管理器
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"sync"
|
||||
@ -14,10 +14,8 @@ import (
|
||||
"gitee.com/johng/gf/g/os/gcache"
|
||||
"gitee.com/johng/gf/g/util/grand"
|
||||
"gitee.com/johng/gf/g/container/gmap"
|
||||
)
|
||||
|
||||
const (
|
||||
DEFAULT_EXPIRE_TIME = 600 // 默认过期间隔(10分钟)
|
||||
"gitee.com/johng/gf/g/util/gconv"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// 单个session对象
|
||||
@ -25,114 +23,93 @@ type Session struct {
|
||||
mu sync.RWMutex // 并发安全互斥锁
|
||||
id string // sessionid
|
||||
data *gmap.StringInterfaceMap // session数据
|
||||
expire int // 过期间隔(秒)
|
||||
}
|
||||
|
||||
// 默认session过期时间(秒)
|
||||
var defaultSessionMaxAge int32 = 600
|
||||
|
||||
// 生成一个唯一的sessionid字符串
|
||||
func Id() string {
|
||||
func makeSessionId() string {
|
||||
return strings.ToUpper(strconv.FormatInt(gtime.Nanosecond(), 32) + grand.RandStr(3))
|
||||
}
|
||||
|
||||
// 设置默认的session过期时间
|
||||
func SetSessionMaxAge(maxage int) {
|
||||
atomic.StoreInt32(&defaultSessionMaxAge, int32(maxage))
|
||||
}
|
||||
|
||||
// 获取或者生成一个session对象
|
||||
func Get(sessionid string) *Session {
|
||||
if r := gcache.Get(cacheKey(sessionid)); r != nil {
|
||||
func GetSession(sessionid string) *Session {
|
||||
if r := gcache.Get(sessionCacheKey(sessionid)); r != nil {
|
||||
return r.(*Session)
|
||||
}
|
||||
s := &Session {
|
||||
id : sessionid,
|
||||
data : gmap.NewStringInterfaceMap(),
|
||||
expire : DEFAULT_EXPIRE_TIME,
|
||||
}
|
||||
s.updateExpire()
|
||||
return s
|
||||
}
|
||||
|
||||
// session在gache中的缓存键名
|
||||
func cacheKey(sessionid string) string {
|
||||
func sessionCacheKey(sessionid string) string {
|
||||
return "session_" + sessionid
|
||||
}
|
||||
|
||||
// 获取sessionid
|
||||
func (s *Session) Id () string {
|
||||
go s.updateExpire()
|
||||
func (s *Session) Id() string {
|
||||
return s.id
|
||||
}
|
||||
|
||||
// 获取当前session所有数据
|
||||
func (s *Session) Data () map[string]interface{} {
|
||||
go s.updateExpire()
|
||||
return *s.data.Clone()
|
||||
}
|
||||
|
||||
// 设置session过期间隔(秒)
|
||||
func (s *Session) SetExpire (expire int) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
go s.updateExpire()
|
||||
s.expire = expire
|
||||
}
|
||||
|
||||
// 设置session
|
||||
func (s *Session) Set (k string, v interface{}) {
|
||||
go s.updateExpire()
|
||||
s.data.Set(k, v)
|
||||
}
|
||||
|
||||
// 批量设置
|
||||
func (s *Session) BatchSet (m map[string]interface{}) {
|
||||
s.data.BatchSet(m)
|
||||
}
|
||||
|
||||
// 获取session
|
||||
func (s *Session) Get (k string) interface{} {
|
||||
go s.updateExpire()
|
||||
return s.data.Get(k)
|
||||
}
|
||||
|
||||
func (s *Session) GetString (k string) string {
|
||||
return gconv.String(s.Get(k))
|
||||
}
|
||||
|
||||
func (s *Session) GetBool (k string) bool {
|
||||
return gconv.Bool(s.Get(k))
|
||||
}
|
||||
|
||||
func (s *Session) GetInt (k string) int {
|
||||
go s.updateExpire()
|
||||
if r := s.data.Get(k); r != nil {
|
||||
return r.(int)
|
||||
}
|
||||
return 0
|
||||
return gconv.Int(s.Get(k))
|
||||
}
|
||||
|
||||
func (s *Session) GetUint (k string) uint {
|
||||
go s.updateExpire()
|
||||
if r := s.data.Get(k); r != nil {
|
||||
return r.(uint)
|
||||
}
|
||||
return 0
|
||||
return gconv.Uint(s.Get(k))
|
||||
}
|
||||
|
||||
func (s *Session) GetFloat32 (k string) float32 {
|
||||
go s.updateExpire()
|
||||
if r := s.data.Get(k); r != nil {
|
||||
return r.(float32)
|
||||
}
|
||||
return 0
|
||||
return gconv.Float32(s.Get(k))
|
||||
}
|
||||
|
||||
func (s *Session) GetFloat64 (k string) float64 {
|
||||
go s.updateExpire()
|
||||
if r := s.data.Get(k); r != nil {
|
||||
return r.(float64)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 获取session(字符串)
|
||||
func (s *Session) GetString (k string) string {
|
||||
go s.updateExpire()
|
||||
if r := s.data.Get(k); r != nil {
|
||||
return r.(string)
|
||||
}
|
||||
return ""
|
||||
return gconv.Float64(s.Get(k))
|
||||
}
|
||||
|
||||
// 删除session
|
||||
func (s *Session) Remove (k string) {
|
||||
go s.updateExpire()
|
||||
s.data.Remove(k)
|
||||
}
|
||||
|
||||
// 更新过期时间
|
||||
func (s *Session) updateExpire() {
|
||||
//gcache.Set(cacheKey(s.id), s, int64(s.expire*1000))
|
||||
gcache.Set(cacheKey(s.id), s, 0)
|
||||
}
|
||||
// 更新过期时间(如果用在守护进程中长期使用,需要手动调用进行更新,防止超时被清除)
|
||||
func (s *Session) UpdateExpire() {
|
||||
gcache.Set(sessionCacheKey(s.id), s, int64(defaultSessionMaxAge*1000))
|
||||
}
|
||||
19
geg/frame/mvc/controller/demo/cookie.go
Normal file
19
geg/frame/mvc/controller/demo/cookie.go
Normal file
@ -0,0 +1,19 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/os/gtime"
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindHandler("/cookie", Cookie)
|
||||
}
|
||||
|
||||
// 用于函数映射
|
||||
func Cookie(s *ghttp.Server, r *ghttp.ClientRequest, w *ghttp.ServerResponse) {
|
||||
datetime := r.Cookie.Get("datetime")
|
||||
r.Cookie.Set("datetime", gtime.Datetime())
|
||||
|
||||
w.WriteString("datetime:" + datetime)
|
||||
}
|
||||
@ -2,8 +2,6 @@ package demo
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
"gitee.com/johng/gf/g/net/gsession"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
||||
@ -15,17 +13,5 @@ func init() {
|
||||
|
||||
// 用于函数映射
|
||||
func Hello(s *ghttp.Server, r *ghttp.ClientRequest, w *ghttp.ServerResponse) {
|
||||
cookie := ghttp.GetCookie(r.Id())
|
||||
session := gsession.Get(cookie.SessionId())
|
||||
|
||||
id := 0
|
||||
for i := 0; i < 1; i++ {
|
||||
if r := session.Get("id"); r != nil {
|
||||
id = r.(int)
|
||||
}
|
||||
id++
|
||||
session.Set("id", id)
|
||||
}
|
||||
|
||||
w.WriteString("Hello World!" + strconv.Itoa(id))
|
||||
w.WriteString("Hello World!")
|
||||
}
|
||||
19
geg/frame/mvc/controller/demo/session.go
Normal file
19
geg/frame/mvc/controller/demo/session.go
Normal file
@ -0,0 +1,19 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindHandler("/session", Session)
|
||||
}
|
||||
|
||||
// 用于函数映射
|
||||
func Session(s *ghttp.Server, r *ghttp.ClientRequest, w *ghttp.ServerResponse) {
|
||||
id := r.Session.GetInt("id")
|
||||
r.Session.Set("id", id + 1)
|
||||
|
||||
w.WriteString("id:" + strconv.Itoa(id))
|
||||
}
|
||||
Reference in New Issue
Block a user