11 - JSP/cookie/HttpSession

本文目錄:

  1. JSP基礎
  2. Cookie
  3. 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
  • 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.setDomain(".baidu.com");//設置domain  直接省略掉二級域名的不同之處
cookie.setPath("/");//設置path
  • 自己測試,步驟:
  1. 修改本機hosts文件
    127.0.0.1 111.x.com
    123.0.0.1 222.x.com

  2. 在${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>

  3. 把tieba和news兩個目錄copy到${CATALINA_HOME}下

  4. 訪問http://news.qdmmy6.com/SaveServlet

  5. 訪問http://tieba.qdmmy6.com/GetServlet

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底層依賴CookieURL重寫

  • 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底層依賴CookieURL重寫

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容