淺入深出Session

在難也要學(xué)完《深入分析的Java Web》的深入理解Session與Cookie,斷斷續(xù)續(xù)花了三四天的時(shí)間在學(xué)習(xí)這塊內(nèi)容,好難啊,但還是得逼自己學(xué)完,不想一直掉坑里
記錄一下學(xué)習(xí)內(nèi)容,這樣哪天忘記了又能重新拾起來

(一)淺入部分:方法使用介紹
1.Session創(chuàng)建的時(shí)間:客戶端第一次請(qǐng)求服務(wù)器的時(shí)候創(chuàng)建的。
通過request.getSession()可以獲得對(duì)應(yīng)的session對(duì)象(返回類型為HttpSession),不存在將返回null。調(diào)用request.getSession(true),如果該客戶的session不存在,將先創(chuàng)建session對(duì)象,在返回session。
測(cè)試代碼:SessionTest.java

public class SessionTest extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        String id = session.getId();
        System.out.println("session_id: " + id);
    }
}

運(yùn)行結(jié)果:

session_id: BE37D76B19597F991999F482A0A6F9BD

說明在客戶端第一次請(qǐng)求時(shí)就創(chuàng)建了session對(duì)象,并且這個(gè)過程對(duì)我們來說是透明的。
注:獲取session時(shí)只需調(diào)用getSession()方法就可以了,不需要指定是哪個(gè)客戶端的session。session的機(jī)制決定了當(dāng)前客戶只會(huì)獲得自己的session,而不會(huì)獲得別人的session。各客戶的session互相獨(dú)立、互不可見

2.session的生命周期
tomcat8中默認(rèn)session的生命周期為30min

  <!-- ==================== Default Session Configuration ================= -->
  <!-- You can set the default session timeout (in minutes) for all newly   -->
  <!-- created sessions by modifying the value below.                       -->

    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>

session的生命周期沒有cookie長(zhǎng)是有原因的,cookie保存在瀏覽器中一般是永久的。session就不一樣了,為了獲得更高的緩存速度,服務(wù)器一般把session保存在內(nèi)存中,但是,如果網(wǎng)站是高并發(fā)的,并且session保存的內(nèi)容很多,就會(huì)造成內(nèi)存溢出,所以需要定期清除那些不常用的session,通過設(shè)置一個(gè)時(shí)間,時(shí)間不可以太長(zhǎng),超時(shí)清理,緩減內(nèi)存壓力。如果自己需要更改sessiond的生命周期,有兩種方式可以修改
1)tomcat web.xml文件中進(jìn)行修改
2)調(diào)用setMaxInactiveInterval(int i)方法進(jìn)行修改
注意web.xml中時(shí)間的單位為小時(shí),setMaxInactiveInterval(int i)方法中時(shí)間的單位為秒

3.session對(duì)瀏覽器的要求
session需要依賴cookie,服務(wù)器生成session時(shí)會(huì)生成一個(gè)name為jsessionid的cookie,值為session的id(即HttpSession.getId()的返回值),session通過cookie來識(shí)別是否為同一個(gè)用戶。服務(wù)器自動(dòng)生成的cookie,maxAge屬性一般為-1,僅在當(dāng)前瀏覽器內(nèi)的當(dāng)前窗口有效,關(guān)閉瀏覽器就會(huì)失效。如果瀏覽器禁用cookie或不支持cookie,就需要使用url地址重寫 。
url地址重寫原理:將該用戶的session的id信息重寫到url地址中。服務(wù)器能夠解析重寫后的url獲取session的id。這樣就可以不需要使用cookie記錄session的id了。
測(cè)試代碼:SessionTest.java

public class SessionTest extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("進(jìn)入SessionTest方法體內(nèi)");
        HttpSession session = request.getSession();
        String id = session.getId();
        System.out.println("session_id: " + id);
        Cookie[] cookies = request.getCookies();

        System.out.println("size: " + cookies.length);

        if (cookies.length != 0) {
            for (Cookie c : cookies) {
                System.out.println("name: " + c.getName() + "  value: " + c.getValue());
            }

        }
