servlet中session的原理和使用


在WEB開(kāi)發(fā)中蹲盘,服務(wù)器可以為每個(gè)用戶瀏覽器創(chuàng)建一個(gè)會(huì)話對(duì)象(session對(duì)象)珊随,注意:一個(gè)瀏覽器獨(dú)占一個(gè)session對(duì)象(默認(rèn)情況下)。因此找岖,在需要保存用戶數(shù)據(jù)時(shí),服務(wù)器程序可以把用戶數(shù)據(jù)寫到用戶瀏覽器獨(dú)占的session中敛滋,當(dāng)用戶使用瀏覽器訪問(wèn)其它程序時(shí)许布,其它程序可以從用戶的session中取出該用戶的數(shù)據(jù),為用戶服務(wù)绎晃。


一蜜唾、Session簡(jiǎn)單介紹

在WEB開(kāi)發(fā)中杂曲,服務(wù)器可以為每個(gè)用戶瀏覽器創(chuàng)建一個(gè)會(huì)話對(duì)象(session對(duì)象),注意:一個(gè)瀏覽器獨(dú)占一個(gè)session對(duì)象(默認(rèn)情況下)袁余。因此擎勘,在需要保存用戶數(shù)據(jù)時(shí),服務(wù)器程序可以把用戶數(shù)據(jù)寫到用戶瀏覽器獨(dú)占的session中颖榜,當(dāng)用戶使用瀏覽器訪問(wèn)其它程序時(shí)棚饵,其它程序可以從用戶的session中取出該用戶的數(shù)據(jù),為用戶服務(wù)掩完。

二噪漾、Session和Cookie的主要區(qū)別

Cookie是把用戶的數(shù)據(jù)寫給用戶的瀏覽器。
Session技術(shù)把用戶的數(shù)據(jù)寫到用戶獨(dú)占的session中且蓬。
Session對(duì)象由服務(wù)器創(chuàng)建欣硼,開(kāi)發(fā)人員可以調(diào)用request對(duì)象的getSession方法得到session對(duì)象。

三缅疟、session實(shí)現(xiàn)原理

3.1分别、服務(wù)器是如何實(shí)現(xiàn)一個(gè)session為一個(gè)用戶瀏覽器服務(wù)的?

服務(wù)器創(chuàng)建session出來(lái)后存淫,會(huì)把session的id號(hào)耘斩,以cookie的形式回寫給客戶機(jī),這樣桅咆,只要客戶機(jī)的瀏覽器不關(guān)括授,再去訪問(wèn)服務(wù)器時(shí),都會(huì)帶著session的id號(hào)去岩饼,服務(wù)器發(fā)現(xiàn)客戶機(jī)瀏覽器帶session id過(guò)來(lái)了荚虚,就會(huì)使用內(nèi)存中與之對(duì)應(yīng)的session為之服務(wù)。

可以用如下的代碼證明:

第一次訪問(wèn)時(shí)籍茧,服務(wù)器會(huì)創(chuàng)建一個(gè)新的sesion版述,并且把session的Id以cookie的形式發(fā)送給客戶端瀏覽器,點(diǎn)擊刷新按鈕寞冯,再次請(qǐng)求服務(wù)器渴析,此時(shí)就可以看到瀏覽器再請(qǐng)求服務(wù)器時(shí),會(huì)把存儲(chǔ)到cookie中的session的Id一起傳遞到服務(wù)器端了

request.getSession()方法內(nèi)部新創(chuàng)建了Session之后一定是做了如下的處理:

//獲取session的Id
String sessionId = session.getId();
//將session的Id存儲(chǔ)到名字為JSESSIONID的cookie中
Cookie cookie = new Cookie("JSESSIONID", sessionId);
//設(shè)置cookie的有效路徑
cookie.setPath(request.getContextPath());
response.addCookie(cookie);

四吮龄、瀏覽器禁用Cookie后的session處理

4.1俭茧、解決方案:URL重寫

response.encodeRedirectURL(java.lang.String url) 用于對(duì)sendRedirect方法后的url地址進(jìn)行重寫。
response.encodeURL(java.lang.String url)用于對(duì)表單action和超鏈接的url地址進(jìn)行重寫

4.2漓帚、范例:禁用Cookie后servlet共享Session中的數(shù)據(jù)

IndexServlet:

package xdp.gacl.session;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//首頁(yè):列出所有書
public class IndexServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        //創(chuàng)建Session
        request.getSession();
        out.write("本網(wǎng)站有如下書:<br/>");
        Set<Map.Entry<String,Book>> set = DB.getAll().entrySet();
        for(Map.Entry<String,Book> me : set){
            Book book = me.getValue();
            String url =request.getContextPath()+ "/servlet/BuyServlet?id=" + book.getId();
            //response. encodeURL(java.lang.String url)用于對(duì)表單action和超鏈接的url地址進(jìn)行重寫
            url = response.encodeURL(url);//將超鏈接的url地址進(jìn)行重寫
            out.println(book.getName()  + "   <a href='"+url+"'>購(gòu)買</a><br/>");
        }
    }

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


/**
 * @author gacl
 * 模擬數(shù)據(jù)庫(kù)
 */
class DB{
    private static Map<String,Book> map = new LinkedHashMap<String,Book>();
    static{
        map.put("1", new Book("1","javaweb開(kāi)發(fā)"));
        map.put("2", new Book("2","spring開(kāi)發(fā)"));
        map.put("3", new Book("3","hibernate開(kāi)發(fā)"));
        map.put("4", new Book("4","struts開(kāi)發(fā)"));
        map.put("5", new Book("5","ajax開(kāi)發(fā)"));
    }
    
