本文目錄:
- JSP基礎
- Cookie
- HttpSession
JSP基礎
JSP(Java Server Pages)是JavaWeb服務器端的動態資源。它與html頁面的作用是相同的,顯示數據和獲取數據。
jsp和Servlet的常見分工
(jsp) request -- servlet -- (jsp) response
- JSP
- 作為請求發起頁面,把來自用戶的post/get等請求發送給servlet:例如頁面內含有表單、超鏈接
- 作為請求結束頁面,接受servlet的數據,顯示給用戶。
- Servlet
- 獲取jsp發送來的請求參數
- 處理請求,得到處理后的數據
- 把結果保存到request中
- 轉發到顯示結果的JSP
jsp的作用
- Servlet
- 優點:動態資源(html靜態頁面不能包含動態信息)
- 缺點:不適合設置html代碼,需要大量的response.getWriter().print("<html>")
- jsp(java server pages)
- jsp文件內容:直接在原有html代碼的基礎上,添加java腳本。很方便。
jsp的組成 jsp = html + java腳本 + jsp標簽(指令)
JSP標簽 有2種:
JSP指令元素<%@ %>
JSP動作元素<jsp: />
-
jsp的9大內置對象(無需創建即可使用的對象):
- request
- response
- out
- session
- application 和tomcat進程“共生死”
- pageContext
- config
- page
- exception
3種java腳本
<% java代碼片段 %>
<!--,常用
可寫0到n條Java語句
方法內能寫什么,它就可以寫什么
-->
<%=表達式 %>
<!--java表達式,用于輸出一條表達式(或變量)的結果。-->
response.getWriter().print( ... );
<!--這里能放什么,它就可以放什么!
比如某個具有返回值的函數 func1()
-->
<%!聲明 成員變量等 %>
<!--聲明,用來創建類的成員變量和成員方法(基本不用,但容易被考到)
類體中可以放什么,它就可以放什么!
Class man{
成員變量
成員方法
構造器
構造代碼塊
靜態塊
內部類
}
-->
out.print()和out.write() 幾乎沒有區別:
String s = null;
out.print(s); // outputs the text "null" 處理空指針異常,輸出字符串“null”。
out.write(s); // NullPointerException 不處理該異常。
jsp注釋
<%-- 當服務器把jsp編譯成java文件前就沒有這些注釋了! --%>
<!-- html注釋會發到客戶端瀏覽器。 -->
案例:演示jsp中java腳本的使用!
案例:演示jsp與servlet分工!
jsp原理(理解)
- 當jsp頁面第一次被訪問時:
- 1.服務器會把jsp編譯成java文件(這個java其實是一個servlet類)
- 2.再把java編譯成.class
- 3.創建該類對象
- 4.最后調用它的service()方法
- 第二次請求某jsp時,直接調用service()方法。
jsp實質是一種特殊的Servlet
在tomcat/work/Catalina目錄下可以找到 jsp 對應的 .java 源代碼,和生成的.class文件。
- 查看jsp對應java文件:
- .java語句,方法體的最上面,聲明了9大內置對象,賦值。
- 原封不動的把程序員寫的代碼放到方法體下面。
- html語句,全是這樣輸出的:
out.wirte("字符串");
Cookie
Http協議與Cookie
- Cookie是HTTP協議制定的!
服務器保存Cookie到瀏覽器,再下次瀏覽器請求服務器時,會帶上Cookie - 由服務器創建保存到客戶端瀏覽器的一個鍵值對!
”key=value“
服務器保存Cookie的響應頭
Set-Cookie: aaa=AAA Set-Cookie: bbb=BBB
response.addHeader("Set-Cookie", "aaa=AAA");
response.addHeader("Set-Cookie", "bbb=BBB");
- 當客戶端瀏覽器發送request給服務器時,會帶上Cookie:
Cookie: aaa=AAA; bbb=BBB
- Http協議規定(很多瀏覽器都會在一定范圍內違反HTTP規定)
- 1個Cookie最大4KB
- 1個服務器最多向1個瀏覽器保存20個Cookie
- 1個瀏覽器最多可以保存300個Cookie
Cookie的用途
注意Cookie不跨瀏覽器!
- 跟蹤客戶端狀態
- 保存購物車信息
- 只保存上次的登錄名,方便登錄。
JavaWeb中使用Cookie
- 原始方式(了解)
- 使用response發送Set-Cookie響應頭
- 使用request獲取Cookie請求頭
- 便捷方式(重要!)
repsonse.addCookie()//讓瀏覽器端保存Cookie
request.getCookies()//獲取瀏覽器端帶來的Cookie
//如果HTTP請求沒有帶來cookie則返回null
服務器端發送response給客戶端瀏覽器,http響應包頭中有Set-Cookie頭,格式如下:
Set-Cookie: key1=value2
Set-Cookie: key1=value2
Set-Cookie: key1=value2
客戶端發送request給服務器時,http請求包頭里面有Cookie頭,格式如下:
Cookie: key1=value1; key2=value2; key3=value3
Cookie詳解
- Cookie不只有name和value兩個屬性
- Cookie的maxAge
- maxAge>0:Cookie的最大生命。瀏覽器會把Cookie保存到客戶機硬盤上,有效時長為maxAge的值,以秒為單位。
cookie.setMaxAge(60)
- maxAge<0:Cookie只在瀏覽器內存中存在(瀏覽器進程結束,Cookie消失)
- maxAge=0:立即刪除同名cookie
- maxAge>0:Cookie的最大生命。瀏覽器會把Cookie保存到客戶機硬盤上,有效時長為maxAge的值,以秒為單位。
- Cookie的path
- Cookie的path決定:當瀏覽器訪問服務器某個路徑時,帶上哪些Cookie
- Cookie的path不可能是設置這個Cookie在客戶端的保存路徑!
- Cookie的path由響應包response創建Cookie時設置
- 瀏覽器訪問服務器的路徑,如果包含某個Cookie的路徑,那么就會帶上這個Cookie。
例如:服務器端設置
aCookie.path=/day11_1/;
bCookie.path=/day11_1/aaa/;
cCookie.path=/day11_1/aaa/bbb/;
客戶端瀏覽器
訪問:域名/day11_1/anyname.jsp 時帶上aCookie
訪問:域名/day11_1/aaa/anyname.jsp 時帶上aCookie、bCookie
訪問:域名/day11_1/aaa/bbb/anyname.jsp 時帶上aCookie、bCookie、cCookie
- Cookie的path默認值:當前訪問路徑的父路徑。
如訪問/day11_1/jsps/a.jsp時響應包設置了cookie,該cookie的默認path為/day11_1/jsps/
- Cookie的domain用來指定服務器設置的Cookie給哪些域名!當多個二級域中共享Cookie時才需要用
例如這些二級域名之間需要共享cookie:www.baidu.com、zhidao.baidu.com、news.baidu.com、tieba.baidu.com
服務器端:
cookie.setDomain(".baidu.com");//設置domain 直接省略掉二級域名的不同之處
cookie.setPath("/");//設置path
- 自己測試,步驟:
修改本機hosts文件
127.0.0.1 111.x.com
123.0.0.1 222.x.com在${CATALINA_HOME}/conf/server.xml中添加配置
<Host name="news.qdmmy6.com" appBase="news"
unpackWARs="true" autoDeploy="true">
</Host>
<Host name="tieba.qdmmy6.com" appBase="tieba"
unpackWARs="true" autoDeploy="true">
</Host>把tieba和news兩個目錄copy到${CATALINA_HOME}下
Cookie保存中文
Cookie的name和value都是不能直接保存中文的,但可以把中文轉換成URL編碼后保存到Cookie(name和value中)
String name = "姓名";
String value = "張三";
name = URLEncoder.encode(name, "utf-8");
value = URLEncoder.encode(value, "utf-8");
Cookie c = new Cookie(name, value);
response.addCookie(c);
//獲取Cookie:使用URL解碼即可。
Cookie[] cs = request.getCookies();
if(cs != null) {
for(Cookie c : cs) {
String name = URLDecoder.decode(c.getName(), "utf-8");
String value = URLDecoder.decode(c.getValue(), "utf-8");
System.out.println(name + "=" + value);
}
}
HttpSession(重點)
HttpSession概述
HttpSession是由JavaWeb提供的,用來會話跟蹤的類。session是服務器端對象,保存在服務器端!!!
HttpSession底層依賴Cookie或URL重寫!
HttpSession是Servlet三大域對象之一
三大域對象
-
request
- 每一次請求都會創建一個request
- 請求鏈共享數據 可把request發給多個Servlet
-
session
- 會話是同一個用戶在瀏覽器打開后關閉前對服務器的多次請求。
-
application(ServletContext)
- 程序存在,保存在這里的內容就一直存在
三大域對象都有方法:
void setAttribute(String name, Object value);
Object getAttribute(String name);
void removeAttribute(String name);
session是域對象,所以有setAttribute()和getAttribute()等方法
服務器會為每個會話創建一個session對象,所以session中的數據可供當前會話中所有servlet共享。
會話 會話追蹤
- 會話:同一個用戶在瀏覽器打開后關閉前對服務器的多次請求。
- 會話范圍:某個用戶從首次訪問服務器開始,到該用戶關閉瀏覽器結束!
- 會話方便了服務器端共享數據!對客戶端瀏覽器只在Cookie里只有一個session的ID,服務器端在這個session中設置的一些值對用戶均不可見。
- 會話跟蹤技術:在一次會話中共享數據。
HTTP是無狀態協議,每個請求之間無法共享數據。這就無法知道會話什么時候開始,什么時候結束,也無法確定發出請求的用戶身份。這說明需要使用額外的手段來跟蹤會話! - session緩存:服務器會為每個客戶端創建一個session對象,session就好比客戶在服務器端的賬戶,它們被服務器保存到一個Map中,這個Map被稱之為session緩存!
Servlet中得到session對象
HttpSession session = request.getSession();
Jsp中得到session對象
session是jsp內置對象,不用創建,直接使用!如
<%session.setAttribute("aa","bb")%>
案例1:session 多次請求中共享數據
- AServlet:向session域中保存數據
- BServlet:從session域中獲取數據
- 演示:
第一個請求:訪問AServlet
第二個請求:訪問BServlet
案例2:session 保存用戶登錄信息(精通)
-
案例相關頁面和Servlet:
- login.jsp:登錄頁面
- succ1.jsp:只有登錄成功才能訪問的頁面
- succ2.jsp:只有登錄成功才能訪問的頁面
- LoginServlet:校驗用戶是否登錄成功!
-
各頁面和Servlet內容:
- login.jsp:提供登錄表單,提交表單請求LoginServlet
- LoginServlet:獲取請求參數,校驗用戶是否登錄成功
- 失敗:保存錯誤信息到request域,轉發到login.jsp(login.jsp顯示request域中的錯誤信息)
- 成功:保存用戶信息到session域中,重定向到succ1.jsp頁面,顯示session域中的用戶信息
- succ1.jsp:從session域獲取用戶信息,如果不存在,顯示“您還沒有登錄”。存在則顯示用戶信息
- succ2.jsp:從session域獲取用戶信息,如果不存在,顯示“您還沒有登錄”。存在則顯示用戶信息
只要用戶沒有關閉瀏覽器,session就一直存在,那么保存在session中的用戶信息也就一起存在!那么用戶訪問succ1和succ2就會通過!
HttpSession原理(理解)
-
request.getSession()方法
- 獲取Cookie中的JSESSIONID(唯一標識)
- 如果Cookie中沒有sessionId,從url參數中獲取 格式為;JsessionID=也沒有時,服務器創建一個session并保存,把新創建的sessionId設置到瀏覽器Cookie中,這個Cookie的生命為-1,即只在瀏覽器內存中存在!
- 關閉瀏覽器前,再次請求,服務器端執行request.getSession()方法,通過客戶端帶Cookie的請求,得到Cookie中的sessionId,服務器的session對象與上一次請求使用的是同一session對象。
- 如果sessionId存在,但通過sessionId沒有找到session對象(可能超時被服務器刪除了),創建session保存到服務器,把新創建的sessionId保存到客戶端瀏覽器的Cookie中
- 如果sessionId存在,通過sessionId查找到了session對象(不會再創建新session對象)
服務器不會馬上給用戶創建session,在第一次獲取session時才會創建該用戶的session!
session對象是保存在服務器端的,而sessionId是通過Cookie保存在客戶端的。
因為Cookie不能在多個瀏覽器中共享,所以session也不能在多個瀏覽器中共享。
//以下都是Servlet的代碼:
//所有Servlet如果不寫這一行,都不會自動創建session(不會給客戶端Set-Cookie)
request.getSession();//如果是服務器端第一次獲取Session 則向客戶端設置Set-Cookie
request.getSession(false)//如果請求包的cookie帶了JsessionID,則獲取;如果沒帶來sessionid則返回null 且不創建session對象!
request.getSession(true)//有session則得到session,沒有則用Set-cookie設置到瀏覽器
request.getSession()//和上一個方法效果相同
任何JSP頁面,都會自動創建session!
HttpSession其他方法
- String getId()
- 獲取sessionId
- void invalidate()
- 調用這個方法會使session讓當前session失效!當session失效后,客戶端再次請求,服務器會給客戶端創建一個新的session在響應中給客戶端Set-Cookie 新sessionId
- boolean isNew()
- 查看session是否為“New”。當客戶端第一次請求時,服務器為客戶端創建session,但這時服務器還沒有響應客戶端(還沒有發送響應包Set-Cookie:sessionId),此時session的狀態為“New”
- long getCreationTime():返回session的創建時間,返回值為當前時間的毫秒值;
- long getLastAccessedTime():返回session的最后活動時間,返回值為當前時間的毫秒值;
- int getMaxInactiveInterval()
- 獲取session可以的最大不活動時間(秒),默認為30分鐘。當session在30分鐘內沒有使用,那么Tomcat會在session池中移除這個session;
- void setMaxInactiveInterval(int interval):設置session允許的最大不活動時間(秒),如果設置為1秒,那么只要session在1秒內不被使用,那么session就會被移除;
request.getSession().isNew();
web.xml中配置session的最大不活動時間(分鐘數)
<session-config>
<session-timeout>30</session-timeout>
</session-config>
URL重寫(理解)
HttpSession底層依賴Cookie或URL重寫!
session依賴Cookie,目的是讓客戶端發出請求時帶上Cookie(含有sessionId),服務器才能找到對應的session
如果瀏覽器禁用所有cookie,所以服務器給瀏覽器Set-Cookie多少遍都沒用。只能用URL重寫:
讓網站的所有超鏈接(get)、表單(post)中都添加一個名為JSESSIONID的參數,這樣服務器通過獲取請求參數也能得到sessionId,從而找到session對象。
URL重寫,簡單說實質:就是把所有的頁面中的路徑,都使用這條語句處理一下:
response.encodeURL(String url)
該方法會對url進行智能的重寫:
當瀏覽器不支持cookie或支持Cookie但第一次請求時,request中的Cookie沒有帶sessionid,則response.encodeURL()方法會在URL后追加sessionId(比如首次訪問JSP頁面)
當request中的Cookie帶sessionid時,response.encodeURL()方法不會在URL后追加sessionId