//        response.sendRedirect("/cookie_message");
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

運(yùn)行結(jié)果:

進(jìn)入SessionTest方法體內(nèi)
session_id: 5748CB766C7130F80F259E72A5637920
進(jìn)入SessionTest方法體內(nèi)
session_id: 5748CB766C7130F80F259E72A5637920
size: 1
name: JSESSIONID  value: 5748CB766C7130F80F259E72A5637920

先清理一下瀏覽器緩存,第一次進(jìn)入方法體時(shí)會(huì)報(bào)500空指針異常
報(bào)空指針異常的原因是此時(shí)request.getCookies()沒有結(jié)果,第二次繼續(xù)調(diào)用方法時(shí)才成功,從結(jié)果中看出確實(shí)生成一個(gè)name為JSESSIONID ,值為session id的cookie。
思考了一下出錯(cuò)原因:客戶端第一次請(qǐng)求服務(wù)器時(shí)生成一個(gè)session,同時(shí)生成了一個(gè)cookie,但這次生成的cookie要通過服務(wù)器的響應(yīng)以后才能返回給客戶端,所以第一次取不到想要的cookie。
禁用cookie后,因?yàn)樵趖omcat配置文件中禁用cookie沒有效果,直接禁用了瀏覽器


禁用cookie

原來的程序運(yùn)行結(jié)果:

進(jìn)入SessionTest方法體內(nèi)
session_id: 39385CEDA231B7DDBC1A42C9BBB6EC92
進(jìn)入SessionTest方法體內(nèi)
session_id: 31E06944B9086767087BCF32E9A5D273
進(jìn)入SessionTest方法體內(nèi)
session_id: A796BD79458635C4C117198B09C9269C
進(jìn)入SessionTest方法體內(nèi)
session_id: 31D60D8791F88E7D28E567A085D3BFCC

一直報(bào)500空指針的錯(cuò)誤,也就是說明沒有cookie
那就使用url重寫

修改一下上面的代碼:

public class SessionTest extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("進(jìn)入SessionTest方法體內(nèi)");
        HttpSession session = request.getSession();
        String id = session.getId();
        System.out.println("session_id: " + id);
        response.sendRedirect(response.encodeRedirectURL("/cookie_message"));
    }
 
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

url地址欄變?yōu)榱耍?br> http://localhost:8080/cookie_message;jsessionid=D4BCA30FE7A2E44D615DBFE04A4016A4
運(yùn)行結(jié)果:

進(jìn)入SessionTest方法體內(nèi)
session_id: D4BCA30FE7A2E44D615DBFE04A4016A4

說明url重定向成功了,這樣服務(wù)器可以通過url來獲得session id了

(二)深出部分:session底層是如何工作的
4.session工作機(jī)制
當(dāng)客戶端和服務(wù)器建立連接時(shí)會(huì)創(chuàng)建一個(gè)session,創(chuàng)建session對(duì)象的過程大致是這樣的:
1)解析url,url中是否有session id(一般可以解析的url是重寫后的url,像這樣,http://localhost:8080/cookie_message;jsessionid=D4BCA30FE7A2E44D615DBFE04A4016A4,id則為jsessionid)
2)如果瀏覽器是支持cookie的,則從cookie中拿到session id,并覆蓋之前的session id(即url重寫中的session id)
所以客戶端支持cookie,tomcat仍然會(huì)解析cookie中的session id,然后覆蓋url中的session id
3)根據(jù)session id在manager類的session容器中查找是否存在這個(gè)id的session對(duì)象
4)如果步驟3)中查找不到這個(gè)對(duì)象,則創(chuàng)建這個(gè)id的session對(duì)象
5)將這個(gè)session對(duì)象添加到session容器中
6)根據(jù)這個(gè)id新增一個(gè)cookie,并將這個(gè)cookie設(shè)置到http協(xié)議頭中
7)通過調(diào)用request.getSession()可以獲得該對(duì)象。它的底層是通過requestedSessionId從StandardManager(Manager的實(shí)現(xiàn)類)的sessions集合中(就是之前說的容器)獲取對(duì)應(yīng)客戶的HttpSession對(duì)象

