@@ -28,36 +28,115 @@ session的基本原理是服务端为每一个session维护一份会话信息数
2828我们就来定义一个全局的session管理器
2929
3030	type SessionManager struct { 
31- 		CookieName     string 
32- 		lock          sync.Mutex 
33- 		sessions      map[string]map[string]interface{}  
34- 		list 		  list.List 
31+ 		cookieName     string       //识别cookie  
32+ 		lock          sync.Mutex   //用来锁  
33+ 		sessions      map[string]*session //用来存储  
34+ 		list 		  * list.List //用来做gc  
3535	} 
3636
37- Go实现整个的流程应该也是这样的,创建一个全部的session管理器 
37+ Go实现整个的流程应该也是这样的,在main包中创建一个全部的session管理器 
3838
39- 	globalSessions = NewSessions() 
39+ 	var globalSessions *SessionManager 
40+ 	//然后在init函数中初始化 
41+ 	func init() { 
42+ 		globalSessions = NewSessions() 
43+ 	} 
44+ 
45+ 接下来的例子中创建的session都是放在内存里面的,当然也可以放在存储中,这个后面会详细的讲解。
4046
41- 我们接下来的例子创建的session放在内存里面,当然也可以放在存储中,这个后面会详细的讲解。
47+ 接下来我们来定义针对每个用户的session对象
48+ 
49+ 	type session strcut{ 
50+ 		sid	string     //session id唯一标示 
51+ 		timeAccessed  time.Time    //最后访问时间 
52+ 		value	map[string]interface{}	   //session里面存储的值 
53+ 	} 
4254
4355###创建
4456首先我们要产生一个唯一的sessionid
4557
46- 	func sessionId() string { 
58+ 	func (this *SessionManager)  sessionId() string { 
4759		var n int = 24 
4860		b := make([]byte, n) 
4961		io.ReadFull(rand.Reader, b) 
5062		return base64.URLEncoding.EncodeToString(b) 
5163	} 
5264
53- 那么这个sessionid什么时候创建呢?	
65+ 那么这个sessionid什么时候创建呢?我们在启动我们的处理器的时候来进行session的创建,这里我继续前面表单处理的例子说明:
66+ 
67+ 	func login(w http.ResponseWriter, r *http.Request) { 
68+ 		 
69+     	fmt.Println("method:", r.Method) //获取请求的方法 
70+     	if r.Method == "GET" { 
71+     	    t, _ := template.ParseFiles("login.gtpl") 
72+     	    t.Execute(w, nil) 
73+     	} else { 
74+     	    //请求的是登陆数据,那么执行登陆的逻辑判断 
75+     	    fmt.Println("username:", r.Form["username"]) 
76+     	    fmt.Println("password:", r.Form["password"]) 
77+     	} 
78+ 	} 
79+ 	
80+ 	//开始一个新的sessionid 
81+ 	//先通过cookiename查询是否已经中了sessionid,然后查找这个sessionid是否还在sessions里面 
82+ 	//如果还在那么就更新timeAccessed,如果不存在就addnew一个 
83+ 	func (this *SessionManager) SessionStart() { 
84+ 		 
85+ 	} 
86+ 	
87+ 	//销毁当前sessionid 
88+ 	func (this *SessionManager) SessionDestroy() { 
89+ 		 
90+ 	}	 
91+ 	
92+ 	//新增一个session 
93+ 	func (this *SessionManager) AddNew(key string, value map[string]interface{}) { 
94+ 		newsid :=this.sessionId() 
95+ 		newsess:=&session{"sid":newsid,"timeAccessed":time.Now(),"value":value} 
96+ 		this.sessions[key]=newsess 
97+ 		this.list.Push(newsess) 
98+ 	} 
5499
55100###保持
56101
57- ###设置值
102+ 
103+ ###操作值:设置、读取和删除
104+ session对象需要有设置和删除操作
105+ 
106+ 	func (this *session) Set(key string, value interface{}){ 
107+ 	
108+ 	} 
109+ 	
110+ 	func (this *session) Get(key string){ 
111+ 	
112+ 	} 
113+ 	
114+ 	func (this *session) Del(key string){ 
115+ 	
116+ 	} 
117+ 	
118+ 当我们设置完值之后需要去更新相应的sessionmanager里面的值
119+ 
120+ 	func (this *SessionManager) update(element *list.Element, value map[string]interface{}) { 
121+ 		this.lock.Lock() 
122+ 		defer this.lock.Unlock() 
123+ 		element.Value.(*session).value = value 
124+ 		this.moveToFront(element) 
125+ 	} 
126+ 
127+ ###如何实时更新时间
128+ 我们的session是有一定的时间限制的,那么如果用户一直在访问页面,那么我们需要实时的去更新这个时间,如何来做这一步呢?请看下面的函数处理
129+ 
130+ 	func (this *SessionManager) moveToFront(element *list.Element) { 
131+ 		this.lock.Lock() 
132+ 		defer this.lock.Unlock() 
133+ 		this.list.MoveToFront(element) 
134+ 		element.Value.(*session).timeAccessed = time.Now() 
135+ 	} 
136+ 	
58137
59138###销毁
60- 我们来看一下Go如何来管理销毁
139+ 我们来看一下Go如何来管理销毁,我们启动一个单独的goroutine来做session的销毁: 
61140
62141	func GC() { 
63142		for true { 
@@ -71,6 +150,26 @@ Go实现整个的流程应该也是这样的,创建一个全部的session管
71150	} 
72151
73152
153+ 	func (this *SessionManager) gc() { 
154+ 		this.lock.Lock() 
155+ 		defer this.lock.Unlock() 
156+ 		var expire int64 = 60 * 15 // 15 minutes 
157+ 		// back to front 
158+ 		for { 
159+ 			element := this.list.Back() 
160+ 			if element == nil { 
161+ 				break 
162+ 			} 
163+ 			if (element.Value.(*session).timeAccessed.Unix() + expire) < time.Now().Unix() { 
164+ 				this.list.Remove(element) 
165+ 				delete(this.table, element.Value.(*session).sid) 
166+ 			} else { 
167+ 				break 
168+ 			} 
169+ 		} 
170+ 	} 
171+ 
172+ 
74173
75174##总结
76175
0 commit comments