九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Session原理和Tomcat實(shí)現(xiàn)分析
這篇文章挖掘Session的原理和tomcat實(shí)現(xiàn)機(jī)制。
由于HTTP是無(wú)狀態(tài)的協(xié)議,客戶程序每次都去web頁(yè)面,都打開到web服務(wù)器的單獨(dú)的連接,并且不維護(hù)客戶的上下文信息。如果需要維護(hù)上下文信息,比如用戶登錄系統(tǒng)后,每次都能夠知道操作的是此登錄用戶,而不是其他用戶。對(duì)于這個(gè)問(wèn)題,存在三種解決方案:cookie,url重寫和隱藏表單域。
1、cookie
cookie是一個(gè)服務(wù)器和客戶端相結(jié)合的技術(shù),服務(wù)器可以將會(huì)話ID發(fā)送到瀏覽器,瀏覽器將此cookie信息保存起來(lái),后面再訪問(wèn)網(wǎng)頁(yè)時(shí),服務(wù)器又能夠從瀏覽器中讀到此會(huì)話ID,通過(guò)這種方式判斷是否是同一用戶。
1 請(qǐng)求:
2 POST /ibsm/LoginAction.do HTTP/1.1
3 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
4 Referer: http://192.168.1.20:8080/crm/
5 Accept-Language: zh-cn
6 Content-Type: application/x-www-form-urlencoded
7 UA-CPU: x86
8 Accept-Encoding: gzip, deflate
9 User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)
10 Host: 192.168.1.20:8080
11 Content-Length: 13
12 Connection: Keep-Alive
13 Cache-Control: no-cache
14
15 username=jack
16
17 響應(yīng):
18 HTTP/1.1 200 OK
19 Server: Apache-Coyote/1.1
20 Set-Cookie: JSESSIONID=3267A671BFEAA147A2383B7E083D4G7E; Path=/crm
21 Content-Type: text/html;charset=GBK
22 Content-Length: 436
23 Date: Sat, 10 June 2009 12:43:26 GMT
生成響應(yīng)的時(shí)候,服務(wù)器向客戶端發(fā)送cookie。cookie的屬性是JSESSIONID,值是267A671BFEAA147A2383B7E083D4G7E。以后每次客戶端請(qǐng)求時(shí),都會(huì)附上此cookie,服務(wù)器端就可以讀取到。
1    1. GET /ibsm/ApplicationFrame.frame HTTP/1.1
2    2. Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
3    3. Accept-Language: zh-cn
4    4. UA-CPU: x86
5    5. Accept-Encoding: gzip, deflate
6    6. User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)
7    7. Host: 192.168.1.20:8080
8    8. Connection: Keep-Alive
9    9. Cookie: JSESSIONID=267A671BFEAA147A2383B7E083D4G7E
服務(wù)器端根據(jù)讀取到的JSESSIONID,在一個(gè)map里面查找其對(duì)應(yīng)的session對(duì)象,這個(gè)map的key是jsessionid的值,value是session對(duì)象。
2、URL重寫
重寫這種方式,客戶端程序在每個(gè)URL的尾部自動(dòng)添加一些額外數(shù)據(jù),這些數(shù)據(jù)以表示這個(gè)會(huì)話,比如
http://192.168.1.20:8080/crm/getuserprofile.html;jsessionid=abc123。URL重寫的額外數(shù)據(jù)是服務(wù)器自動(dòng)添加的,那么服務(wù)器是怎么添加的呢?Tomcat在返回Response的時(shí)候,檢查JSP頁(yè)面中所有的URL,包括所有的鏈接,和 Form的Action屬性,在這些URL后面加上“;jsessionid=xxxxxx”。 添加url后綴的代碼片段如下:
org.apache.coyote.tomcat5.CoyoteResponse類的toEncoded()方法支持URL重寫。
1 StringBuffer sb = new StringBuffer(path);
2         if( sb.length() > 0 ) { // jsessionid can't be first.
3             sb.append(";jsessionid=");
4             sb.append(sessionId);
5         }
6         sb.append(anchor);
7         sb.append(query);
8         return (sb.toString());
從上面URL的實(shí)現(xiàn)原理可知,URL重寫有一個(gè)缺點(diǎn):在你的站點(diǎn)上不能有任何靜態(tài)的HTML頁(yè)面(至少靜態(tài)頁(yè)面中不能有任何鏈接到站點(diǎn)動(dòng)態(tài)頁(yè)面的鏈接)。因此,每個(gè)頁(yè)面都必須使用servlet或 JSP動(dòng)態(tài)生成。即使所有的頁(yè)面都動(dòng)態(tài)生成,如果用戶離開了會(huì)話并通過(guò)書簽或鏈接再次回來(lái),會(huì)話的信息都會(huì)丟失,因?yàn)榇鎯?chǔ)下來(lái)的鏈接含有錯(cuò)誤的標(biāo)識(shí)信息- 該URL后面的SESSION ID已經(jīng)過(guò)期了。
3、隱藏表單域
這種方式借助html表單中的hidden來(lái)實(shí)現(xiàn),適用特定的一個(gè)流程,但是不適用于通常意義的會(huì)話跟蹤。
綜上所述,session實(shí)現(xiàn)會(huì)話跟蹤通常是cookie和url重寫,如果瀏覽器不禁止cookie的話,tomcat優(yōu)先使用cookie實(shí)現(xiàn)。
服務(wù)器端實(shí)現(xiàn)原理
Session在服務(wù)器端具體是怎么實(shí)現(xiàn)的呢?我們使用session的時(shí)候一般都是這么使用的:
request.getSession()或者request.getSession(true)。
這個(gè)時(shí)候,服務(wù)器就檢查是不是已經(jīng)存在對(duì)應(yīng)的Session對(duì)象,見(jiàn)HttpRequestBase類
doGetSession(boolean create)方法:
1  if ((session != null) && !session.isValid())
2             session = null;
3         if (session != null)
4             return (session.getSession());
5
6
7         // Return the requested session if it exists and is valid
8         Manager manager = null;
9         if (context != null)
10             manager = context.getManager();
11         if (manager == null)
12             return (null);      // Sessions are not supported
13         if (requestedSessionId != null) {
14             try {
15                 session = manager.findSession(requestedSessionId);
16             } catch (IOException e) {
17                 session = null;
18             }
19             if ((session != null) && !session.isValid())
20                 session = null;
21             if (session != null) {
22                 return (session.getSession());
23             }
24         }
requestSessionId從哪里來(lái)呢?這個(gè)肯定是通過(guò)Session實(shí)現(xiàn)機(jī)制的cookie或URL重寫來(lái)設(shè)置的。見(jiàn)HttpProcessor類中的parseHeaders(SocketInputStream input):
1 for (int i = 0; i < cookies.length; i++) {
2                     if (cookies[i].getName().equals
3                         (Globals.SESSION_COOKIE_NAME)) {
4                         // Override anything requested in the URL
5                         if (!request.isRequestedSessionIdFromCookie()) {
6                             // Accept only the first session id cookie
7                             request.setRequestedSessionId
8                                 (cookies[i].getValue());
9                             request.setRequestedSessionCookie(true);
10                             request.setRequestedSessionURL(false);
11
12                         }
13                     }
14 }
或者HttpOrocessor類中的parseRequest(SocketInputStream input, OutputStream output)
1 // Parse any requested session ID out of the request URI
2         int semicolon = uri.indexOf(match);  //match 是";jsessionid="字符串
3         if (semicolon >= 0) {
4             String rest = uri.substring(semicolon + match.length());
5             int semicolon2 = rest.indexOf(';');
6             if (semicolon2 >= 0) {
7                 request.setRequestedSessionId(rest.substring(0, semicolon2));
8                 rest = rest.substring(semicolon2);
9             } else {
10                 request.setRequestedSessionId(rest);
11                 rest = "";
12             }
13             request.setRequestedSessionURL(true);
14             uri = uri.substring(0, semicolon) + rest;
15             if (debug >= 1)
16                 log(" Requested URL session id is " +
17                     ((HttpServletRequest) request.getRequest())
18                     .getRequestedSessionId());
19         } else {
20             request.setRequestedSessionId(null);
21             request.setRequestedSessionURL(false);
22         }
23
里面的manager.findSession(requestSessionId)用于查找此會(huì)話ID對(duì)應(yīng)的session對(duì)象。Tomcat實(shí)現(xiàn)
是通過(guò)一個(gè)HashMap實(shí)現(xiàn),見(jiàn)ManagerBase.java的findSession(String id):
1         if (id == null)
2             return (null);
3         synchronized (sessions) {
4             Session session = (Session) sessions.get(id);
5             return (session);
6         }
Session本身也是實(shí)現(xiàn)為一個(gè)HashMap,因?yàn)镾ession設(shè)計(jì)為存放key-value鍵值對(duì),Tomcat里面Session實(shí)現(xiàn)類是StandardSession,里面一個(gè)attributes屬性:
1     /**
2      * The collection of user data attributes associated with this Session.
3      */
4     private HashMap attributes = new HashMap();
所有會(huì)話信息的存取都是通過(guò)這個(gè)屬性來(lái)實(shí)現(xiàn)的。Session會(huì)話信息不會(huì)一直在服務(wù)器端保存,超過(guò)一定的時(shí)間期限就會(huì)被刪除,這個(gè)時(shí)間期限可以在web.xml中進(jìn)行設(shè)置,不設(shè)置的話會(huì)有一個(gè)默認(rèn)值,Tomcat的默認(rèn)值是60。那么服務(wù)器端是怎么判斷會(huì)話過(guò)期的呢?原理服務(wù)器會(huì)啟動(dòng)一個(gè)線程,一直查詢所有的Session對(duì)象,檢查不活動(dòng)的時(shí)間是否超過(guò)設(shè)定值,如果超過(guò)就將其刪除。見(jiàn)StandardManager類,它實(shí)現(xiàn)了Runnable接口,里面的run方法如下:
1     /**
2      * The background thread that checks for session timeouts and shutdown.
3      */
4     public void run() {
5
6         // Loop until the termination semaphore is set
7         while (!threadDone) {
8             threadSleep();
9             processExpires();
10         }
11
12     }
13
14     /**
15      * Invalidate all sessions that have expired.
16      */
17     private void processExpires() {
18
19         long timeNow = System.currentTimeMillis();
20         Session sessions[] = findSessions();
21
22         for (int i = 0; i < sessions.length; i++) {
23             StandardSession session = (StandardSession) sessions[i];
24             if (!session.isValid())
25                 continue;
26             int maxInactiveInterval = session.getMaxInactiveInterval();
27             if (maxInactiveInterval < 0)
28                 continue;
29             int timeIdle = // Truncate, do not round up
30                 (int) ((timeNow - session.getLastUsedTime()) / 1000L);
31             if (timeIdle >= maxInactiveInterval) {
32                 try {
33                     expiredSessions++;
34                     session.expire();
35                 } catch (Throwable t) {
36                     log(sm.getString("standardManager.expireException"), t);
37                 }
38             }
39         }
40
41     }
Session信息在create,expire等事情的時(shí)候都會(huì)觸發(fā)相應(yīng)的Listener事件,從而可以對(duì)session信息進(jìn)行監(jiān)控,這些Listener只需要繼承HttpSessionListener,并配置在web.xml文件中。如下是一個(gè)監(jiān)控在線會(huì)話數(shù)的Listerner:
import java.util.HashSet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MySessionListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext();
// 在application范圍由一個(gè)HashSet集保存所有的session
HashSet sessions = (HashSet) application.getAttribute("sessions");
if (sessions == null) {
sessions = new HashSet();
application.setAttribute("sessions", sessions);
}
// 新創(chuàng)建的session均添加到HashSet集中
sessions.add(session);
// 可以在別處從application范圍中取出sessions集合
// 然后使用sessions.size()獲取當(dāng)前活動(dòng)的session數(shù),即為“在線人數(shù)”
}
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
ServletContext application = session.getServletContext();
HashSet sessions = (HashSet) application.getAttribute("sessions");
// 銷毀的session均從HashSet集中移除
sessions.remove(session);
}
}
以上就是我對(duì)session的研究,后面還會(huì)對(duì)session擴(kuò)展和跨應(yīng)用session共享等進(jìn)行進(jìn)一步的研究。本文系原創(chuàng),轉(zhuǎn)載請(qǐng)標(biāo)明來(lái)源。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Load-balancing Tomcat with Apache
session功能實(shí)現(xiàn)原理
Tomcat中的Session小結(jié)
Web項(xiàng)目答辯問(wèn)題
Tomcat禁用cookie時(shí)沒(méi)有自動(dòng)URL rewriting,沒(méi)有加上jsessionid?
jsp/servlet 深入解析session本質(zhì)
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服