5)管理session對(duì)象的StandardManager類介紹
StandardManager類負(fù)責(zé)Servlet容器中所有session對(duì)象生命周期的管理。當(dāng)tomcat重啟或關(guān)閉時(shí),StandardManager通過序列化(調(diào)用unload方法)將沒有過期的session對(duì)象持久化到SESSIONS.ser文件中,當(dāng)tomcat重啟時(shí),即StandardManager初始化時(shí),會(huì)重新讀取這個(gè)文件,解析出所有的session對(duì)象保存到StandardManager的session集合中。注意:在重啟讀取SESSIONS.ser文件時(shí),會(huì)在一次進(jìn)行檢查session是否過期,過期就不在加載到sessions集合中了 。不正常的關(guān)閉tomcat服務(wù)器也有可能不會(huì)對(duì)session進(jìn)行持久化,因?yàn)檎{(diào)用不到unload方法
SESSIONS.ser這個(gè)文件有點(diǎn)難找,最后選擇以搜索的方式查找到了這類文件


皮皮甜電腦上的SESSIONS.ser文件查找結(jié)果

6)session過期清理
檢查session是否過期是tomcat中的一個(gè)后臺(tái)線程完成的(backgroundProcess()方法),如果過期了,則將設(shè)置Session.expire(true),否則保留session。過期了的session對(duì)象不是立刻就被清理的,tomcat使用一個(gè)1分鐘的定時(shí)任務(wù)定時(shí)清除當(dāng)前超時(shí)session對(duì)象,所以清除超時(shí)的session對(duì)象有一個(gè)小于1分鐘的延時(shí),在處理過期問題上,redis清理過期鍵的機(jī)制和它類似。如果此時(shí)expire=true,但是定時(shí)任務(wù)時(shí)間沒有到,客戶端發(fā)送request.getSession()請(qǐng)求,則這個(gè)session對(duì)象將會(huì)被立刻清理掉,不會(huì)等定時(shí)任務(wù)來清理,并創(chuàng)建一個(gè)新的session對(duì)象來響應(yīng)客戶端的請(qǐng)求

2017年最后一篇文章
繼續(xù)沉淀自己。酒越久越醇厚

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自 :http://blog.csdn.net/taoff/articles/1921009.aspx 一、術(shù)語...
    stone_yao閱讀 6,386評(píng)論 0 31
  • 轉(zhuǎn)自:http://justsee.iteye.com/blog/1570652 雖然session機(jī)制在web應(yīng)...
    Maggie編程去閱讀 537評(píng)論 0 6
  • 兩小寶哄睡著后已經(jīng)十點(diǎn)了,聽到孩子爸打呼嚕的聲音也是睡著了,可是老大還在客廳看IPAD,我心里有火氣竄出...
    ShirleyQian閱讀 227評(píng)論 0 1
  • 《品牌洗腦》 1.聰明的品牌總能找到你的弱點(diǎn),攻陷你的內(nèi)心。直到你徹底成為它的“奴隸”,還很情愿。 2.比如,連接...
    琢磨概念者閱讀 299評(píng)論 0 0
  • 感恩今日按時(shí)準(zhǔn)時(shí)收到我為幼兒園買的物品,沒有耽誤孩子們發(fā)獎(jiǎng)品,這個(gè)活動(dòng)策劃了幾天了,物品及時(shí)到達(dá)沒有讓孩子們失望,...
    念秀閱讀 162評(píng)論 0 1

友情鏈接更多精彩內(nèi)容