前言
session它是一個域對象
三大域對象:ServletContext,Session,Request
注意:
由於客戶端需要接收、記錄和回送Session對象的ID,因此,通常情況下,Session是藉助Cookie技術來傳遞ID屬性的。
一,Session
(1)使用Cookie的問題:
1,最多存儲4k字符串
2,存儲數據不太安全
session的作用:在一次會話的多次請求之間共享數據,將數據保存到服務器
(2)HTTPSession也是一個域對象
void setAttribute(String name, Object value)
在session中保存數據
Object getAttribute(String name)
從session中獲取數據
void removeAttribute(String name)
從session中移除數據
使用:
1. 將數據存儲到session中
// 1.通過rquest對象,獲取session對象
HttpSession session = request.getSession();
// 2.操作session的API,存儲數據
session.setAttribute("username","哈哈,呵呵");
2. 從session中獲取數據
// 1.通過rquest對象,獲取session對象
HttpSession session = request.getSession();
// 2.操作session的API,獲取數據
session.getAttribute("username");
code:
@WebServlet("/SetSession")
public class SetSession extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.通過rquest對象,獲取session對象
HttpSession session = request.getSession();
// 2.操作session的API,存儲數據
session.setAttribute("username", "哈哈,呵呵");
}
}
@WebServlet("/GetSession")
public class GetSession extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.通過rquest對象,獲取session對象
HttpSession session = request.getSession();
// 2.操作session的API,獲取數據
String username = (String) session.getAttribute("username");
System.out.println("GetSession獲取:" + username);
}
}
(3)工作原理
Session基於Cookie技術實現
(4)Session細節
--1.客戶端關閉,服務器不關閉
兩次獲取的Session數據是否爲相同:
* 默認情況下,瀏覽器關閉,再次打開二次獲取的session不一樣
基於cookie實現(瀏覽器關閉,cookie銷燬)
* 設置cookie的存活時間(JESSIONID)
這裏我們代替服務器,做一個小操作,覆蓋這個JSESSIONID,指定持久化時間
--2客戶端不關閉,服務器關閉
兩次獲取的Session數據是否相同?
* 當服務器正常關閉,重啓後,二次獲取的session數據一樣
tomcat這實現以下二個功能
鈍化(序列化)
當服務器正常關閉時,session中的數據,會序列化到磁盤
活化(反序列化)
當服務器開啓後,從磁盤文件中,反序列化到內存中
注意一個問題:Idea問題:
支持鈍化,但是在重新啓動的時候又會刪除了鈍化文件,所以導致會變,解決方法如下:
進行打對勾,強制設置idea重啓時,不清除Session會話
(4)生命週期:
* 何時創建
用戶第一次調用request.getSession()方法時,創建
* 何時銷燬
服務器非正常關閉
非活躍狀態30分鐘後
tomcat進行配置 /tocmat安裝目錄/conf/web.xml
session.invalidate(); 自殺
* 作用範圍
一次會話中,多次請求之間
注意:每一個瀏覽器跟服務器都是獨立的會話...
(5)URL重寫
什麼是url重寫?如果瀏覽器不支持Cookie或用戶阻止了所有Cookie,可以把會話ID附加在HTML頁面中所有的URL上,這些頁面作爲響應發送給客戶。這樣,當用戶單擊URL時,會話ID被自動作爲請求頭的一部分而不是作爲頭行發送回服務器。這種方法稱爲URL重寫(URL rewriting)。作用:當客戶機不接受cookie時,server就使用URL重寫作爲會話跟蹤的基本方式.URL重寫,添加了附加數據(會話ID)到請求的URL路徑上.會話ID必須被編碼作爲該URL字符串中的路徑參數。該參數的名稱爲jsessionid,簡單說就是cookie禁用了jsessionid就不能攜帶,那麼每次請求,都是一個新的session對象。如果想要使用同一個session對象,可以使用url重寫url重寫實現:response. encodeRedirectURL(java.lang.String?url)用於對sendRedirect方法後的url地址進行重寫。response. encodeURL(java.lang.String?url)用於對錶單action和超鏈接的url地址進行重寫
Session基於Cookie技術實現;瀏覽器的Cookie是可以禁用的,一旦禁用了之後,Session就會出現問題了。
開發中,一般我們是不關注用戶的cookie是否禁用的,若用戶禁用了cookie,只能用其他網站了
若真想處理用戶端的cookie禁用,我們可以使用url重寫技術:
@WebServlet("/SessionDemo")
public class SessionDemo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 獲取session對象
HttpSession session = request.getSession();
// 向session中存數據
session.setAttribute("username", "瀏覽器禁用了cookie,也不影響我使用");
// 定義url
String url = "/dsession/GetSession";
// 重寫url,拼接JSESSIONID
url = response.encodeURL(url); // /dsession/GetSession?JSESSIONID=xxsdfasdf
System.out.println(url);
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("<a href='" + url + "'>跳轉到獲取session內容</a>");
}
}
(6)Session特點
1. session存儲數據在服務器
2. session存儲類型任意(Object)
3. session存儲大小和數量沒有限制(相對於內存)
4. session存儲相對安全
cookie和session的選擇
-
cookie將數據保存在瀏覽器端,數據相對不安全.建議敏感的數據不要放在cookie中,而且數據大小是有限制的
-
成本低,對服務器要求不高
-
瀏覽器,解決這個不足,localStroage【項目二中講解...】
-
-
session將數據保存在服務器端,數據相對安全.數據的大小要比cookie中數據靈活很多
-
成本較高,對服務器壓力較大
-
二、三大域對象總結:
request、session、ServletContext
相關API
1. 設置數據
void setAttribute(String name, Object o)
2. 獲取數據
Object getAttribute(String name)
3. 刪除數據
void removeAttribute(String name)
生命週期:
ServletContext域對象
* 何時創建
服務器正常啓動,項目加載時,創建
* 何時銷燬
服務器關閉或項目卸載時,銷燬
* 作用範圍
整個web項目(共享數據)
針對一個WEB應用。一個WEB應用只有一個ServletContext對象,使用該對象保存的數據在整個WEB應用中都有效。創建:服務器啓動的時候.銷燬:服務器關閉的時候或者項目移除的時候.
HTTPSessiont域對象
* 何時創建
用戶第一次調用request.getSession()方法時,創建
用戶訪問攜帶的jsessionid與服務器不匹配時,創建
* 何時銷燬
服務器非正常關閉
未活躍狀態30分鐘
自己消滅自己
* 作用範圍
一次會話中,多次請求間(共享數據)
針對一次會話。使用該對象保存數據,一次會話(多次請求)內數據有效。創建:可以暫且認爲在服務器第一次調用getSession()的時候.服務器創建session的對象.因爲session銷燬後,再次調用getSession()的時候也會創建.銷燬:非正常關閉服務器Session過期了,默認時間是30分鐘.手動調用session的invalidate的方法
HttpServletRequest域對象
* 何時創建
用戶發送請求時,創建
* 何時銷燬
服務器做出響應後,銷燬
* 作用範圍
一次請求中,多次轉發間(共享數據)
針對一次請求。使用該對象保存數據,一次請求(一個頁面,如果是請求轉發多個頁面)內數據有效.創建:客戶端向服務器發送一次請求銷燬:服務器爲這次請求作出響應之後,銷燬request.
總結:
-
能用小的不用大的:request<session<servletContext
-
常用的場景:
-
request:一次查詢的結果(servlet轉發jsp)
-
session:存放當前會話的私有數據
-
用戶登錄狀態
-
驗證碼
-
購物車
-
-
-
servletContext:若需要所有的servlet都能訪問到,才使用這個域對象.
三 。案例:
1.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>goods.jsp</title>
</head>
<body>
<h3>商品列表</h3>
<a href="/dsession/AddCartServlet?name=電視機">電視機</a><br>
<a href="/dsession/AddCartServlet?name=冰箱">冰箱</a><br>
<a href="/dsession/AddCartServlet?name=洗衣機">洗衣機</a><br>
<a href="/dsession/AddCartServlet?name=電腦">電腦</a><br>
</body>
</html>
@WebServlet("/AddCartServlet")
public class AddCartServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8"); // 請求解碼
response.setContentType("text/html;charset=utf-8");// 響應編碼
// 1.獲取請求參數
String product = request.getParameter("name");
// 2.返回結果
response.getWriter().write(product + ",商品已成功加入購物車 <br>");
// 3.從session中獲取購物車
Map<String, Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");
// 4.判斷購物車是否爲空
if (cart == null) {
cart = new HashMap<>();
}
// 5.判斷購物車中是否包含本次添加的商品
if (cart.containsKey(product)) {// 6.存在,數量+1
Integer oldCount = cart.get(product); // 之前數量
cart.put(product, oldCount + 1);// 數量加1
} else { // 7.不存在,直接添加商品,數量爲1
cart.put(product, 1);
}
// 8.重新將購物車,寫入到session中
request.getSession().setAttribute("cart", cart);
// 9.繼續瀏覽
response.getWriter().write("<a href='/dsession/goods.jsp'>繼續瀏覽</a><br>");
// 10.查看購物車
response.getWriter().write("<a href='/dsession/cart.jsp'>查看購物車</a><br>");
}
}
<%@ page import="java.util.Map" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>cart</title>
</head>
<body>
<h3>購物車頁面</h3>
<table border="1" width="200px" align="center">
<tr>
<th>商品</th>
<th>數量</th>
</tr>
<%
// 1.從session中獲取購物車
Map<String,Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");
// 2.判斷是否爲空
if(cart == null){
out.write("購物車內暫時沒有商品<br>");
}else{
for (String s : cart.keySet()) {
out.write("<tr><td>"+s+"</td><td>"+cart.get(s)+"</td></tr>");
}
}
%>
</table>
</body>
</html>
2.用戶登錄
<%--
Created by IntelliJ IDEA.
User: apple
Date: 2020/4/19
Time: 18:55
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登錄</title>
<style type="text/css">
.content{
margin: 0 auto;
height: 600px;
width: 800px;
background-color: white;
}
#errormsg{
font-size: 16px;
color: red;
}
input{
width: 160px;
height: 40px;
}
</style>
</head>
<body>
<div class="content">
<h3>用戶登錄</h3>
<form action="/day20200419/LoginServlet" method="post">
<span id="errormsg"></span><br>
用戶名:<input type="text" name="username"><br>
密碼: <input type="password" name="password"> <br>
驗證碼:<input type="text" name="checkcode"><img src="/d19/CheckCodeServlet" alt="" id="checkcode"> <br>
<input type="submit" value="登錄">
</form>
</div>
<script type="text/javascript">
let elementById = document.getElementById("errormsg");
<%
String errormsg = (String) request.getAttribute("errormsg");
if (errormsg==null||errormsg.length()==0){
errormsg="";
}
%>
elementById.innerHTML=`<%=errormsg%>`;
document.getElementById("checkcode").onclick = function () {
this.src="/d19/CheckCodeServlet?"+new Date().getTime();
}
</script>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: apple
Date: 2020/4/19
Time: 18:55
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登錄成功</title>
</head>
<body>
<h1>您登錄成功了:
<%
String username = (String) request.getSession().getAttribute("username");
out.write(username);
%>
</h1>
</body>
</html>
package com.wsl.zy;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String checkcode = request.getParameter("checkcode");
String codeSession = (String) request.getSession().getAttribute("codeSession");
if (!checkcode.equalsIgnoreCase(codeSession)){
request.setAttribute("errormsg","驗證碼有誤!");
request.getRequestDispatcher("/login.jsp").forward(request,response);
return;
}
//獲取輸入的用戶名和密碼
String username = request.getParameter("username");
String password = request.getParameter("password");
// 判斷用戶名或者密碼不正確
if (!("wsl".equals(username)&&"123456".equals(password))){
request.setAttribute("errormsg","用戶名或者密碼錯誤");
request.getRequestDispatcher("/login.jsp").forward(request,response);
return;
}
request.getSession().setAttribute("username",username);
response.sendRedirect(request.getContextPath()+"/success.jsp");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}