一.Servlet細節(jié)
1.Servlet細節(jié)
1):一個Servlet向外暴露多個資源名稱(一般來說,一個Servlet使用一個資源名稱即可).
方式1:同一個<servlet>元素,提供多個<servlet-mapping>元素.
方式2:在<servlet-mapping>元素中提供多個<url-pattern>元素.
2):Servlet的資源名稱使用通配符表示(:表示N個任意字符).
- 方式1:/:任意的資源名稱都可以訪問該Servlet.
推論:/system/:訪問的資源名稱必須以/system/打頭才可以訪問(在簡單權(quán)限控制的時候使用). - 方式2:*.拓展名: 比如: *.do:凡是以.do結(jié)尾的資源名稱都可以訪問當(dāng)前的Servlet.
3):自定義的Servlet在編寫<servlet-name>元素的時候,文本內(nèi)容不能叫做:default.
原因是:在Tomcat根/conf/web.xml文件,有一個DefaultServlet的<servlet-name>就叫做:default.
如果我們也起名叫做:default,將會覆蓋DefaultServlet的配置.
DefaultServlet的作用是:在于訪問靜態(tài)的資源(html/圖片/css/js等).
4):默認情況下,Servlet的創(chuàng)建時機,在第一次訪問Servlet的時候,創(chuàng)建Servlet對象并調(diào)用init方法做初始化操作:
如果我們的某一個Servlet是用來做初始化操作的(比較耗時),那么也將會在第一次請求的時候才會執(zhí)行,第一用戶耗時比較長.
解決方案:在系統(tǒng)(Tomcat)啟動的時候,就對初始化Servlet做創(chuàng)建以及初始化操作,啟動耗時延遲.
在<servlet>元素中配置: <load-on-startup>數(shù)字</load-on-startup>.數(shù)字越小越優(yōu)先加載.
2.Servlet3.0新特性-注解配置
1.說明
從JavaEE6(Tomcat7,Servelt3.0)開始,可以使用(WebServlet)注解來取代傳統(tǒng)的XML配置.
所以我們說,從Tomcat7開始,web.xml文件不再是必須的,但是我們一般都保留該文件.
注意:web.xml文件中的:metadata-complete="true",表示是否忽略掃描Servlet上的注解標(biāo)簽.
metadata-complete="true" :要忽略掃描注解.
metadata-complete="false":不忽略,要掃描注解.(不寫該屬性,缺省就是false.)
2.Servlet的注解使用方式
使用WebServlet的注意:
1): metadata-complete="false"或者刪除該屬性:
2): @WebServlet("/資源名"),資源名稱必須使用/打頭.
3.注解和XML的使用對比
4.如何選擇使用
開發(fā)中到底使用XML配置還是注解配置:
-
XML配置:
- 優(yōu)點:直觀,清晰,可以統(tǒng)一配置,維護性較高.
- 缺點:繁瑣,如果配置信息比較多,配置文件會臃腫.
-
注解配置:
- 優(yōu)點:簡單,高效.
- 缺點:配置不夠清晰,不能統(tǒng)一管理,硬編碼又再次回到了Java代碼中.
在開發(fā)中因情況而定.
一般說來,我們使用XML做統(tǒng)一通用的配置,個別的配置可以使用注解來完成.
3.安全問題
多線程并發(fā)訪問同一個資源,會造成線程不安全問題.
Servlet是單例的,Servlet中的成員變量name,也就只有一個空間,后來的數(shù)據(jù)會覆蓋name空間的之前的數(shù)據(jù),
解決方案:
- 方式1:讓Servlet實現(xiàn)SingleThreadModel(過時).只允許一個線程訪問當(dāng)前Servlet,但是效率很低.
- 方式2:在Servlet中不要使用成員變量,使用局部變量.
在service方法中定義的局部變量,每一個線程發(fā)出請求的時候,都會重新調(diào)用service方法.
4.Servlet總結(jié)
Servlet:其實就是一個特殊的類,繼承于HttpServlet.
作用:
- 1):輸出一個動態(tài)網(wǎng)頁.
- 2):處理用戶的請求.
Servlet的優(yōu)缺點:
- 優(yōu)點: 是動態(tài)網(wǎng)頁,跨平臺, Servlet是單實例的,在Tomcat中一個Servlet就只有一個對象-->效率比較高.
- 缺點: 輸出動態(tài)網(wǎng)頁太惡心(JSP). Servlet的單實例提高了效率,但是卻帶來了安全性問題.
二.Http協(xié)議無狀態(tài)帶來的問題
1.HTTP協(xié)議:
規(guī)范了瀏覽器和服務(wù)器之間傳輸數(shù)據(jù)的格式.
Http協(xié)議是無狀態(tài)的:(健忘的人).服務(wù)器不知道上一次請求是哪一個客戶端發(fā)出的.
HTTP是無狀態(tài)協(xié)議,也就是沒有記憶力,每個請求之間無法共享數(shù)據(jù)。這就無法知道會話什么時候開始,什么時候結(jié)束,也無法確定發(fā)出請求的用戶身份。
2.會話:
百度百科的解釋:簡單為,打開瀏覽器,訪問一個站點,在這一個網(wǎng)站中和服務(wù)端有多次交互,最后關(guān)閉瀏覽器,整個過程就稱之為一次會話.
在這一次會話中,用戶需要和服務(wù)端做多次交互,每一次交互都是一個(請求-響應(yīng)),HTTP協(xié)議是無狀態(tài)的,服務(wù)端怎么怎么你的這一次請求和上一次請求是同一個用戶發(fā)出的.
在一個會話中共享多次請求的數(shù)據(jù)即會話跟蹤技術(shù).
登錄郵件系統(tǒng):收郵件:
郵件系統(tǒng)流程分析:
3.解決的問題:如何跟蹤用戶的會話信息(處理多個請求之間共享數(shù)據(jù)).**
方式1:在資源后面使用傳遞參數(shù)的機制.
比如: /param/list?username=iwiller .
那么在ListServlet就可以通過request.getParameter獲取參數(shù).
該方式很不安全,因為超鏈接的請求參數(shù)會全部暴露在瀏覽器的地址欄.http://localhost/param/get?username=will
解決方案:
傳遞參數(shù)的時候,不要把參數(shù)存放在請求的行里面(瀏覽器地址欄),
最好把請求參數(shù),存放于請求頭中,如此一來瀏覽器中看不到,比較安全.--->Cookie.
方式2:Cookie.
方式3:Session.
三.Cookie
1.什么是Cookie:
解決用戶的會話跟蹤.
Cookie是客戶端技術(shù),程序把每個用戶的數(shù)據(jù)以cookie的形式寫給用戶各自的瀏覽器。當(dāng)用戶使用瀏覽器再去訪問服務(wù)器中的web資源時,就會帶著各自的數(shù)據(jù)去。這樣,web資源處理的就是用戶各自的數(shù)據(jù)了。
客戶端技術(shù):多個請求時需要共享數(shù)據(jù),我們把共享數(shù)據(jù)存放于客戶端(瀏覽器)中.
原理(辦會員卡的例子):
使用Cookie和不使用Cookie的區(qū)別(請求/響應(yīng)中)
2.Cookie的操作:
1:創(chuàng)建Cookie對象并設(shè)置共享數(shù)據(jù)[辦一張會員卡,并填寫卡上的信息].
Cookie c = new Cookie(String name,String value);
Cookie c = new Cookie("currentName","Will");
參數(shù):
name: 給共享數(shù)據(jù)起個名字
value: 多個請求之前需要共享的數(shù)據(jù)
2.把Cookie放入響應(yīng)中,響應(yīng)給瀏覽器(把會員卡交給客戶).
response對象.addCookie(c);
3.從請求中獲取Cookie對象,再從Cookie中獲取共享的數(shù)據(jù)(客戶帶卡去健身房).
Cookie[] cs = req.getCookies();
4.:Cookie的屬性名和屬性值都不支持中文.
解決方案:URLEncoder對中文做編碼操作.
- 編碼(放進Cookie之前):
Cookie cookie = new Cookie("currentName",URLEncoder.encode(username, "UTF-8"));
- 解碼(從Cookie中獲取出來):
username = URLDecoder.decode(c.getValue(), "UTF-8");
5.修改Cookie(修改Cookie中存放的共享數(shù)據(jù)).
- 方式1:獲取被修改的Cookie對象,cookie對象.setValue(新的數(shù)據(jù))(不推薦);
- 方式2:創(chuàng)建一個和被修改Cookie同名的Cookie對象,只改變value值即可.
Cookie xxx = new Cookie("currentName","lucy");
注意:此時修改重新把修改之后的Cookie響應(yīng)給瀏覽器.
6.Cookie的分類(根據(jù)Cookie存活的時間,分成兩大類).
名稱 | 解釋 |
---|---|
會 話Cookie: | 在當(dāng)前會話中有效,瀏覽器關(guān)閉就銷毀了.此時該Cookie存放在瀏覽器進程中(缺省). |
持久化Cookie: | 可以存活指定的時間(我們需要來設(shè)置Cookie的存活時間). |
Cookie對象.setMaxAge(int seconds);設(shè)置Cookie對象存儲的最大時間.
7.刪除Cookie.
Cookie對象.setMaxAge(0):表示立刻刪除該Cookie對象.
8.設(shè)置訪問路徑和域.
Cookie的path是在同一主機中指定共享Cookie,如果主機不同那么就一定不能共享Cookie,無論path是什么。
需求:AServlet和BServlet共享Cookie:
- 如果:AServlet的資源路徑是/cookie/a,BServlet的資源路徑是:/cookie/b. 此時共享成功.
- 如果:AServlet的資源路徑是/cookie/a,BServlet的資源路徑是:/ooxx/b. 此時不能共享.
(1)默認情況下會根據(jù)Servlet的相對路徑來做判斷.
若需要讓整個應(yīng)用中所有的Servlet都可以獲取該Cookie,則設(shè)置為:Cookie對象.setPath("/");
(2)如果希望不同的二級域名中可以共享Cookie,那么就要設(shè)置Cookie的domain了。
例如:music.baidu.com、map.baidu.com、tieba.baidu.com,它們的域名不同,但百度希望它們之間可以共享Cookie,那么就要設(shè)置domain了。
1). 設(shè)置Cookie的path為“/”,例如:cookie.setPath("/");
2). 設(shè)置Cookie的domain,例如:cookie.setDomain(".baidu.com"),其中domain中沒有指定域名前綴!
在music.baidu.com主機中的某個項目中保存了Cookie
在map.baidu.com主機中某個項目中獲取Cookie
當(dāng)然這需要配置兩個虛擬主機才行。
3.Cookie的缺陷:
1):Cookie存儲中文的時候,操作麻煩(手動的編碼/解碼操作);
2):Cookie存儲在瀏覽器中,多個人使用共同的一臺的電腦的時候,不安全.
3):Cookie的文件大小和數(shù)量是有限制的.
- Cookie大小限制在4KB之內(nèi);
- 一臺服務(wù)器在一個客戶端最多保存20個Cookie;
- 一個瀏覽器最多可以保存300個Cookie;
4):Cookie的value只能存儲String類型的數(shù)據(jù),一個Cookie只能存儲一個共享數(shù)據(jù).
若需要共享多個數(shù)據(jù),就得創(chuàng)建多個Cookie對象.--->操作麻煩
如果Cookie的Value可以存儲Object類型,我們就可以把多個數(shù)據(jù)封裝成對象,再做存儲.
5):Cookie在設(shè)計上的問題.
Cookie的設(shè)計:把客戶端和服務(wù)端的識別數(shù)據(jù)存放于客戶端中,這個在設(shè)計上有點不合理.
最好的設(shè)計方式:把識別數(shù)據(jù)存放于服務(wù)端,客戶端只需要存儲一個標(biāo)志即可.
新會員過來, 把新會員的數(shù)據(jù)錄入到系統(tǒng)中(健身房這里/服務(wù)端).
下一次,會員來健身,只要報手機號碼,就可以從系統(tǒng)中找到該用戶的識別數(shù)據(jù).---->Session.
四.Session
1.什么是session
Session其實就是一個特殊的會話Cookie,瀏覽器關(guān)閉Session就銷毀了.
Session是服務(wù)器端技術(shù)(把識別數(shù)據(jù)/共享數(shù)據(jù)存放于服務(wù)端),利用這個技術(shù),服務(wù)器在運行時可以為每一個用戶的瀏覽器創(chuàng)建一個其獨享的session對象,由于session為用戶瀏覽器獨享,所以用戶在訪問服務(wù)器的web資源時,可以把各自的數(shù)據(jù)放在各自的session中,當(dāng)用戶再去訪問服務(wù)器中的其它web資源時,其它web資源再從用戶各自的session中取出數(shù)據(jù)為用戶服務(wù)。
cookie的方式
session的方式
session對象
session和cookie的區(qū)別
2.操作Session:
1.創(chuàng)建和獲取Session對象.
// 如果當(dāng)前存在Session對象,則直接返回,如果當(dāng)前沒有Session對象,先創(chuàng)建一個Session對象,再返回.
HttpSession session = request對象.getSession(true);
// 如果當(dāng)前存在Session對象,則直接返回,如果沒有,在則返回null.
HttpSession session = request對象.getSession(false);
//等價于 request對象.getSession(true).
HttpSession session = request對象.getSession();
2.往Session中存儲共享數(shù)據(jù).
session對象.setAttribute(String name,Object value);
- 0):一般的,我們把存儲在session中的屬性起名為:XXX_IN_SESSION.
- 1):因為Session的setAttribute方法支持Object類型,所以我們可以把多個共享數(shù)據(jù)封裝成對象,再存儲到session中.
session.setAttribute("USER_IN_SESSION",user對象); - 2):一般的,為了多態(tài)服務(wù)器之間共享session中的數(shù)據(jù),我們把session中的對象實現(xiàn)java.io.Serializable接口.
當(dāng)某一個對象只有實現(xiàn)java.io.Serializable接口之后,才可以做序列化操作.
序 列化: 把對象的數(shù)據(jù)以二進制的形式存儲到文件中.------>網(wǎng)絡(luò)傳輸.
反序列化: 把二進制形式的數(shù)據(jù)恢復(fù)成Java對象.
3.獲取Session中存儲的數(shù)據(jù).
Object value = session對象.getAttribute(String name);
4.刪除Session(刪除Session中存儲的共享數(shù)據(jù))[登錄注銷]:
- 方式1:session對象.remove(String name);從當(dāng)前session中刪除指定屬性名的屬性.
- 方式2:session.invalidate();銷毀session對象,從而session中的數(shù)據(jù)全部沒了.
5.Session的超時管理.
超時時間:用戶的兩次操作的最大間隔時間:超時時間到了,就會銷毀Session.
session對象.setMaxInactiveInterval(int seconds):
一般說來:不用設(shè)置,Tomcat中默認為30分鐘.
6.URL重寫.
Session其實也就是一個會話Cookie(瀏覽器關(guān)閉之后,瀏覽器存儲的jsessionid消失了,session對象在服務(wù)端依然存在).
瀏覽器可以禁用Cookie(不接受Cookie),非常不推薦的,操作相當(dāng)麻煩.
解決方案:手動的在每一個資源后面攜帶:;jsessionid= session的id值.
http://localhost/session/get ------>因為瀏覽器沒有存儲session的id值,所以找不到服務(wù)端的共享數(shù)據(jù)內(nèi)存地址.
http://localhost/session/get;jsessionid=FACF8BD9AFB39C1A85A1B1FDC1978923 .
URL重寫:
String newUrl = response對象.encodeURL(String oldUrl);
String newUrl = response對象.encodeURL("session/get");返回:/session/get;jsessionid=FACF8BD9AFB39C1A85A1B1FDC1978923
五.總結(jié)
解決用戶的會話跟蹤問題(實現(xiàn)多個請求之間共享數(shù)據(jù)):
Cookie: 客戶端技術(shù):把共享數(shù)據(jù)存儲在瀏覽器中.
Session:服務(wù)端技術(shù):把共享數(shù)據(jù)存儲在服務(wù)端,只是給了客戶端一個地址(jesseionid).
電子商城的購物車:
1):session來做:瀏覽器關(guān)閉,購物車中的數(shù)據(jù)也就消失了.
2):如果沒有登錄: 此時把購物車中的商品信息存儲到cookie中.
3):一旦登錄,先讀取該站點的Cookie,把商品信息持久化到數(shù)據(jù)庫.
Cookie的應(yīng)用:
1):記住多久不用登錄.
2):購物車
3):存儲網(wǎng)站的個人愛好設(shè)置.
4):單點登錄(針對多個應(yīng)用).
Session的應(yīng)用:
1):登錄信息存儲到session中.
2):網(wǎng)站需要統(tǒng)計在線會員人數(shù).