mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
merge master
This commit is contained in:
5
TODO.MD
5
TODO.MD
@ -50,6 +50,11 @@
|
||||
1. grpool增加支持阻塞添加任务接口;
|
||||
1. gdb.Model在链式安全的对象创建中增加sync.Pool的使用;
|
||||
1. 增加g.Table快捷方法以方便操作数据表,但是得考虑后续模型操作设计,特别是脚手架的模型管理;
|
||||
1. 改进ghttp分组路由中对hook的支持方式,以便格式与BindHookHandler统一;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# DONE
|
||||
1. gconv完善针对不同类型的判断,例如:尽量减少sprintf("%v", xxx)来执行string类型的转换;
|
||||
|
||||
@ -170,7 +170,7 @@ var (
|
||||
// which is DEFAULT_GROUP_NAME in default.
|
||||
func New(name ...string) (db DB, err error) {
|
||||
group := configs.defaultGroup
|
||||
if len(name) > 0 {
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
group = name[0]
|
||||
}
|
||||
configs.RLock()
|
||||
|
||||
@ -110,7 +110,7 @@ func New(config Config) *Redis {
|
||||
// it returns a redis instance with default group.
|
||||
func Instance(name ...string) *Redis {
|
||||
group := DEFAULT_GROUP_NAME
|
||||
if len(name) > 0 {
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
group = name[0]
|
||||
}
|
||||
v := instances.GetOrSetFuncLock(group, func() interface{} {
|
||||
|
||||
@ -77,7 +77,7 @@ func Config(name ...string) *gcfg.Config {
|
||||
func Database(name ...string) gdb.DB {
|
||||
config := Config()
|
||||
group := gdb.DEFAULT_GROUP_NAME
|
||||
if len(name) > 0 {
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
group = name[0]
|
||||
}
|
||||
key := fmt.Sprintf("%s.%s", gFRAME_CORE_COMPONENT_NAME_DATABASE, group)
|
||||
@ -214,7 +214,7 @@ func parseDBConfigNode(value interface{}) *gdb.ConfigNode {
|
||||
func Redis(name ...string) *gredis.Redis {
|
||||
config := Config()
|
||||
group := "default"
|
||||
if len(name) > 0 {
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
group = name[0]
|
||||
}
|
||||
key := fmt.Sprintf("%s.%s", gFRAME_CORE_COMPONENT_NAME_REDIS, group)
|
||||
|
||||
@ -192,7 +192,7 @@ func serverProcessInit() {
|
||||
// 单例模式,请保证name的唯一性
|
||||
func GetServer(name ...interface{}) *Server {
|
||||
sname := gDEFAULT_SERVER
|
||||
if len(name) > 0 {
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
sname = gconv.String(name[0])
|
||||
}
|
||||
if s := serverMapping.Get(sname); s != nil {
|
||||
|
||||
@ -9,11 +9,12 @@ package ghttp
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -25,7 +26,7 @@ const (
|
||||
NAME_TO_URI_TYPE_CAMEL = 3 // 采用驼峰命名方式
|
||||
gDEFAULT_COOKIE_PATH = "/" // 默认path
|
||||
gDEFAULT_COOKIE_MAX_AGE = 86400 * 365 // 默认cookie有效期(一年)
|
||||
gDEFAULT_SESSION_MAX_AGE = 600000 // 默认session有效期(600秒)
|
||||
gDEFAULT_SESSION_MAX_AGE = 86400 // 默认session有效期(一天)
|
||||
gDEFAULT_SESSION_ID_NAME = "gfsessionid" // 默认存放Cookie中的SessionId名称
|
||||
gCHANGE_CONFIG_WHILE_RUNNING_ERROR = "cannot be changed while running"
|
||||
)
|
||||
|
||||
@ -38,13 +38,13 @@ func (s *Server) Group(prefix ...string) *RouterGroup {
|
||||
|
||||
// 获取分组路由对象
|
||||
func (d *Domain) Group(prefix ...string) *RouterGroup {
|
||||
if len(prefix) > 0 {
|
||||
return &RouterGroup{
|
||||
domain: d,
|
||||
prefix: prefix[0],
|
||||
}
|
||||
group := &RouterGroup{
|
||||
domain: d,
|
||||
}
|
||||
return &RouterGroup{}
|
||||
if len(prefix) > 0 {
|
||||
group.prefix = prefix[0]
|
||||
}
|
||||
return group
|
||||
}
|
||||
|
||||
// 执行分组路由批量绑定
|
||||
|
||||
@ -3,32 +3,34 @@
|
||||
// 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://github.com/gogf/gf.
|
||||
// 并发安全的Session管理器
|
||||
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"github.com/gogf/gf/g/container/gvar"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"github.com/gogf/gf/g/util/grand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SESSION对象
|
||||
// SESSION对象,并发安全
|
||||
type Session struct {
|
||||
id string // SessionId
|
||||
data *gmap.StrAnyMap // Session数据
|
||||
dirty bool // 数据是否被修改
|
||||
server *Server // 所属Server
|
||||
request *Request // 关联的请求
|
||||
}
|
||||
|
||||
// 生成一个唯一的SessionId字符串,长度18位。
|
||||
func makeSessionId() string {
|
||||
return strings.ToUpper(strconv.FormatInt(gtime.Nanosecond(), 36) + grand.RandStr(6))
|
||||
return strings.ToUpper(strconv.FormatInt(gtime.Nanosecond(), 36) + grand.Str(6))
|
||||
}
|
||||
|
||||
// 获取或者生成一个session对象(延迟初始化)
|
||||
@ -41,17 +43,22 @@ func GetSession(r *Request) *Session {
|
||||
}
|
||||
}
|
||||
|
||||
// 执行初始化(用于延迟初始化).
|
||||
// UpdateSession updates the session with custom map.
|
||||
func (s *Server) UpdateSession(id string, data map[string]interface{}) {
|
||||
v := s.sessions.GetOrSetFuncLock(id, func() interface{} {
|
||||
return gmap.NewStrAnyMap(true)
|
||||
}, s.GetSessionMaxAge()*1000)
|
||||
v.(*gmap.StrAnyMap).Sets(data)
|
||||
}
|
||||
|
||||
// 延迟初始化
|
||||
func (s *Session) init() {
|
||||
if len(s.id) == 0 {
|
||||
s.server = s.request.Server
|
||||
// 根据提交的SESSION ID获取已存在SESSION
|
||||
id := s.request.Cookie.GetSessionId()
|
||||
if id != "" {
|
||||
data := s.server.sessions.Get(id)
|
||||
if data != nil {
|
||||
if id := s.request.Cookie.GetSessionId(); id != "" {
|
||||
if v := s.server.sessions.Get(id); v != nil {
|
||||
s.id = id
|
||||
s.data = data.(*gmap.StrAnyMap)
|
||||
s.data = v.(*gmap.StrAnyMap)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -59,6 +66,7 @@ func (s *Session) init() {
|
||||
s.id = s.request.Cookie.MakeSessionId()
|
||||
s.data = gmap.NewStrAnyMap(true)
|
||||
s.server.sessions.Set(s.id, s.data, s.server.GetSessionMaxAge()*1000)
|
||||
s.dirty = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +76,7 @@ func (s *Session) Id() string {
|
||||
return s.id
|
||||
}
|
||||
|
||||
// 获取当前session所有数据
|
||||
// 获取当前session所有数据,注意是值拷贝
|
||||
func (s *Session) Map() map[string]interface{} {
|
||||
if len(s.id) > 0 || s.request.Cookie.GetSessionId() != "" {
|
||||
s.init()
|
||||
@ -77,16 +85,27 @@ func (s *Session) Map() map[string]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获得session map大小
|
||||
func (s *Session) Size() int {
|
||||
if len(s.id) > 0 || s.request.Cookie.GetSessionId() != "" {
|
||||
s.init()
|
||||
return s.data.Size()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 设置session
|
||||
func (s *Session) Set(key string, value interface{}) {
|
||||
s.init()
|
||||
s.data.Set(key, value)
|
||||
s.dirty = true
|
||||
}
|
||||
|
||||
// 批量设置
|
||||
func (s *Session) Sets(m map[string]interface{}) {
|
||||
s.init()
|
||||
s.data.Sets(m)
|
||||
s.dirty = true
|
||||
}
|
||||
|
||||
// 判断键名是否存在
|
||||
@ -98,6 +117,58 @@ func (s *Session) Contains(key string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// 判断session是否有修改(包括新创建)
|
||||
func (s *Session) IsDirty() bool {
|
||||
return s.dirty
|
||||
}
|
||||
|
||||
// 删除指定session键值对
|
||||
func (s *Session) Remove(key string) {
|
||||
if len(s.id) > 0 || s.request.Cookie.GetSessionId() != "" {
|
||||
s.init()
|
||||
s.data.Remove(key)
|
||||
s.dirty = true
|
||||
}
|
||||
}
|
||||
|
||||
// 将session数据导出为[]byte数据(目前使用json进行序列化)
|
||||
func (s *Session) Export() (data []byte, err error) {
|
||||
if s.Size() > 0 {
|
||||
data, err = json.Marshal(s.data)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 从[]byte中恢复session数据(目前使用json进行序列化)
|
||||
func (s *Session) Restore(data []byte) (err error) {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
if len(s.id) > 0 || s.request.Cookie.GetSessionId() != "" {
|
||||
s.init()
|
||||
s.data.LockFunc(func(m map[string]interface{}) {
|
||||
err = json.Unmarshal(data, &m)
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 清空session
|
||||
func (s *Session) Clear() {
|
||||
if len(s.id) > 0 || s.request.Cookie.GetSessionId() != "" {
|
||||
s.init()
|
||||
s.data.Clear()
|
||||
s.dirty = true
|
||||
}
|
||||
}
|
||||
|
||||
// 更新过期时间(如果用在守护进程中长期使用,需要手动调用进行更新,防止超时被清除)
|
||||
func (s *Session) UpdateExpire() {
|
||||
if len(s.id) > 0 && s.data.Size() > 0 {
|
||||
s.server.sessions.Set(s.id, s.data, s.server.GetSessionMaxAge()*1000)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取SESSION变量
|
||||
func (s *Session) Get(key string, def ...interface{}) interface{} {
|
||||
if len(s.id) > 0 || s.request.Cookie.GetSessionId() != "" {
|
||||
@ -114,30 +185,7 @@ func (s *Session) Get(key string, def ...interface{}) interface{} {
|
||||
|
||||
// 获取SESSION,建议都用该方法获取参数
|
||||
func (s *Session) GetVar(key string, def ...interface{}) *gvar.Var {
|
||||
return gvar.New(s.Get(key, def...))
|
||||
}
|
||||
|
||||
// 删除session
|
||||
func (s *Session) Remove(key string) {
|
||||
if len(s.id) > 0 || s.request.Cookie.GetSessionId() != "" {
|
||||
s.init()
|
||||
s.data.Remove(key)
|
||||
}
|
||||
}
|
||||
|
||||
// 清空session
|
||||
func (s *Session) Clear() {
|
||||
if len(s.id) > 0 || s.request.Cookie.GetSessionId() != "" {
|
||||
s.init()
|
||||
s.data.Clear()
|
||||
}
|
||||
}
|
||||
|
||||
// 更新过期时间(如果用在守护进程中长期使用,需要手动调用进行更新,防止超时被清除)
|
||||
func (s *Session) UpdateExpire() {
|
||||
if len(s.id) > 0 && s.data.Size() > 0 {
|
||||
s.server.sessions.Set(s.id, s.data, s.server.GetSessionMaxAge()*1000)
|
||||
}
|
||||
return gvar.New(s.Get(key, def...), true)
|
||||
}
|
||||
|
||||
func (s *Session) GetString(key string, def ...interface{}) string {
|
||||
@ -228,7 +276,34 @@ func (s *Session) GetDuration(key string, def ...interface{}) time.Duration {
|
||||
return gconv.Duration(s.Get(key, def...))
|
||||
}
|
||||
|
||||
// 将变量转换为对象,注意 pointer 参数必须为struct指针
|
||||
func (s *Session) GetMap(value interface{}, tags ...string) map[string]interface{} {
|
||||
return gconv.Map(value, tags...)
|
||||
}
|
||||
|
||||
func (s *Session) GetMapDeep(value interface{}, tags ...string) map[string]interface{} {
|
||||
return gconv.MapDeep(value, tags...)
|
||||
}
|
||||
|
||||
func (s *Session) GetMaps(value interface{}, tags ...string) []map[string]interface{} {
|
||||
return gconv.Maps(value, tags...)
|
||||
}
|
||||
|
||||
func (s *Session) GetMapsDeep(value interface{}, tags ...string) []map[string]interface{} {
|
||||
return gconv.MapsDeep(value, tags...)
|
||||
}
|
||||
|
||||
func (s *Session) GetStruct(key string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.Struct(s.Get(key), pointer, mapping...)
|
||||
}
|
||||
|
||||
func (s *Session) GetStructDeep(key string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.StructDeep(s.Get(key), pointer, mapping...)
|
||||
}
|
||||
|
||||
func (s *Session) GetStructs(key string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.Structs(s.Get(key), pointer, mapping...)
|
||||
}
|
||||
|
||||
func (s *Session) GetStructsDeep(key string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.StructsDeep(s.Get(key), pointer, mapping...)
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ var serverMapping = gmap.NewStrAnyMap(true)
|
||||
// The parameter <name> is used to specify the TCP server
|
||||
func GetServer(name ...interface{}) *Server {
|
||||
serverName := gDEFAULT_SERVER
|
||||
if len(name) > 0 {
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
serverName = gconv.String(name[0])
|
||||
}
|
||||
return serverMapping.GetOrSetFuncLock(serverName, func() interface{} {
|
||||
|
||||
@ -32,7 +32,7 @@ var serverMapping = gmap.NewStrAnyMap(true)
|
||||
// 单例模式,请保证name的唯一性
|
||||
func GetServer(name ...interface{}) *Server {
|
||||
serverName := gDEFAULT_SERVER
|
||||
if len(name) > 0 {
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
serverName = gconv.String(name[0])
|
||||
}
|
||||
if s := serverMapping.Get(serverName); s != nil {
|
||||
|
||||
@ -10,104 +10,70 @@ package gcache_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/os/gcache"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
c = gcache.New()
|
||||
clru = gcache.New(10000)
|
||||
mInt = make(map[int]int)
|
||||
mMap = make(map[interface{}]interface{})
|
||||
|
||||
muInt = sync.RWMutex{}
|
||||
muMap = sync.RWMutex{}
|
||||
cache = gcache.New()
|
||||
cacheLru = gcache.New(10000)
|
||||
)
|
||||
|
||||
func Benchmark_CacheSet(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.Set(i, i, 0)
|
||||
}
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
i := 0
|
||||
for pb.Next() {
|
||||
cache.Set(i, i, 0)
|
||||
i++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Benchmark_CacheGet(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.Get(i)
|
||||
}
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
i := 0
|
||||
for pb.Next() {
|
||||
cache.Get(i)
|
||||
i++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Benchmark_CacheRemove(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.Remove(i)
|
||||
}
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
i := 0
|
||||
for pb.Next() {
|
||||
cache.Remove(i)
|
||||
i++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Benchmark_CacheLruSet(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
clru.Set(i, i, 0)
|
||||
}
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
i := 0
|
||||
for pb.Next() {
|
||||
cacheLru.Set(i, i, 0)
|
||||
i++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Benchmark_CacheLruGet(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
clru.Get(i)
|
||||
}
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
i := 0
|
||||
for pb.Next() {
|
||||
cacheLru.Get(i)
|
||||
i++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Benchmark_CacheLruRemove(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
clru.Remove(i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_InterfaceMapWithLockSet(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
muMap.Lock()
|
||||
mMap[i] = i
|
||||
muMap.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_InterfaceMapWithLockGet(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
muMap.RLock()
|
||||
if _, ok := mMap[i]; ok {
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
i := 0
|
||||
for pb.Next() {
|
||||
cacheLru.Remove(i)
|
||||
i++
|
||||
}
|
||||
muMap.RUnlock()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_InterfaceMapWithLockRemove(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
muMap.Lock()
|
||||
delete(mMap, i)
|
||||
muMap.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_IntMapWithLockWithLockSet(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
muInt.Lock()
|
||||
mInt[i] = i
|
||||
muInt.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_IntMapWithLockGet(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
muInt.RLock()
|
||||
if _, ok := mInt[i]; ok {
|
||||
|
||||
}
|
||||
muInt.RUnlock()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_IntMapWithLockRemove(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
muInt.Lock()
|
||||
delete(mInt, i)
|
||||
muInt.Unlock()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ var (
|
||||
// The parameter <name> is the name for the instance.
|
||||
func Instance(name ...string) *Config {
|
||||
key := DEFAULT_GROUP_NAME
|
||||
if len(name) > 0 {
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
key = name[0]
|
||||
}
|
||||
return instances.GetOrSetFuncLock(key, func() interface{} {
|
||||
|
||||
@ -22,7 +22,7 @@ var (
|
||||
// The parameter <name> is the name for the instance.
|
||||
func Instance(name ...string) *View {
|
||||
key := DEFAULT_INSTANCE_NAME
|
||||
if len(name) > 0 {
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
key = name[0]
|
||||
}
|
||||
return instances.GetOrSetFuncLock(key, func() interface{} {
|
||||
|
||||
@ -379,40 +379,40 @@ func Interfaces(i interface{}) []interface{} {
|
||||
}
|
||||
|
||||
// Maps converts <i> to []map[string]interface{}.
|
||||
func Maps(i interface{}) []map[string]interface{} {
|
||||
if i == nil {
|
||||
func Maps(value interface{}, tags ...string) []map[string]interface{} {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
if r, ok := i.([]map[string]interface{}); ok {
|
||||
if r, ok := value.([]map[string]interface{}); ok {
|
||||
return r
|
||||
} else {
|
||||
array := Interfaces(i)
|
||||
array := Interfaces(value)
|
||||
if len(array) == 0 {
|
||||
return nil
|
||||
}
|
||||
list := make([]map[string]interface{}, len(array))
|
||||
for k, v := range array {
|
||||
list[k] = Map(v)
|
||||
list[k] = Map(v, tags...)
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
// MapsDeep converts <i> to []map[string]interface{} recursively.
|
||||
func MapsDeep(i interface{}) []map[string]interface{} {
|
||||
if i == nil {
|
||||
func MapsDeep(value interface{}, tags ...string) []map[string]interface{} {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
if r, ok := i.([]map[string]interface{}); ok {
|
||||
if r, ok := value.([]map[string]interface{}); ok {
|
||||
return r
|
||||
} else {
|
||||
array := Interfaces(i)
|
||||
array := Interfaces(value)
|
||||
if len(array) == 0 {
|
||||
return nil
|
||||
}
|
||||
list := make([]map[string]interface{}, len(array))
|
||||
for k, v := range array {
|
||||
list[k] = MapDeep(v)
|
||||
list[k] = MapDeep(v, tags...)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
2
geg/net/ghttp/server/session/config.toml
Normal file
2
geg/net/ghttp/server/session/config.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[redis]
|
||||
default = "127.0.0.1:6379,10"
|
||||
@ -22,7 +22,7 @@ func (c *Controller) DoLogin() {
|
||||
}
|
||||
|
||||
func (c *Controller) Main() {
|
||||
c.Response.WriteJson(c.Session.Data())
|
||||
c.Response.WriteJson(c.Session.Map())
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
82
geg/net/ghttp/server/session/session_redis.go
Normal file
82
geg/net/ghttp/server/session/session_redis.go
Normal file
@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
)
|
||||
|
||||
// 测试,SESSION写入
|
||||
func SessionSet(r *ghttp.Request) {
|
||||
r.Session.Set("time", gtime.Second())
|
||||
r.Response.WriteJson("ok")
|
||||
}
|
||||
|
||||
// 测试,SESSION读取
|
||||
func SessionGet(r *ghttp.Request) {
|
||||
r.Response.WriteJson(r.Session.Map())
|
||||
}
|
||||
|
||||
// 请求处理之前将Redis中的数据读取出来并存储到SESSION对象中。
|
||||
func RedisHandlerGet(r *ghttp.Request) {
|
||||
if !r.IsFileRequest() {
|
||||
id := r.Cookie.GetSessionId()
|
||||
if id == "" {
|
||||
return
|
||||
}
|
||||
// 应用服务器一般是多个节点构成的集群,
|
||||
// 当请求中带有SESSION ID时,自动从Redis读取并恢复数据。
|
||||
value, err := g.Redis().DoVar("GET", id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !value.IsNil() {
|
||||
if err := r.Session.Restore(value.Bytes()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 请求结束时将SESSION数据存储到Redis中,或者在SESSION删除时也删除Redis中的数据。
|
||||
func RedisHandlerSet(r *ghttp.Request) {
|
||||
if !r.IsFileRequest() {
|
||||
id := r.Cookie.GetSessionId()
|
||||
if id == "" {
|
||||
return
|
||||
}
|
||||
err := (error)(nil)
|
||||
value := ([]byte)(nil)
|
||||
if r.Session.Size() > 0 {
|
||||
if value, err = r.Session.Export(); err == nil {
|
||||
if len(value) == 0 {
|
||||
return
|
||||
} else if !r.Session.IsDirty() {
|
||||
// 更新过期时间
|
||||
_, err = g.Redis().Do("EXPIRE", id, r.Server.GetSessionMaxAge())
|
||||
} else {
|
||||
// 更新Redis数据
|
||||
_, err = g.Redis().Do("SETEX", id, r.Server.GetSessionMaxAge(), value)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 清空SESSION后自动删除Redis数据
|
||||
_, err = g.Redis().Do("DEL", id)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
s := g.Server()
|
||||
s.BindHandler("/set", SessionSet)
|
||||
s.BindHandler("/get", SessionGet)
|
||||
s.BindHookHandlerByMap("/*", map[string]ghttp.HandlerFunc{
|
||||
ghttp.HOOK_BEFORE_SERVE: RedisHandlerGet,
|
||||
ghttp.HOOK_AFTER_SERVE: RedisHandlerSet,
|
||||
})
|
||||
s.SetPort(8199)
|
||||
s.Run()
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package gf
|
||||
|
||||
const VERSION = "v1.8.2"
|
||||
const VERSION = "v1.8.3"
|
||||
const AUTHORS = "john<john@goframe.org>"
|
||||
|
||||
Reference in New Issue
Block a user