    public static Map<String,Book> getAll(){
        return map;
    }
}

class Book{
    
    private String id;
    private String name;

    public Book() {
        super();
    }
    public Book(String id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

BuyServlet:

package xdp.gacl.session;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class BuyServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String id = request.getParameter("id");
        Book book = DB.getAll().get(id);  //得到用戶想買的書
        HttpSession session = request.getSession();
        List<Book> list = (List) session.getAttribute("list");  //得到用戶用于保存所有書的容器
        if(list==null){
            list = new ArrayList<Book>();
            session.setAttribute("list", list);
        }
        list.add(book);
        //response. encodeRedirectURL(java.lang.String url)用于對(duì)sendRedirect方法后的url地址進(jìn)行重寫
        String url = response.encodeRedirectURL(request.getContextPath()+"/servlet/ListCartServlet");
        System.out.println(url);
        response.sendRedirect(url);
    }

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

}   

ListCartServlet:

package xdp.gacl.session;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class ListCartServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        HttpSession session = request.getSession();
        List<Book> list = (List) session.getAttribute("list");
        if(list==null || list.size()==0){
            out.write("對(duì)不起母债,您還沒(méi)有購(gòu)買任何商品!!");
            return;
        }
        
        //顯示用戶買過(guò)的商品
        out.write("您買過(guò)如下商品:<br>");
        for(Book book : list){
            out.write(book.getName() + "<br/>");
        }
    }

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

當(dāng)瀏覽器禁用了cookie后,就可以用URL重寫這種解決方案解決Session數(shù)據(jù)共享問(wèn)題。而且response. encodeRedirectURL(java.lang.String url) 和response. encodeURL(java.lang.String url)是兩個(gè)非常智能的方法毡们,當(dāng)檢測(cè)到瀏覽器沒(méi)有禁用cookie時(shí)迅皇,那么就不進(jìn)行URL重寫了。

五衙熔、session對(duì)象的創(chuàng)建和銷毀時(shí)機(jī)

5.1喧半、session對(duì)象的創(chuàng)建時(shí)機(jī)

在程序中第一次調(diào)用request.getSession()方法時(shí)就會(huì)創(chuàng)建一個(gè)新的Session,可以用isNew()方法來(lái)判斷Session是不是新創(chuàng)建的

范例:創(chuàng)建session

//使用request對(duì)象的getSession()獲取session青责,如果session不存在則創(chuàng)建一個(gè)
HttpSession session = request.getSession();
//獲取session的Id
String sessionId = session.getId();
//判斷session是不是新創(chuàng)建的
if (session.isNew()) {
    response.getWriter().print("session創(chuàng)建成功,session的id是:"+sessionId);
}else {
    response.getWriter().print("服務(wù)器已經(jīng)存在session取具,session的id是:"+sessionId);
}

5.2脖隶、session對(duì)象的銷毀時(shí)機(jī)

session對(duì)象默認(rèn)30分鐘沒(méi)有使用,則服務(wù)器會(huì)自動(dòng)銷毀session暇检,在web.xml文件中可以手工配置session的失效時(shí)間产阱,例如:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name>
  
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <!-- 設(shè)置Session的有效時(shí)間:以分鐘為單位-->
    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>

</web-app>

5.3手動(dòng)銷毀session

當(dāng)需要在程序中手動(dòng)設(shè)置Session失效時(shí),可以手工調(diào)用session.invalidate方法块仆,摧毀session构蹬。

HttpSession session = request.getSession();
//手工調(diào)用session.invalidate方法,摧毀session
session.invalidate();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末悔据,一起剝皮案震驚了整個(gè)濱河市庄敛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌科汗,老刑警劉巖藻烤,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異头滔,居然都是意外死亡怖亭,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門坤检,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)兴猩,“玉大人,你說(shuō)我怎么就攤上這事早歇∏阒ィ” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵缺前,是天一觀的道長(zhǎng)蛀醉。 經(jīng)常有香客問(wèn)我,道長(zhǎng)衅码,這世上最難降的妖魔是什么拯刁? 我笑而不...
    開(kāi)封第一講書人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮逝段,結(jié)果婚禮上垛玻,老公的妹妹穿的比我還像新娘割捅。我一直安慰自己,他們只是感情好帚桩,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布亿驾。 她就那樣靜靜地躺著,像睡著了一般账嚎。 火紅的嫁衣襯著肌膚如雪莫瞬。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 50,021評(píng)論 1 291
  • 那天郭蕉,我揣著相機(jī)與錄音疼邀,去河邊找鬼。 笑死召锈,一個(gè)胖子當(dāng)著我的面吹牛旁振,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播涨岁,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拐袜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了梢薪?” 一聲冷哼從身側(cè)響起蹬铺,我...
    開(kāi)封第一講書人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎秉撇,沒(méi)想到半個(gè)月后丛塌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡畜疾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年赴邻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啡捶。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姥敛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瞎暑,到底是詐尸還是另有隱情彤敛,我是刑警寧澤,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布了赌,位于F島的核電站墨榄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏勿她。R本人自食惡果不足惜袄秩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧之剧,春花似錦郭卫、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蟹肘,卻和暖如春词疼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背帘腹。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工寒跳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人竹椒。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像米辐,于是被迫代替她去往敵國(guó)和親胸完。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容