關於Session的使用以及Session與瀏覽器交互的原理通通在這了

  
  前面說了Cookie,那麼爲什麼還要說Session呢?因爲在使用Cookie有一個非常大的侷限,就是如果Cookie很多,則無形的增加了客戶端與服務端的數據傳輸量。而且由於瀏覽器對Cookie數量的限制,註定我們不能再Cookie中保存過多的信息,於是Session出現。
  Session的作用就是在服務器端保存一些用戶的數據,然後傳遞給用戶一個名字爲JSESSIONID的Cookie,這個JESSIONID對應這個服務器中的一個Session對象,通過它就可以獲取到保存用戶信息的Session。
那我們具體來看看Session是個什麼鬼。
  

1. Session是什麼

  Session是jsp中九大內置對象之一。其次Session是一個域對象。Session是在服務器端用來保存用戶數據的一種技術。並且Session會話技術是基於Cookie實現的。

  

2.Session的使用

1.1 Session的創建和獲取

Session的創建時機是在request.getSession()方法第一次被調用時。

  • 補充:request.getSession()之後的調用都是獲取已經創建了的Session對象。

Session被創建後,同時還會有一個名爲JSESSIONID的Cookie被創建。
這個Cookie的默認時效就是當前會話。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZaYpcMzu-1575203336945)(尚硅谷_張春勝_會話控制.assets/1558627840672.png)]

下面是創建Session和獲取Session。以及獲取Session的 ID編號,獲取Session是否是新創建的示例代碼:

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class SessionServlet extends BaseServlet {
	private static final long serialVersionUID = 1L;

	public SessionServlet() {
	}

	protected void getSession(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println(request.getHeader("Cookie"));
		
		// 第一次調用就是創建一個新的Session。如果Session已經創建過。就獲取原來的會話。
		HttpSession session = request.getSession();
		// 輸出會話id號,和是否是新創建
		// session.getId()返回Session的唯一編號
		// session.isNew()返回當前Session是否是剛創建的
		response.getWriter().write("session ID:" + session.getId() + "<br/>是否是新的:" + session.isNew());
	}
}

在web.xml文件中的配置:

<servlet>
		<servlet-name>SessionServlet</servlet-name>
		<servlet-class>com.javaWeb.servlet.SessionServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>SessionServlet</servlet-name>
		<url-pattern>/sessionServlet</url-pattern>
	</servlet-mapping>

第一次訪問的結果:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-t6CEn34K-1575203336945)(尚硅谷_張春勝_會話控制.assets/1558627941430.png)]

之後每次訪問的結果:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6djJ7kSw-1575203336947)(尚硅谷_張春勝_會話控制.assets/1558627964822.png)]
  

2.2 Session的工作原理

  Session被創建後,對應的Cookie被保存到瀏覽器中,之後瀏覽器每次訪問項目時都會攜帶該Cookie。

  當我們再次調用時會根據該JSESSIONID獲取已經存在的Cookie,而不是再創建一個新的Cookie。

  如果Cookie中有JSESSIONID,但是JSESSIONID沒有對應的Session存在,則會重新創建一個HttpSession對象,並重新設置JSESSIONID。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-a68FgiGN-1575203336948)(尚硅谷_張春勝_會話控制.assets/1558748151080.png)]

  

2.3 Session數據的存取

Session域對象數據的存取和其他三個域對象PageContext、Request、ServletContext是一樣的。只需要調用下面兩個方法:

  • setAttribute 設置屬性
  • getAttribute 獲取屬性

編寫下面的java代碼去訪問,就可以在Session域中設置屬性,和獲取屬性。

protected void setAttribute(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 第一個調用就是獲取一個新的Session。如果Session已經創建過。就獲取原來的會話。
		HttpSession session = request.getSession();
		// 設置數據
		session.setAttribute("abc", "abc value");
		response.getWriter().write("設置屬性值成功!");
	}
	
	protected void getAttribute(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 第一個調用就是獲取一個新的Session。如果Session已經創建過。就獲取原來的會話。
		HttpSession session = request.getSession();
		// 設置數據
		String value = (String) session.getAttribute("abc");
		response.getWriter().write("獲取abc的屬性值:" + value);
	}

修改session.html 中訪問的連接地址,然後點擊訪問。

<li>
	<a href="sessionServlet?action=setAttribute" target="target">Session域數據的存儲</a>
</li>

<li>
	<a href="sessionServlet?action=getAttribute" target="target">Session域數據的獲取</a>
</li>

訪問後效果圖:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-8Z6I1ahj-1575203336949)(尚硅谷_張春勝_會話控制.assets/1558628097144.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HV5JguV7-1575203336950)(尚硅谷_張春勝_會話控制.assets/1558628140230.png)]
  

2.4 Session 的有效時間

基本原則:

  Session對象在服務器端不能長期保存,它是有時間限制的,超過一定時間沒有被訪問過的Session對象就應該釋放掉,以節約內存。所以Session的有效時間並不是從創建對象開始計時,到指定時間後釋放。而是從最後一次被訪問開始計時,統計其“空閒”的時間。

默認時效:

在tomcat的conf目錄下web.xml配置文件中能夠找到如下配置:

 <!-- ==================== Default Session Configuration ================= -->
   <!-- You can set the default session timeout (in minutes) for all newly   -->
   <!-- created sessions by modifying the value below.                       -->
 
     <session-config>
         <session-timeout>30</session-timeout>
     </session-config>
 

