session是服務(wù)器端技術(shù),利用這個(gè)技術(shù),服務(wù)器在運(yùn)行時(shí)可以為每一個(gè)用戶(hù)的瀏覽器創(chuàng)建一個(gè)其獨(dú)享的session對(duì)象,注意是默認(rèn)情況下,一個(gè)瀏覽器獨(dú)占一個(gè)session,由于session為用戶(hù)瀏覽器獨(dú)享,所以用戶(hù)在訪問(wèn)服務(wù)器的web資源時(shí),可以把各自數(shù)據(jù)存放在各自的session中,當(dāng)用戶(hù)再去訪問(wèn)服務(wù)器的其他web資源時(shí),其他web資源再?gòu)挠脩?hù)各自的session中取出數(shù)據(jù)為用戶(hù)服務(wù)。
session和cookie的主要區(qū)別:
cookie技術(shù)是客戶(hù)端技術(shù),是由服務(wù)器將用戶(hù)的數(shù)據(jù)寫(xiě)回給用戶(hù)瀏覽器的。
session技術(shù)是服務(wù)器端技術(shù),是把用戶(hù)的數(shù)據(jù)寫(xiě)到服務(wù)器為用戶(hù)所創(chuàng)建的獨(dú)享的session對(duì)象中,但session是基于cookie的。
session對(duì)象由服務(wù)器創(chuàng)建,這跟cookie不一樣。編程人員可以通過(guò)request請(qǐng)求對(duì)象的getsession()方法獲取session對(duì)象。
注意,session一旦創(chuàng)建,是會(huì)存活無(wú)操作情況(或者瀏覽器關(guān)閉)下30分鐘,這是由服務(wù)器(如tomcat)來(lái)指定的。當(dāng)我們關(guān)閉瀏覽器后,因?yàn)閟ession是基于cookie的,因此session是存在的,只是我們可能無(wú)法再使用到(要看cookie是否還能取到)。
那么我們以一個(gè)簡(jiǎn)單的session例子來(lái)說(shuō)明,創(chuàng)建兩個(gè)servlet:分別命名為servletdemo1和servletdemo2。
在servletdemo1中的代碼如下:
1
2
3
|
httpsession session = request.getsession(); string data = "message form sessiondemo" ; session.setattribute( "data" , data); |
在servletdemo2中的代碼如下:
1
2
3
4
5
6
|
response.setcontenttype( "text/html;charset=utf-8" ); printwriter writer = response.getwriter(); httpsession session = request.getsession(); string data = (string) session.getattribute( "data" ); writer.write(data); |
當(dāng)我們打開(kāi)一個(gè)瀏覽器先訪問(wèn)servletdemo1,此時(shí)瀏覽器會(huì)幫我們創(chuàng)建session對(duì)象,并保存數(shù)據(jù),這時(shí)再訪問(wèn)servletdemo2可以看到該保存的數(shù)據(jù):
說(shuō)明session確實(shí)能保存訪問(wèn)不同servlet時(shí)的數(shù)據(jù)。
這里說(shuō)清楚一點(diǎn),雖然代碼都是相同的,但是針對(duì)不同瀏覽器訪問(wèn)的話看到的是不同的session對(duì)象保存的不同的數(shù)據(jù),雖然這時(shí)候數(shù)據(jù)都是一樣的。比如說(shuō)a在自己主機(jī)上訪問(wèn)這個(gè)servlet和b在自己電腦上訪問(wèn)這個(gè)相同的servlet,a和b得到各自的session。
而如果我們打開(kāi)一個(gè)瀏覽器訪問(wèn)servletdemo1后,再打開(kāi)另一個(gè)瀏覽器訪問(wèn)servletdemo2,那么則會(huì)顯示該數(shù)據(jù)找不到:
注意:這時(shí)候是兩個(gè)瀏覽器,即已經(jīng)是兩個(gè)會(huì)話了!!!
我們來(lái)做一個(gè)類(lèi)似于點(diǎn)擊商品然后能加入到購(gòu)物車(chē)的案例,使用session技術(shù)。
前提準(zhǔn)備,我們需要為商品創(chuàng)建javabean,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
public class product { private string id; private string name; private string author; public product() { super (); } public product(string id, string name, string author) { super (); this .id = id; this .name = name; this .author = author; } 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; } public string getauthor() { return author; } public void setauthor(string author) { this .author = author; } |
然后再建立一個(gè)數(shù)據(jù)庫(kù),以類(lèi)的方式來(lái)創(chuàng)建(誰(shuí)讓數(shù)據(jù)庫(kù)還沒(méi)學(xué)呢t_t!),然后使用map集合來(lái)存儲(chǔ)數(shù)據(jù),便于通過(guò)鍵值對(duì)檢索:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class productdatabase { private static map<string,product> map = new hashmap<string,product>(); static { map.put( "1" , new product( "1" , "《java編程思想》" , "jb" )); map.put( "2" , new product( "2" , "《java核心技術(shù)》" , "fdaf" )); map.put( "3" , new product( "3" , "《java并發(fā)編程》" , "什么鬼" )); map.put( "4" , new product( "4" , "《head first 設(shè)計(jì)模式》" , "老王" )); map.put( "5" , new product( "5" , "《html5權(quán)威手冊(cè)》" , "hhaa" )); } public static map<string,product> getmap() { return map; } } |
好了,我們?cè)谏唐凤@示的首頁(yè)顯示商品,同時(shí)為每個(gè)商品建立一個(gè)超鏈接,以便于當(dāng)用戶(hù)點(diǎn)擊超鏈接時(shí)能將商品的id作為存儲(chǔ)數(shù)據(jù)的依據(jù)由其他servlet類(lèi)獲取用戶(hù)購(gòu)買(mǎi)的商品種類(lèi):
1
2
3
4
5
6
7
8
9
10
|
response.setcharacterencoding( "utf-8" ); response.setcontenttype( "text/html;charset=utf-8" ); printwriter writer = response.getwriter(); //獲取數(shù)據(jù)庫(kù)中的商品數(shù)據(jù) map<string, product> map = productdatabase.getmap(); for (map.entry<string, product> entry : map.entryset()) { product book = entry.getvalue(); writer.print(book.getname()+ " <a href='/myservlet/servlet/buysession?id=" +book.getid()+ "' >購(gòu)買(mǎi)</a> <br/>" ); } |
此時(shí)可以看一看效果:
接著我們來(lái)做 點(diǎn)擊購(gòu)買(mǎi)超鏈接后的servlet,該servlet需要將獲取用戶(hù)所購(gòu)買(mǎi)的商品(通過(guò)id號(hào)),同時(shí)需要獲取(創(chuàng)建)session對(duì)象,并利用一個(gè)集合將所購(gòu)買(mǎi)的商品存入,這個(gè)session對(duì)象存儲(chǔ)用戶(hù)希望購(gòu)買(mǎi)的商品,當(dāng)我們跳轉(zhuǎn)到購(gòu)物車(chē)頁(yè)面上時(shí)能從session中取出商品并顯示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//獲取用戶(hù)所購(gòu)買(mǎi)商品的id號(hào) string productid = request.getparameter( "id" ); product book = productdatabase.getmap().get(productid); //將用戶(hù)所購(gòu)買(mǎi)的商品加入到session對(duì)象中保存,以便最后一起結(jié)賬,類(lèi)似于購(gòu)物車(chē)功能 httpsession session = request.getsession(); list<product> list = (list<product>) session.getattribute( "productlist" ); if (list == null ){ //首次購(gòu)買(mǎi) list = new arraylist<product>(); session.setattribute( "productlist" , list); } list.add(book); //跳轉(zhuǎn)到購(gòu)物車(chē)列表上 response.sendredirect( "/myservlet/servlet/cartlistservlet" ); |
注意:這里使用的是sendredirect重定向,如果使用的是forward轉(zhuǎn)發(fā),則在購(gòu)物車(chē)頁(yè)面進(jìn)行刷新的話會(huì)將每次購(gòu)買(mǎi)的商品再次購(gòu)買(mǎi)。
在購(gòu)物車(chē)頁(yè)面的servlet中功能就可以比較簡(jiǎn)單了,從用戶(hù)的session中取出保存的購(gòu)買(mǎi)商品對(duì)象,并顯示在頁(yè)面上即可:
1
2
3
4
5
6
7
8
9
10
11
|
response.setcharacterencoding( "utf-8" ); response.setcontenttype( "text/html;charset=utf-8" ); printwriter writer = response.getwriter(); writer.print( "您購(gòu)買(mǎi)的商品如下: <br/>" ); httpsession session = request.getsession(); list<product> list = (list<product>) session.getattribute( "productlist" ); for (product p : list) { writer.write(p.getname()+ "<br/>" ); } |
點(diǎn)擊多個(gè)商品,會(huì)看到在購(gòu)物車(chē)的servlet頁(yè)面上會(huì)顯示出我們購(gòu)買(mǎi)的商品:
而另外開(kāi)啟的多個(gè)瀏覽器點(diǎn)擊這些商品會(huì)看到購(gòu)買(mǎi)的不同購(gòu)物車(chē)頁(yè)面,所以可以使用session來(lái)解決不同用戶(hù)來(lái)訪問(wèn)相同頁(yè)面而同時(shí)保存他們各自不同數(shù)據(jù)的需求。
當(dāng)然這只是一個(gè)簡(jiǎn)單的強(qiáng)調(diào)session對(duì)象能在一個(gè)會(huì)話過(guò)程中保存一個(gè)瀏覽器訪問(wèn)多個(gè)servlet中會(huì)產(chǎn)生的數(shù)據(jù),上面這樣的簡(jiǎn)單示例肯定是不能用于購(gòu)物的,比如當(dāng)我們將瀏覽器關(guān)閉時(shí)(會(huì)話結(jié)束),這個(gè)session對(duì)象就結(jié)束了,那么下次再打開(kāi)瀏覽器我們的購(gòu)物車(chē)將一無(wú)所有,如果要滿足用戶(hù)的不同需求,那么就要了解一些session對(duì)象的底層結(jié)構(gòu)