1.1 Servlet
1.1.1 什么是Servlet
Servlet是JavaWeb三大組件之一(Servlet摔笤、Filter够滑、Listener)
Servlet是用來處理客戶端請求的動(dòng)態(tài)資源
Servlet的任務(wù)有:
獲取請求數(shù)據(jù)
處理請求
完成響應(yīng)
- Servlet接口方法:
servlet 中的方法大多數(shù)不由我們調(diào)用,而是由 tomcat 調(diào)用吕世,并且 servlet 對(duì)象也不由我們創(chuàng)建彰触,由 tomcat 創(chuàng)建
> void init(ServletConfig) 它會(huì)在servlet對(duì)象創(chuàng)建之后馬上執(zhí)行,并只執(zhí)行一次
> void service(ServletRequest,ServletResponse) 它會(huì)被調(diào)用多次 , 每次處理請求都是在調(diào)用這個(gè)方法
> void destory() 它會(huì)在servlet被銷毀之前調(diào)用命辖,只會(huì)被調(diào)用一次 [留遺言]
以上三個(gè)方法都為生命周期方法
> ServletConfig getServletConfig() 用來獲取 servlet 配置信息
> String getServletInfo() 獲取 servlet 信息
1.1.2 實(shí)現(xiàn)Servlet的方式
實(shí)現(xiàn)Servlet接口(不方便)
繼承GenericServlet類(不方便)
繼承 HttpServlet 類(方便)
1.1.3 Servlet第一例
寫一個(gè)類cn.itcast.MyServlet况毅,實(shí)現(xiàn)Servlet接口
實(shí)現(xiàn)service()方法分蓖,在其中給出System.out.println("hello servlet!");
在web.xml文件中指定Servlet的訪問路徑為:/myservlet
<servlet>
<servlet-name>xxx</servlet-name>
<servlet-class>cn.itcast.MyServlet</servlet-class> 將路徑和類綁在一起,此處為包名
</servlet>
<servlet-mapping>
<servlet-name>xxx</servlet-name>
<url-pattern>/myservlet</url-pattern> 此處為路徑
</servlet-mapping>
注意尔许!兩處的 servlet-name 要一致
- servletConfig 方法&功能:servletConfig 是接口
當(dāng)用戶在地址欄中訪問:http://localhost:8080/day04_1/myservlet時(shí)么鹤,會(huì)執(zhí)行System.out.println("hello servlet!");
1). 服務(wù)器創(chuàng)建Servlet:
當(dāng) Servlet 第一次被請求時(shí),或服務(wù)器啟動(dòng)時(shí)味廊,服務(wù)器會(huì)創(chuàng)建 Servlet 實(shí)例蒸甜。
- 服務(wù)器默認(rèn)是在servlet第一次被請求時(shí)創(chuàng)建Servlet實(shí)例,如果希望服務(wù)器啟動(dòng)時(shí)就創(chuàng)建Servlet實(shí)現(xiàn)需要在web.xml中配置
服務(wù)器只為一個(gè)類型的 Servlet 創(chuàng)建一個(gè)實(shí)例對(duì)象余佛,所以 Servlet 是單例的柠新;
2). 服務(wù)器初始化Servlet:
當(dāng)服務(wù)器創(chuàng)建Servlet實(shí)例后會(huì)馬上調(diào)用Servlet的init(ServletConfig)方法,完成對(duì)Servlet的初始化辉巡;
init(ServletConfig)只會(huì)被調(diào)用一次
服務(wù)器會(huì)在調(diào)用init()方法時(shí)傳遞ServletConfig參數(shù)
3). 服務(wù)器使用Servlet處理請求:
當(dāng)Servlet被請求時(shí)恨憎,服務(wù)器會(huì)調(diào)用Servlet的service(ServletRequest,ServletResponse)方法
service(ServletRequest,ServletResponse)方法每處理一次請求,就會(huì)被調(diào)用一次郊楣,所以它可能會(huì)被調(diào)用N次
因?yàn)?/strong> Servlet 是單例的框咙,所以可能在同一時(shí)刻一個(gè) Servlet 對(duì)象會(huì)被多個(gè)請求同時(shí)訪問,所以這可能出現(xiàn)線程案例問題
Servlet 不是線程案例的痢甘,這有助與提高效率喇嘱,但不能讓 Servlet 具有狀態(tài),以免多個(gè)線程爭搶數(shù)據(jù)
4). 服務(wù)器銷毀Servlet
服務(wù)器通常不會(huì)銷毀 Servlet 塞栅,通常只有在服務(wù)器關(guān)閉時(shí)才會(huì)銷毀 Servlet
服務(wù)器會(huì)在銷毀Servlet之前調(diào)用Servlet的destory()方法
可以在destory()方法中給出釋放Servlet占有的資源者铜,但通常Servlet是沒什么可要釋放的,所以該方法一般都是空的
1.1.4 ServletConfig
ServletConfig是Servlet中的init()方法的參數(shù)類型放椰,服務(wù)器會(huì)在調(diào)用init()方法時(shí)傳遞ServletConfig對(duì)象給init()方法作烟。
ServletConfig 對(duì)象封裝了 Servlet 在 web.xml 中的配置信息,它對(duì)應(yīng) <servlet> 元素砾医。
ServletConfig類的功能有:
String getServletName():獲取 Servlet 配置名拿撩,即 <servlet-name> 的值;
ServletContext getServletContext():獲取 ServletContext 對(duì)象
String getInitParameter(String name):獲取初始化參數(shù)
Enumeration getInitParameterNames():獲取所有初始化參數(shù)的名稱
在web.xml文件中如蚜,配置<servlet>時(shí)可以為<servlet>配置0~N個(gè)初始化參數(shù)
1.1.5 GenericServlet
GenericServlet是Servlet接口的實(shí)現(xiàn)類压恒,但它是一個(gè)抽象類,它唯一的抽象方法就是 service() 方法
GenericServlet實(shí)現(xiàn)了Servlet方法:
實(shí)現(xiàn)了String getServletInfo()方法
實(shí)現(xiàn)了void destory()方法错邦,空實(shí)現(xiàn)
實(shí)現(xiàn)了void init(ServletConfig)方法探赫,用來保存ServletConfig參數(shù)
實(shí)現(xiàn)了ServletConfig getServletConfig()方法
GenericServlet實(shí)現(xiàn)了ServletConfig接口:
實(shí)現(xiàn)了ServletContext getServletContext()方法
實(shí)現(xiàn)了String getInitParameter()方法
實(shí)現(xiàn)了String getServletName()方法
實(shí)現(xiàn)了Enumeration getInitParameterNames()方法
GenericServlet添加了init()方法:
該方法會(huì)被init(ServletConfig)方法調(diào)用
如果希望對(duì)Servlet進(jìn)行初始化,那么應(yīng)該覆蓋init()方法撬呢,而不是init(ServletConfig)方法
service 方法中也可以使用 servletconfig 成員 , 只要在 init 方法之前就可以
不可貿(mào)然覆蓋init方法伦吠,其中有config對(duì)象
可以覆蓋init()無參函數(shù)
1.1.6 HttpServlet
HttpServlet是GenericServlet的子類,它專注HTTP請求
HttpServlet類的方法:
- 實(shí)現(xiàn)了void service(ServletRequest,ServletResponse)方法,實(shí)現(xiàn)內(nèi)容是:
> 把ServletRequest強(qiáng)轉(zhuǎn)成HttpServletRequest
> 把ServletResponse強(qiáng)轉(zhuǎn)成HttpServletResponse
> 調(diào)用本類添加的void service(HttpServletRequest,HttpServletResponse)方法
- 添加了void service(HttpServletRequest,HttpServletResponse)方法毛仪,內(nèi)容是:
> 調(diào)用request的getMethod()獲取請求方式
> 如果請求方式為GET搁嗓,那么調(diào)用本類添加的doGet(HttpServletRequest,HttpServletResponse)方法
> 如果請求方式為POST,那么調(diào)用本類添加的doPost(HttpServletRequest,HttpServletResponse)方法
添加了doGet(HttpServletRequest,HttpServletResponse)方法箱靴,內(nèi)容是響應(yīng)405谱姓,表示錯(cuò)誤,所以我們應(yīng)該去覆蓋這個(gè)方法
添加了doPost(HttpServletRequest,HttpServletResponse)方法刨晴,內(nèi)容是響應(yīng)405,表示錯(cuò)誤路翻,所以我們應(yīng)用去覆蓋這個(gè)方法
如果是通過繼承HttpServlet類來自定義Sevlet的話狈癞,那么:
不要去覆蓋void service(ServletRequest,ServletResponse)
不要去覆蓋void service(HttpServletRequest, HttpServletResponse)
而應(yīng)該去覆蓋doGet()或doPost()方法。
1.1.7 web.xml
servlet創(chuàng)建兩種方式茂契,
1.servlet第一次收到請求創(chuàng)建
2.服務(wù)器在啟動(dòng)時(shí)就創(chuàng)建
1.1.8 defaultServlet
default優(yōu)先級(jí)最低蝶桶,如果一個(gè)請求沒有處理,那么它來處理掉冶,顯示404
url-pattern 匹配的是 /
當(dāng)訪問路徑不存在時(shí)真竖,會(huì)執(zhí)行defaultServlet,其實(shí)在訪問index.html時(shí)也是在執(zhí)行這個(gè)servlet
1.1.9 jspServlet
訪問jsp頁面時(shí)厌小,會(huì)調(diào)用jspServlet恢共,通過將動(dòng)態(tài)資源轉(zhuǎn)為靜態(tài)資源,然后用response進(jìn)行響應(yīng)
1.1.10 session-config
session過期時(shí)間
1.2 MIME 多功能網(wǎng)際郵件擴(kuò)充協(xié)議
多用途擴(kuò)展類型璧亚,包含jpeg gif等讨韭,在這里定義了類型:
xml類型
txt類型
jpg/jpeg類型
doc類型
docx
1.2.1 什么是MIME-Type
首先,我們要了解瀏覽器是如何處理內(nèi)容的癣蟋。在瀏覽器中顯示的內(nèi)容有 HTML透硝、有 XML、有 GIF灵汪、還有 Flash ……那么杜秸,瀏覽器是如何區(qū)分它們佩耳,決定什么內(nèi)容用什么形式來顯示呢?答案是 MIME Type罪治,也就是該資源的媒體類型。
媒體類型通常是通過 HTTP 協(xié)議礁蔗,由 Web 服務(wù)器告知瀏覽器的规阀,更準(zhǔn)確地說,是通過 Content-Type 來表示的瘦麸,
例如:Content-Type: text/HTML
表示內(nèi)容是 text/HTML 類型谁撼,也就是超文本文件。為什么是“text/HTML”而不是“HTML/text”或者別的什么?MIME Type 不是個(gè)人指定的厉碟,是經(jīng)過 ietf 組織協(xié)商喊巍,以 RFC 的形式作為建議的標(biāo)準(zhǔn)發(fā)布在網(wǎng)上的,大多數(shù)的 Web 服務(wù)器和用戶代理都會(huì)支持這個(gè)規(guī)范 (順便說一句箍鼓,Email 附件的類型也是通過 MIME Type 指定的)崭参。
通常只有一些在互聯(lián)網(wǎng)上獲得廣泛應(yīng)用的格式才會(huì)獲得一個(gè) MIME Type,如果是某個(gè)客戶端自己定義的格式款咖,一般只能以 application/x- 開頭何暮。
XHTML 正是一個(gè)獲得廣泛應(yīng)用的格式,
因此铐殃,在 RFC 3236 中海洼,說明了 XHTML 格式文件的 MIME Type 應(yīng)該是application/xHTML+XML。
當(dāng)然富腊,處理本地的文件坏逢,在沒有人告訴瀏覽器某個(gè)文件的 MIME Type 的情況下,瀏覽器也會(huì)做一些默認(rèn)的處理赘被,這可能和你在操作系統(tǒng)中給文件配置的 MIME Type 有關(guān)是整。
比如在 Windows 下,打開注冊表的“HKEY_LOCAL_MACHINESOFTWAREClassesMIMEDatabaseContent Type”主鍵民假,你可以看到所有 MIME Type 的配置信息浮入。
1.2.2 <url-pattern>
<url-pattern>是<servlet-mapping>的子元素,用來綁定Servlet的訪問路徑
可以在一個(gè)<servlet-mapping>中給出多個(gè)<url-pattern>羊异,也就是說一個(gè)Servlet可以有多個(gè)訪問路徑:
<servlet-mapping>
<servlet-name>xxx</servlet-name>
<url-pattern>/helo1<url-pattern>
<url-pattern>/hello2<url-pattern>
</servlet-mapping>
還可以在<url-pattern>中使用通配符舵盈,即“*”。
<url-pattern>/*<url-pattern>:表示匹配任何路徑
<url-pattern>/do/*<url-pattern>:表示匹配以/do開頭的任何路徑
<url-pattern>*.do<url-pattern>:表示匹配任何以“.do”結(jié)尾的路徑
注意:
通配符要么在開頭球化,要么在結(jié)尾秽晚,不能在中間,例如:/*.do就是錯(cuò)誤的使用筒愚。
如果不使用通配符赴蝇,那么<url-pattern>必須以“/”開頭,例如:<url-pattern>abc</url-pattern>就是錯(cuò)誤的
1.2.3 welcome-file-list
設(shè)置歡迎界面
1.3 ServletContext
ServletContext是Servlet三大域?qū)ο笾?/p>
ServletContext在服務(wù)器啟動(dòng)時(shí)創(chuàng)建巢掺,在服務(wù)器關(guān)閉時(shí)銷毀句伶,一個(gè)JavaWeb應(yīng)用只創(chuàng)建一個(gè)ServletContext對(duì)象
一個(gè)項(xiàng)目只有一個(gè)ServletContext對(duì)象
1.3.1 ServletContext概述
服務(wù)器會(huì)為每個(gè)應(yīng)用創(chuàng)建一個(gè)ServletContext對(duì)象:
ServletContext對(duì)象的創(chuàng)建是在服務(wù)器啟動(dòng)時(shí)完成的;
ServletContext對(duì)象的銷毀是在服務(wù)器關(guān)閉時(shí)完成的陆淀。
ServletContext對(duì)象的作用是在整個(gè)Web應(yīng)用的動(dòng)態(tài)資源之間共享數(shù)據(jù)考余!例如在AServlet中向ServletContext對(duì)象中保存一個(gè)值,然后在BServlet中就可以獲取這個(gè)值轧苫,這就是共享數(shù)據(jù)了楚堤。
不能用AServlet調(diào)用BServlet方法,會(huì)使耦合過緊
1.3.2 ServletContext的功能分類:
存取數(shù)據(jù)
讀取web.xml中的應(yīng)用初始化參數(shù)
讀取應(yīng)用資源
1.3.3 獲取ServletContext對(duì)象
在HttpServlet中可以通過以下方法來獲取ServletContext對(duì)象
ServletContext sc = this.getServletContext()
ServletContext sc = this.getServletConfig().getServletContext()
servletConfig.getServletContext(); 也可獲取
HttpSession 也可獲取
ServletContextEvent
在void init(ServletConfig config)中:
ServletContext context = config.getServletContext();
ServletConfig類的getServletContext()方法可以用來獲取ServletContext對(duì)象;
在GenericeServlet或HttpServlet中獲取ServletContext對(duì)象:
GenericServlet類有g(shù)etServletContext()方法身冬,所以可以直接使用this.getServletContext()來獲刃普汀;
1.3.4 存取數(shù)據(jù)
因?yàn)樵谝粋€(gè)JavaWeb應(yīng)用中酥筝,只有一個(gè)ServletContext對(duì)象滚躯,所以在ServletContext中保存的數(shù)據(jù)可以共整個(gè)JavaWeb應(yīng)用中的動(dòng)態(tài)資源共享
ServletContext是Servlet三大域?qū)ο笾唬驅(qū)ο髢?nèi)部有一個(gè)Map嘿歌,用來保存數(shù)據(jù)
域?qū)ο蟮墓δ?***(****用來在多個(gè)****servlet****中傳遞數(shù)據(jù)****)
ServletContext是JavaWeb四大域?qū)ο笾唬?/p>
PageContext掸掏;
ServletRequest;
HttpSession宙帝;
ServletContext丧凤;
1. 存數(shù)據(jù)
- void setAttribute(String name, Object value):用來添加或替換ServletContext域數(shù)據(jù)
> servletContext.setAttribute("xxx", "XXX"),添加域數(shù)據(jù)
> servletContext.setAttribute("xxx", "XXXX")茄唐,覆蓋域數(shù)據(jù),因?yàn)樵谟蛑幸呀?jīng)存在了名為xxx的數(shù)據(jù)蝇更,所以這次就是覆蓋了
2. 取數(shù)據(jù)
Object getAttribute(String name):通過名稱來獲取域數(shù)據(jù)
void removeAttribute(String name):通過名稱移除域數(shù)據(jù)
Enumeration<String> getAttributeNames():獲取所有ServletContext域數(shù)據(jù)的名稱
1.3.5 讀取web.xml中配置的應(yīng)用初始化參數(shù)
Servlet也可以獲取初始化參數(shù)沪编,但它是局部的參數(shù);也就是說年扩,一個(gè)Servlet只能獲取自己的初始化參數(shù)蚁廓,不能獲取別人的,即初始化參數(shù)只為一個(gè)Servlet準(zhǔn)備厨幻!
可以配置公共的初始化參數(shù)相嵌,為所有Servlet而用!這需要使用ServletContext才能使用况脆!
<context-param>
<param-name>p1</param-name>
<param-value>v1</param-value>
</context-param>
<context-param>
<param-name>p2</param-name>
<param-value>v2</param-value>
</context-param>
servletContext.getInitParameter("p1")饭宾,返回v1
servletContext.getInitParameter("p2"),返回v2
servletContext.getInitParameterNames()格了,返回Enumeration<String>看铆,包含p1和p2
1.3.6 獲取項(xiàng)目資源
需要?jiǎng)討B(tài)獲取地址,引入
- String getRealPath(String path):獲取資源的真實(shí)名稱
String path = servletContext.getRealPath("/WEB-INF/a.jpg");
返回值為/WEB-INF/a.jpg真實(shí)路徑盛末,即磁盤路徑:C:/tomcat6/wabapps/hello/WEB-INF/a.jpg
如:
- InputStream getResourceAsStream(String path):獲取資源的輸入流
InputStream in = servletContext.getResourceAsStream("/WEB-INF/a.jpg");
返回的是a.jpg的輸入流對(duì)象弹惦,可以從流中得到a.jpg的數(shù)據(jù)
- Set<String> getResourcePaths(String path):獲取指定目錄下的所有資源路徑
Set<String> paths = servletContext.getResourcePaths("/WEB-INF");
返回的Set中包含如下字符串:
> /WEB-INF/lib/
> /WEB-INF/classes/
> /WEB-INF/web.xml
> /WEB-INF/a.jpg
1.3.7 獲取類路徑資源
可以通過Class類的對(duì)象來獲取類路徑下的資源,對(duì)應(yīng)JavaWeb應(yīng)用的類路徑就是classes目錄下的資源
例如:
InputStream in = cn.itcast.servlet.MyServlet.class.getResourceAsStream("a.jpg");
獲取的是:/WEB-INF/classes/cn/itcast/servlet/a.jpg悄但,即與MyServlet.class同目錄下的資源
例如:
InputStream in = cn.itcast.servlet.MyServlet.class.getResourceAsStream("/a.jpg");
獲取的是:/WEB-INF/classes/a.jpg棠隐,即類路徑的根目錄下的資源,類路徑的根目錄就是/classes目錄
IOUtils 輸入出流工具類檐嚣,可以轉(zhuǎn)換為字符串
練習(xí):統(tǒng)計(jì)網(wǎng)站訪問量
一個(gè)項(xiàng)目中所有的資源被訪問都要對(duì)訪問量進(jìn)行累加助泽!
創(chuàng)建一個(gè)int類型的變量,用來保存訪問量,然后把它保存到ServletContext的域中报咳,這樣可以保存所有的Servlet都可以訪問到侠讯!
最初時(shí),ServletContext中沒有保存訪問量相關(guān)的屬性暑刃;
當(dāng)本站第一次被訪問時(shí)厢漩,創(chuàng)建一個(gè)變量,設(shè)置其值為1岩臣;保存到ServletContext中溜嗜;
當(dāng)以后的訪問時(shí),就可以從ServletContext中獲取這個(gè)變量架谎,然后在其基礎(chǔ)之上加1炸宵。
獲取ServletContext對(duì)象,查看是否存在名為count的屬性谷扣,如果存在土全,說明不是第一次訪問,如果不存在会涎,說明是第一次訪問裹匙;
第一次訪問:調(diào)用Servletcontext的setAttribute()傳遞一個(gè)屬性,名為count末秃,值為1概页;
第2~N次訪問:調(diào)用ServletContext的getAttribute()方法獲取原來的訪問量,給訪問量加1练慕,再調(diào)用Servletcontext的setAttribute()方法完成設(shè)置惰匙。
1.3.8 參數(shù)(parameter)和屬性(Attribute)的區(qū)別
區(qū)別:
- 來源不同:
參數(shù)(parameter)是從客戶端(瀏覽器)中由用戶提供的,若是GET方法是從URL中
提供的铃将,若是POST方法是從請求體(request body)中提供的项鬼;
屬性(attribute)是服務(wù)器端的組件(JSP或者Servlet)利用requst.setAttribute()設(shè)置的
- 操作不同:
參數(shù)(parameter)的值只能讀取不能修改,讀取可以使用request.getParameter()讀染⒀帧秃臣;
屬性(attribute)的值既可以讀取亦可以修改,讀取可以使用request.setAttribute(),設(shè)置可使用request.getAttribute()
- 數(shù)據(jù)類型不同:
參數(shù)(parameter)不管前臺(tái)傳來的值語義是什么哪工,在服務(wù)器獲取時(shí)都以String類型看待奥此,并且客戶端的參數(shù)值只能是簡單類型的值,不能是復(fù)雜類型雁比,比如一個(gè)對(duì)象稚虎。
屬性(attribute)的值可以是任意一個(gè)Object類型。
共同點(diǎn)
二者的值都被封裝在request對(duì)象中偎捎。
1.4 Cookie
1.4.1 Http協(xié)議與Cookie(了解)
Cookie是HTTP****協(xié)議制定的蠢终!先由服務(wù)器保存Cookie到瀏覽器序攘,再下次瀏覽器請求服務(wù)器時(shí)把上一次請求得到Cookie再歸還給服務(wù)器
由服務(wù)器創(chuàng)建保存到客戶端瀏覽器的一個(gè)鍵值對(duì)!服務(wù)器保存 Cookie 的響應(yīng)頭:Set-Cookie: aaa=AAA Set-Cookie: bbb=BBB
response.addHeader("Set-Cookie", "aaa=AAA");
response.addHeader("Set-Cookie", "bbb=BBB");
當(dāng)瀏覽器請求服務(wù)器時(shí)寻拂,會(huì)把該服務(wù)器保存的Cookie隨請求發(fā)送給服務(wù)器程奠。瀏覽器歸還 Cookie 的請求頭:Cookie: aaa=AAA; bbb=BBB
Http協(xié)議規(guī)定(保證不給瀏覽器太大壓力):
> 1 個(gè) Cookie 最大 4KB
> 1 個(gè)服務(wù)器最多向 1 個(gè)瀏覽器保存 20 個(gè) Cookie
> 1 個(gè)瀏覽器最多可以保存 300 個(gè) Cookie
- 瀏覽器大戰(zhàn):因?yàn)闉g覽器競爭很激烈,所以很多瀏覽器都會(huì)在一定范圍內(nèi)違反HTTP規(guī)定祭钉,但也不會(huì)讓一個(gè)Cookie為4GB瞄沙!
1.4.2 Cookie的用途
服務(wù)器使用Cookie來跟蹤客戶端狀態(tài)!
保存購物車(購物車中的商品不能使用request保存慌核,因?yàn)樗且粋€(gè)用戶向服務(wù)器發(fā)送的多個(gè)請求信息)
顯示上次登錄名(也是一個(gè)用戶多個(gè)請求)
********** Cookie 是不能跨瀏覽器的距境! ***********
1.4.3 JavaWeb中使用Cookie
-
原始方式(了解):
> 使用response發(fā)送Set-Cookie響應(yīng)頭
> 使用request獲取Cookie請求頭
- 便捷方式(精通):
> 使用repsonse.addCookie()方法向?yàn)g覽器保存Cookie
> 使用request.getCookies()方法獲取瀏覽器歸還的Cookie(* 判斷 null) *
Cookie第一例:
> 一個(gè)jsp保存cookie, a.jsp
> 另一個(gè)jsp獲取瀏覽器歸還的cookie! b.jsp
1.4.4 Cookie詳解
Cookie不只有name和value兩個(gè)屬性
Cookie的maxAge(掌握):Cookie的最大生命垮卓,即Cookie可保存的最大時(shí)長垫桂。以秒為單位,例如:cookie.setMaxAge(60)表示這個(gè)Cookie會(huì)被瀏覽器保存到硬盤上60秒
> maxAge>0:瀏覽器會(huì)把Cookie保存到客戶機(jī)硬盤上粟按,有效時(shí)長為maxAge的值決定诬滩。
> maxAge<0:Cookie只在瀏覽器內(nèi)存中存在,當(dāng)用戶關(guān)閉瀏覽器時(shí)灭将,瀏覽器進(jìn)程結(jié)束疼鸟,同時(shí)Cookie也就死亡了。
> maxAge=0:瀏覽器會(huì)馬上刪除這個(gè)Cookie宗侦!
- Cookie的path(理解):
> Cookie的path并不是設(shè)置這個(gè)Cookie在客戶端的保存路徑S尥巍R涫础矾利!
> Cookie的path由服務(wù)器創(chuàng)建Cookie時(shí)設(shè)置
> 當(dāng)瀏覽器訪問服務(wù)器某個(gè)路徑時(shí),需要?dú)w還哪些Cookie給服務(wù)器呢馋袜?這由Cookie的path決定男旗。
> 瀏覽器訪問服務(wù)器的路徑,如果包含某個(gè)Cookie的路徑欣鳖,那么就會(huì)歸還這個(gè)Cookie察皇。
例如:
<> aCookie.path=/day11_1/; bCookie.path=/day11_1/jsps/; cCookie.path=/day11_1/jsps/cookie/;
<> 訪問:/day11_1/index.jsp時(shí),歸還:aCookie
<> 訪問:/day11_1/jsps/a.jsp時(shí)泽台,歸還:aCookie什荣、bCookie
<> 訪問:/day11_1/jsps/cookie/b.jsp時(shí),歸還:aCookie怀酷、bCookie稻爬、cCookie
Cookie的path默認(rèn)值:當(dāng)前訪問路徑的父路徑。例如在訪問/day11_1/jsps/a.jsp時(shí)蜕依,響應(yīng)的cookie桅锄,那么這個(gè)cookie的默認(rèn)path為/day11_1/jsps/
- Cookie的domain(了解)
> domain用來指定Cookie的域名琉雳!當(dāng)多個(gè)二級(jí)域中共享Cookie時(shí)才有用。
> 例如友瘤;www.baidu.com翠肘、zhidao.baidu.com、news.baidu.com辫秧、tieba.baidu.com之間共享Cookie時(shí)可以使用domain
> 設(shè)置domain為:cookie.setDomain(".baidu.com");
> 設(shè)置path為:cookie.setPath("/");
Cookie中不能存在中文J丁!茶没!
// 保存
Cookie c = new Cookie("username", URLEncoder.encode("張三", "utf-8"));//出錯(cuò)肌幽!
response.addCookie(c);
// 獲取
Cookie[] cs = request.getCookies();
if(cs != null) {
for(Cookie c : cs){
if("username".equals(c.getName())) {
String username = c.getValue();
username = URLDecoder.decode(username, "utf-8");
}
}
}
============================================
1.5 HttpSession
1.5.1 HttpSession概述
HttpSession是由JavaWeb提供的,用來會(huì)話跟蹤的類抓半。session是服務(wù)器端對(duì)象喂急,保存在服務(wù)器端!5亚蟆廊移!
HttpSession是Servlet三大域?qū)ο笾?request、session探入、application(ServletContext))狡孔,所以它也有setAttribute()、getAttribute()蜂嗽、removeAttribute()方法
HttpSession底層依賴Cookie苗膝,或是URL重寫!
1.5.2 HttpSession的作用
- 會(huì)話范圍:會(huì)話范圍是某個(gè)用戶從首次訪問服務(wù)器開始植旧,到該用戶關(guān)閉瀏覽器結(jié)束辱揭!
會(huì)話:一個(gè)用戶對(duì)服務(wù)器的多次連貫性請求!所謂連貫性請求病附,就是該用戶多次請求中間沒有關(guān)閉瀏覽器问窃!
- 服務(wù)器會(huì)為每個(gè)客戶端創(chuàng)建一個(gè)session對(duì)象,session就好比客戶在服務(wù)器端的賬戶完沪,它們被服務(wù)器保存到一個(gè)Map中域庇,這個(gè)Map被稱之為session緩存!
Servlet中得到session對(duì)象:HttpSession session = request.getSession();
Jsp中得到session對(duì)象:session是jsp內(nèi)置對(duì)象之下覆积,不用創(chuàng)建就可以直接使用听皿!
- session域相關(guān)方法:
> void setAttribute(String name, Object value);
> Object getAttribute(String name);
> void removeAttribute(String name);
1.5.3 HttpSession原理(理解)
- request.getSession()方法:
> 獲取Cookie中的JSESSIONID:
<> 如果sessionId不存在,創(chuàng)建session宽档,把session保存起來尉姨,把新創(chuàng)建的sessionId保存到Cookie中
<> 如果sessionId存在,通過sessionId查找session對(duì)象雌贱,如果沒有查找到啊送,創(chuàng)建session偿短,把session保存起來,把新創(chuàng)建的sessionId保存到Cookie中
<> 如果sessionId存在馋没,通過sessionId查找到了session對(duì)象昔逗,那么就不會(huì)再創(chuàng)建session對(duì)象了。
<> 返回session
如果創(chuàng)建了新的session篷朵,瀏覽器會(huì)得到一個(gè)包含了sessionId的Cookie勾怒,這個(gè)Cookie的生命為-1,即只在瀏覽器內(nèi)存中存在声旺,如果不關(guān)閉瀏覽器笔链,那么Cookie就一直存在。
下次請求時(shí)腮猖,再次執(zhí)行request.getSession()方法時(shí)鉴扫,因?yàn)榭梢酝ㄟ^Cookie中的sessionId找到session對(duì)象,所以與上一次請求使用的是同一session對(duì)象澈缺。
服務(wù)器不會(huì)馬上給你創(chuàng)建session坪创,在第一次獲取session時(shí),才會(huì)創(chuàng)建姐赡!request.getSession();
request.getSession(false)莱预、request.getSession(true)、request.getSession()项滑,后兩個(gè)方法效果相同依沮,
第一個(gè)方法:如果session緩存中(如果cookie不存在),不存在session枪狂,那么返回null危喉,而不會(huì)創(chuàng)建session對(duì)象。
1.5.4 HttpSession其他方法:
String getId():獲取sessionId摘完;
int getMaxInactiveInterval():獲取session可以的最大不活動(dòng)時(shí)間(秒)姥饰,默認(rèn)為30分鐘傻谁。當(dāng)session在30分鐘內(nèi)沒有使用孝治,那么Tomcat會(huì)在session池中移除這個(gè)session;
void invalidate():讓session失效审磁!調(diào)用這個(gè)方法會(huì)被session失效谈飒,當(dāng)session失效后,客戶端再次請求态蒂,服務(wù)器會(huì)給客戶端創(chuàng)建一個(gè)新的session杭措,并在響應(yīng)中給客戶端新session的sessionId;
boolean isNew():查看session是否為新钾恢。當(dāng)客戶端第一次請求時(shí)手素,服務(wù)器為客戶端創(chuàng)建session鸳址,但這時(shí)服務(wù)器還沒有響應(yīng)客戶端,也就是還沒有把sessionId響應(yīng)給客戶端時(shí)泉懦,這時(shí)session的狀態(tài)為新稿黍。
1.5.5 web.xml中配置session的最大不活動(dòng)時(shí)間
<session-config>
<session-timeout>30</session-timeout>
</session-config>
1.5.6 案例1:演示session中會(huì)話的多次請求中共享數(shù)據(jù)
AServlet:向session域中保存數(shù)據(jù)
BServlet:從session域中獲取數(shù)據(jù)
演示:
> 第一個(gè)請求:訪問AServlet
> 第二個(gè)請求:訪問BServlet
1.5.7 案例2:演示保存用戶登錄信息(精通)
- 案例相關(guān)頁面和Servlet:
> login.jsp:登錄頁面
> succ1.jsp:只有登錄成功才能訪問的頁面
> succ2.jsp:只有登錄成功才能訪問的頁面
> LoginServlet:校驗(yàn)用戶是否登錄成功!
- 各頁面和Servlet內(nèi)容:
> login.jsp:提供登錄表單崩哩,提交表單請求LoginServlet
> LoginServlet:獲取請求參數(shù)巡球,校驗(yàn)用戶是否登錄成功
<> 失敗:保存錯(cuò)誤信息到request域邓嘹,轉(zhuǎn)發(fā)到login.jsp(login.jsp顯示request域中的錯(cuò)誤信息)
<> 成功:保存用戶信息到session域中酣栈,重定向到succ1.jsp頁面,顯示session域中的用戶信息
> succ1.jsp:從session域獲取用戶信息汹押,如果不存在矿筝,顯示“您還沒有登錄”。存在則顯示用戶信息
> succ2.jsp:從session域獲取用戶信息棚贾,如果不存在跋涣,顯示“您還沒有登錄”。存在則顯示用戶信息
只要用戶沒有關(guān)閉瀏覽器鸟悴,session就一直存在陈辱,那么保存在session中的用戶信息也就一起存在!那么用戶訪問succ1和succ2就會(huì)通過细诸!
1.6 JSP
1.6.1 JSP三大指令
一個(gè)jsp頁面中沛贪,可以有0~N個(gè)指令的定義!
- page --> 最復(fù)雜:%@page language="java" info="xxx"...%
- pageEncoding和contentType:
> pageEncoding:它指定當(dāng)前jsp頁面的編碼震贵,只要不說謊利赋,就不會(huì)有亂碼!在服務(wù)器要把jsp編譯成.java時(shí)需要使用pageEncoding!
> contentType:它表示添加一個(gè)響應(yīng)頭:Content-Type猩系!等同與response.setContentType("text/html;charset=utf-8");
> 如果兩個(gè)屬性只提供一個(gè)媚送,那么另一個(gè)的默認(rèn)值為設(shè)置那一個(gè)。
> 如果兩個(gè)屬性都沒有設(shè)置寇甸,那么默認(rèn)為iso
import:導(dǎo)包塘偎!可以出現(xiàn)多次
errorPage和isErrorPage
> errorPage:當(dāng)前頁面如果拋出異常,那么要轉(zhuǎn)發(fā)到哪一個(gè)頁面拿霉,由errorPage來指定
> isErrorPage:它指定當(dāng)前頁面是否為處理錯(cuò)誤的頁面吟秩!當(dāng)該屬性為true時(shí),這個(gè)頁面會(huì)設(shè)置狀態(tài)碼為500绽淘!而且這個(gè)頁面可以使用9大內(nèi)置對(duì)象中的exception!
<error-page>
<error-code>404</error-code>
<location>/error/errorPage.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/errorPage.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.RuntimeException</exception-type>
<location>/index.jsp</location>
</error-page>
- autoFlush和buffer
autoFlush:指定jsp的輸出流緩沖區(qū)滿時(shí)涵防,是否自動(dòng)刷新!默認(rèn)為true沪铭,如果為false壮池,那么在緩沖區(qū)滿時(shí)拋出異常偏瓤!
buffer:指定緩沖區(qū)大小,默認(rèn)為8kb椰憋,通常不需要修改硼补!
isELIgnored:是否忽略el表達(dá)式,默認(rèn)值為false熏矿,不忽略已骇,即支持!
基本沒有:
language:指定當(dāng)前jsp編譯后的語言類型票编,默認(rèn)值為java褪储。
info:信息!
isThreadSafe:當(dāng)前的jsp是否支持并發(fā)訪問慧域!
session:當(dāng)前頁面是否支持session鲤竹,如果為false,那么當(dāng)前頁面就沒有session這個(gè)內(nèi)置對(duì)象昔榴!
extends:讓jsp生成的servlet去繼承該屬性指定的類辛藻!
- include --> 靜態(tài)包含
與RequestDispatcher的include()方法的功能相似!
<%@include%> 它是在jsp編譯成java文件時(shí)完成的互订!他們共同生成一個(gè)java(就是一個(gè)servlet)文件吱肌,然后再生成一個(gè)class!
RequestDispatcher的include()是一個(gè)方法仰禽,包含和被包含的是兩個(gè)servlet氮墨,即兩個(gè).class!他們只是把響應(yīng)的內(nèi)容在運(yùn)行時(shí)合并了吐葵!
作用:把頁面分解了规揪,使用包含的方式組合在一起,這樣一個(gè)頁面中不變的部分温峭,就是一個(gè)獨(dú)立jsp猛铅,而我們只需要處理變化的頁面。
- taglib --> 導(dǎo)入標(biāo)簽庫
- 兩個(gè)屬性:
prefix:指定標(biāo)簽庫在本頁面中的前綴凤藏!由我們自己來起名稱奸忽!
uri: 指定標(biāo)簽庫的位置!
<%@taglib prefix="s" uri="/struts-tags"%> 前綴的用法<s:text>
=========================================
1.6.2 JSP九大內(nèi)置對(duì)象
out --> jsp的輸出流清笨,用來向客戶端響應(yīng)
page --> 當(dāng)前jsp對(duì)象月杉! 它的引用類型是Object刃跛,即真身中有如下代碼:Object page = this;
config --> 它對(duì)應(yīng)真身中的ServletConfig對(duì)象抠艾!
pageContext --> 一個(gè)頂9個(gè)!
request --> HttpServletRequest
response --> HttpServletResponse
exception --> Throwable
session --> HttpSession
application --> ServletContext
- pageContext
一個(gè)頂9個(gè)桨昙!
Servlet中有三大域检号,而JSP中有四大域腌歉,它就是最后一個(gè)域?qū)ο螅?/p>
ServletContext:整個(gè)應(yīng)用程序
session:整個(gè)會(huì)話(一個(gè)會(huì)話中只有一個(gè)用戶)
request:一個(gè)請求鏈!
pageContext:一個(gè)jsp頁面齐苛!這個(gè)域是在當(dāng)前jsp頁面和當(dāng)前jsp頁面中使用的標(biāo)簽之間共享數(shù)據(jù)翘盖!
域?qū)ο?/p>
代理其他域:pageContext.setAttribute("xxx", "XXX", PageContext.SESSION_SCOPE);
全域查找:pageContext.findAttribute("xxx");從小到大,依賴查找凹蜂!
獲取其他8個(gè)內(nèi)置對(duì)象:
=========================================
1.6.3 JSP動(dòng)作標(biāo)簽
這些jsp的動(dòng)作標(biāo)簽馍驯,與html提供的標(biāo)簽有本質(zhì)的區(qū)別。
* 動(dòng)作標(biāo)簽是由tomcat(服務(wù)器)來解釋執(zhí)行玛痊!它與java代碼一樣汰瘫,都是在服務(wù)器端執(zhí)行的!
* html由瀏覽器來執(zhí)行擂煞!
<jsp:forward>:轉(zhuǎn)發(fā)混弥!它與RequestDispatcher的forward方法是一樣的,一個(gè)是在Servlet中使用对省,一個(gè)是在jsp中使用蝗拿!
<jsp:include>:包含:它與RequestDispatcher的include方法是一樣的,一個(gè)是在Servlet中使用蒿涎,一個(gè)是在jsp中使用哀托!
%@include和<jsp:include>有什么不同!
- <jsp:param>:它用來作為forward和include的子標(biāo)簽劳秋!用來給轉(zhuǎn)發(fā)或包含的頁面?zhèn)鬟f參數(shù)萤捆!
=========================================
1.7 JavaBean
1.7.1 JavaBean的規(guī)范:
必須要有一個(gè)默認(rèn)構(gòu)造器
提供get/set方法,如果只有g(shù)et方法俗批,那么這個(gè)屬性是只讀屬性俗或!
屬性:有g(shù)et/set方法的成員,還可以沒有成員岁忘,只有g(shù)et/set方法辛慰。屬性名稱由get/set方法來決定!而不是成員名稱干像!
方法名稱滿足一定的規(guī)范帅腌,那么它就是屬性!boolean類型的屬性麻汰,它的讀方法可以是is開頭速客,也可以是get開頭!
1.7.2 內(nèi)饰弼辍:
內(nèi)省類 --> Bean信息 --> 屬性描述符 --> 屬性的get/set對(duì)應(yīng)的Method溺职! --- > 可以反射了!
commons-beanutils,它是依賴內(nèi)省完成浪耘!
- 導(dǎo)包:
commons-beanutils.jar
commons-logging.jar
BeanUtils.getProperty(Object bean, String propertyName)
BeanUtils.setProperty(Object bean, String propertyName, String propertyValue)
BeanUtils.populate(Map map, Object bean)
CommontUtils.toBean(Map map, Class class)
注意導(dǎo)包的時(shí)候后面寫.*
1.7.3 javaBean導(dǎo)航
<%
Address address = new Address();
address.setCity("北京");
address.setStreet("西三旗");
Employee emp = new Employee();
emp.setName("李小四");
emp.setSalary(123456);
emp.setAddress(address);
request.setAttribute("emp", emp);
%>
1.7.4 jsp中與javaBean相關(guān)的標(biāo)簽
<jsp:useBean>
--> 創(chuàng)建或查詢 bean<jsp:useBean id="user1" class="cn.itcast.domain.User" scope="session"/>
在 session 域中查找名為user1的bean乱灵,如果不存在,創(chuàng)建之<jsp:useBean id="user1" class="cn.itcast.domain.User" scope="session"/>
創(chuàng)建<jsp:useBean id="user1" class="cn.itcast.domain.User" scope="session"/>
查找<jsp:setProperty>
?4<jsp:setProperty property="username" na=me="user1" value="admin"/>
設(shè)置名為user1的這個(gè)javabean的username屬性值為admin<jsp:getProperty>
<jsp:getProperty property="username" name="user1"/>
獲取名為user1的javabean的名為username屬性值
=========================================
1.8 EL表達(dá)式
1.8.1 EL基本概念
EL是JSP內(nèi)置的表達(dá)式語言七冲!
jsp2.0開始痛倚,不讓再使用java腳本,而是使用el表達(dá)式和動(dòng)態(tài)標(biāo)簽來替代java腳本澜躺!
EL替代的是<%= ... %>蝉稳,也就是說,EL只能做輸出掘鄙!
1.8.2 EL表達(dá)式讀取四大域
- ${xxx} 颠区,全域查找名為 xxx 的屬性,如果不存在通铲,輸出空字符串毕莱,而不是 null。
* ${pageScope.xxx}颅夺、${requestScope.xxx}朋截、${sessionScope.xxx}、${applicationScope.xxx}吧黄,指定域獲取屬性部服!
<h3>使用el獲取request域的emp</h3>
${requestScope.emp.address.street }<!-- request.getAttribute("emp").getAddress().getStreet() --><br/>
1.8.3 EL表達(dá)式與內(nèi)置對(duì)象
EL可以輸出的東西都在11個(gè)內(nèi)置對(duì)象中!11個(gè)內(nèi)置對(duì)象拗慨,其中10個(gè)是Map廓八!pageContext不是map,它就是PageContext類型赵抢,1個(gè)項(xiàng)9個(gè)剧蹂。
我們已經(jīng)學(xué)習(xí)了四個(gè)
param:對(duì)應(yīng)參數(shù),它是一個(gè)Map烦却,其中key參數(shù)名宠叼,value是參數(shù)值,適用于單值的參數(shù)其爵。
paramValues:對(duì)應(yīng)參數(shù)冒冬,它是一個(gè)Map,其中key參數(shù)名摩渺,value是多個(gè)參數(shù)值简烤,適用于多值的參數(shù)。
header:對(duì)應(yīng)請求頭摇幻,它是一個(gè)Map横侦,其中key表示頭名稱挥萌,value是單個(gè)頭值,適用于單值請求頭
headerValues:對(duì)應(yīng)請求頭丈咐,它是一個(gè)Map瑞眼,其中key表示頭名稱龙宏,value是多個(gè)頭值棵逊,適用于多值請求頭
initParam:獲取<context-param>內(nèi)的參數(shù)!
<context-param>
<param-name>xxx</param-name>
<param-value>XXX</param-value>
</context-param>
<context-param>
<param-name>yyy</param-name>
<param-value>YYY</param-value>
</context-param>
${initParam.xxx}
cookie:Map<String,Cookie>類型银酗,其中key是cookie的name辆影,value是cookie對(duì)象。 ${cookie.username.value}
pageContext:它是PageContext類型黍特!${pageContext.request.contextPath}
=========================================
1.8.4 EL函數(shù)庫(由JSTL提供的)
- 導(dǎo)入標(biāo)簽庫:
<%@ tablib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
String toUpperCase(String input):把參數(shù)轉(zhuǎn)換成大寫
String toLowerCase(String input):把參數(shù)轉(zhuǎn)換成小寫
int indexOf(String input, String substring):從大串蛙讥,輸出小串的位置!
boolean contains(String input, String substring):查看大串中是否包含小串
boolean containsIgnoreCase(String input, String substring):忽略大小寫的灭衷,是否包含
boolean startsWith(String input, String substring):是否以小串為前綴
boolean endsWith(String input, String substring):是否以小串為后綴
String substring(String input, int beginIndex, int endIndex):截取子串
String substringAfter(String input, String substring):獲取大串中次慢,小串所在位置后面的字符串
substringBefore(String input, String substring):獲取大串中,小串所在位置前面的字符串
String escapeXml(String input):把input中“<”翔曲、">"迫像、"&"、"'"瞳遍、"""闻妓,進(jìn)行轉(zhuǎn)義
String trim(String input):去除前后空格
String replace(String input, String substringBefore, String substringAfter):替換
String[] split(String input, String delimiters):分割字符串,得到字符串?dāng)?shù)組
int length(Object obj):可以獲取字符串掠械、數(shù)組由缆、各種集合的長度!
String join(String array[], String separator):聯(lián)合字符串?dāng)?shù)組猾蒂!
=========================================
1.8.5 EL自定義函數(shù)庫
寫一個(gè)java類均唉,類中可以定義0~N個(gè)方法,但必須是static肚菠,而且有返回值的浸卦!
在WEB-INF目錄下創(chuàng)建一個(gè)tld文件
<function>
<name>fun</name>
<function-class>cn.itcast.fn.MyFunction</function-class>
<function-signature>java.lang.String fun()</function-signature>
</function>
- 在jsp頁面中導(dǎo)入標(biāo)簽庫
<%@ taglib prefix="it" uri="/WEB-INF/tlds/itcast.tld" %>
- 在jsp頁面中使用自定義的函數(shù):
${it:fun() }