說明:Session對象默認的最長有效時間爲30分鐘。

手動設置1:全局:

  也可以在自己工程的web.xml文件中配置Session會話的超時時間爲10分鐘。在web.xml文件中配置的Session會話超時時間是對所有Session都生效的。

<!-- 設置Session默認的過期時間  -->
<session-config>
	<!-- 以分鐘爲單位。10分鐘超時  -->
    <session-timeout>10</session-timeout>
</session-config>

手動設置2:局部:

  • int getMaxInactiveInterval() 獲取超時時間。以秒爲單位。
  • setMaxInactiveInterval (int seconds) 設置用戶多長時間沒有操作之後就會Session過期。以秒爲單位。
    • 如果是正數。表示用戶在給定的時間內沒有任意操作,Session會話就會過期。
    • 如果是負數。表示Session永不過期。

強制失效:

  • invalidate()

示例代碼:

Session在3秒之後超時
// 第一個調用就是獲取一個新的Session。如果Session已經創建過。就獲取原來的會話。
HttpSession session = request.getSession();
// 設置過期時間爲3秒 
session.setMaxInactiveInterval(3);

Session在1分鐘之後超時
// 第一個調用就是獲取一個新的Session。如果Session已經創建過。就獲取原來的會話。 
HttpSession session = request.getSession();
// 設置過期時間爲1分鐘
session.setMaxInactiveInterval(60);

Session在1小時之後超時
// 第一個調用就是獲取一個新的Session。如果Session已經創建過。就獲取原來的會話。
HttpSession session = request.getSession();
// 設置過期時間爲1小時
session.setMaxInactiveInterval(60 * 60);

Session在1天之後超時
// 第一個調用就是獲取一個新的Session。如果Session已經創建過。就獲取原來的會話。
HttpSession session = request.getSession();
// 設置過期時間爲1天
session.setMaxInactiveInterval(60 * 60 * 24);

Session在1周之後超時
// 第一個調用就是獲取一個新的Session。如果Session已經創建過。就獲取原來的會話。
HttpSession session = request.getSession();
// 設置過期時間爲1周
session.setMaxInactiveInterval(60 * 60 * 24 * 7);

Session永遠不超時
// 第一個調用就是獲取一個新的Session。如果Session已經創建過。就獲取原來的會話。
HttpSession session = request.getSession();
// 設置永遠不超時
session.setMaxInactiveInterval(-1);

Session馬上超時(失效)
// 第一個調用就是獲取一個新的Session。如果Session已經創建過。就獲取原來的會話。
HttpSession session = request.getSession();
// 讓Session對象立即過期
session.invalidate();

  

2.4 Session對象的釋放
  1. Session對象空閒時間達到了目標設置的最大值,自動釋放。
  2. Session對象被強制失效。
  3. Web應用卸載。
  4. 服務器進程停止。

  

2.5 Session的活化和鈍化

  Session機制很好的解決了Cookie的不足,但是當訪問應用的用戶很多時,服務器上就會創建非常多的Session對象,如果不對這些Session對象進行處理,那麼在Session失效之前,這些Session一直都會在服務器的內存中存在。那麼就,就出現了Session活化和鈍化的機制。

Session鈍化:Session在一段時間內沒有被使用時,會將當前存在的Session對象序列化到磁盤上,而不再佔用內存空間。

Session活化:Session被鈍化後,服務器再次調用Session對象時,將Session對象由磁盤中加載到內存中使用。

  如果希望Session域中的對象也能夠隨Session鈍化過程一起序列化到磁盤上,則對象的實現類也必須實現java.io.Serializable接口。不僅如此,如果對象中還包含其他對象的引用,則被關聯的對象也必須支持序列化,否則會拋出異常:java.io.NotSerializableException。

  

2.6 瀏覽器和Session關聯的技術底層內幕

  在前面的演示中我們發現一旦瀏覽器關閉之後,我們再去獲取Session對象就會創建一個新的Session對象。這是怎麼回事呢。現在來看一下這一系列操作過程中的內幕細節。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hJFUXUqO-1575203336951)(尚硅谷_張春勝_會話控制.assets/1558628349795.png)]
  通過上圖的分析,我們不難發現。當瀏覽器關閉之後。只是因爲瀏覽器無法再通知服務器,之前創建的Session的會話id是多少了。所以服務器沒辦法找到對應的Session對象之後,就以爲這是第一次訪問服務器。就創建了新的Session對象返回。

  

3.URL重寫

  在整個會話控制技術體系中,保持JSESSIONID的值主要通過Cookie實現。但Cookie在瀏覽器端可能會被禁用,所以我們還需要一些備用的技術手段,例如:URL重寫。

  URL重寫其實就是將JSESSIONID的值以固定格式附着在URL地址後面,以實現保持JSESSIONID,進而保持會話狀態。這個固定格式是:URL;jsessionid=xxxxxxxxx

例如:

targetServlet;jsessionid=F9C893D3E77E3E8329FF6BD9B7A09957

實現方式:

  • response.encodeURL(String)

  • response.encodeRedirectURL(String)

示例:

//1.獲取Session對象
HttpSession session = request.getSession(); 		
//2.創建目標URL地址字符串
String url = "targetServlet";	
//3.在目標URL地址字符串後面附加JSESSIONID的值
url = response.encodeURL(url); 		
//4.重定向到目標資源
response.sendRedirect(url);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章