金九銀十已到!Cookie 和 Session的這些知識你必須知道,面試必問!
前言
- 會話:一次會話中包含多次請求和響應
注:一次會話表示瀏覽器第一次給伺服器傳送請求,會話建立,直到有一方斷開為止 - 功能:在一次會話的多次請求間共享資料
- 方式:
(1) 客戶端會話技術:Cookie
(2) 伺服器端會話技術:Session
Cookie
- 概念:將資料儲存到客戶端,客戶端有了Cookie之後,每次請求都會發送給伺服器
- 使用步驟:
(1) 建立Cookie物件,引數中繫結資料(鍵值對)
new Cookie(String name, String value);
(2) 客戶端向伺服器傳送請求後,伺服器向客戶端傳送Cookie物件
response.addCookie(Cookie cookie);
(3) 客戶端收到Cookie後,再次傳送請求時,伺服器獲取從客戶端發來的Cookie物件
Cookie[] request.getCookies();
(4) 伺服器得到Cookie物件後,使用getName與getValue方法得到Cookie物件的資料
程式碼演示:演示Cookie的使用步驟
(1) 此工程Tomcat的設定:
(2) 在src下建立CookieTest1.java
@WebServlet("/CookieTest1") public class CookieTest1 extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1\. 建立Cookie物件,引數類似鍵值對 Cookie cookie = new Cookie("msg", "hello"); //2\. 客戶端向瀏覽器傳送Cookie response.addCookie(cookie); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
(3) 在src下建立CookieTest2.java
@WebServlet("/CookieTest2") public class CookieTest2 extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //3\. 伺服器獲取Cookie物件 Cookie[] cookies = request.getCookies(); //4\. 伺服器獲取Cookie物件的值 for (Cookie cookie : cookies) { String name = cookie.getName(); String value = cookie.getValue(); System.out.println("獲得的Cookie物件的值:" + name + ":" + value); } } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
執行結果:
在瀏覽器位址列先輸入:http://localhost:8080/MyTest/CookieTest1
後輸入:http://localhost:8080/MyTest/CookieTest2
控制檯輸出:獲得的Cookie物件的值:msg:hello
- 上述程式原理:基於響應頭set-cookie和請求頭cookie實現
Cookie的細節
1.一次可以傳送多個Cookie物件,使用response呼叫多次addCookie方法即可
2.Cookie在瀏覽器中儲存的時間:
(1) 預設情況下,當瀏覽器關閉後,Cookie資料被銷燬
(2) 持久化儲存:
使用Cookie物件的setMaxAge(int seconds)方法:
a. 正數:將Cookie資料寫到硬碟中儲存,引數指定存活的秒數,時間到後,資料失效, 此時間指的是建立cookie後開始計時,並不是關閉瀏覽器後才開始計時
b. 負數:預設情況
c. 零:刪除cookie資訊
3.在Tomcat 8之後Cookie可以存中文,但特殊中文字元仍不支援,建議使用URL編碼格式
4.Cookie的共享問題:
(1) 一個Tomcat伺服器中,部署了多個web專案,這些web專案cookie的共享說明:
① 預設情況cookie無法共享
② 使用Cookie物件的setPath(String path)方法設定cookie的獲取範圍:
a. 預設情況,引數是web工程路徑,只有這個工程才可以訪問到,其餘工程無法訪問
b. 如果要共享,可以設定引數為”/” ( /被瀏覽器解析得到的地址為http://ip:port/ )
(2) 不同的Tomcat伺服器間cookie的共享說明:
使用Cookie物件的setDomain(String path)方法,引數設定為一級域名,則一級域名相同的不同伺服器之間Cookie可共享
如:setDomain(“.baidu.com”),則tieba.baidu.com與news.baidu.com等的cookie可共享
Cookie的特點和作用
1.Cookie在客戶端儲存資料,客戶端有了cookie之後,每次傳送請求都會把cookie傳送給伺服器
2.瀏覽器對單個Cookie有大小限制(4KB),對同一個域名下的總cookie數量也有限制(20個)
3.作用:
(1)Cookie一般用於儲存少量的安全性較低的資料
(2)在不登陸的情況下,完成伺服器對客戶端的身份識別,如沒有登入百度賬號的前提下開啟百 度,設定搜尋引擎搜尋時不提示,以後開啟瀏覽器訪問百度時,不會再出現搜尋提示框,原 理:百度伺服器將設定的Cookie資訊儲存到瀏覽器,下次訪問百度時,百度伺服器獲取瀏覽 器的Cookie,根據Cookie的值決定要不要顯示提示框
Cookie案例:記錄上一次訪問的時間
- 需求:訪問一個Servlet程式:
(1) 如果是第一次訪問,提示:您好,歡迎您首次訪問
(2) 如果不是第一次訪問,提示:歡迎回來,您上次的訪問時間是:xxxx - 分析:
使用Cookie來完成,在伺服器判斷客戶端是否有一個名為lastTime的cookie物件
(1) 有,不是第一次訪問:
①在瀏覽器顯示:歡迎回來,您上次的訪問時間是:xxxx
②將現在的時間寫回名為lastTime的cookie中
(2) 無,是第一次訪問:
①在瀏覽器顯示:您好,歡迎您首次訪問
②將現在的時間寫回名為lastTime的cookie中
程式碼演示:使用jsp頁面完成此案例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>CookieTest</title>
</head>
<body>
<%-- jsp頁面通過首行的page標籤自動的設定響應的格式,所以向瀏覽器輸出資料不會亂碼 --%>
<%
//1\. 伺服器獲取客戶端的所有cookie
Cookie[] cookies = request.getCookies();
//2\. 獲取的cookie不一定含有lastTime,用一個布林型別判斷
boolean flag = false;
//3\. 遍歷cookie陣列,判斷是否有lastTime
if(cookies != null && cookies.length > 0) {
for (Cookie cookie :
cookies) {
String cookieName = cookie.getName();
if ("lastTime".equals(cookieName)) {
// 有lastTime,不是第一次訪問
flag = true;
// 將現在的時間寫回lastTime的cookie中
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String format = sdf.format(date);
// 防止亂碼,向cookie物件中儲存的中文資料使用URL編碼
format = URLEncoder.encode(format, "UTF-8");
// 向名為lastTime的cookie中儲存此時間
cookie.setValue(format);
// 設定cookie的存活時間
cookie.setMaxAge(60 * 60 * 24 * 30); //一個月
// 將cookie寫回客戶端
response.addCookie(cookie);
// 獲取此cookie的value時間值,用於寫出時間到瀏覽器
String cookieValue = cookie.getValue();
cookieValue = URLDecoder.decode(cookieValue, "UTF-8");
out.write("歡迎回來,您上次的訪問時間是:" + cookieValue);
break; //找到了需要的cookie,就不需要判斷別的cookie了
}
}
}
%>
<%
if(cookies == null || cookies.length == 0 || flag == false) {
// 沒有lastTime,第一次訪問,將當前時間儲存至cookie,向客戶端傳遞此cookie
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String format = sdf.format(date);
format = URLEncoder.encode(format, "UTF-8");
Cookie cookie = new Cookie("lastTime", format);
cookie.setMaxAge(60 * 60 * 24 * 30);
response.addCookie(cookie);
out.write("您好,歡迎您首次訪問");
}
%>
</body>
</html>
Session的介紹
- 概念:Session是伺服器端會話技術,在一次會話的多次請求間共享資料,將資料儲存到伺服器 端,常用來儲存使用者登入之後的資訊
- 快速入門:
(1) 獲取HttpSession物件
HttpSession session = request.getSession();
注:①第一次呼叫表示建立Session會話
②之後呼叫都是獲取前面建立好的Session會話物件
(2) 使用HttpSession物件的方法
void setAttribute(String name, Object value);
Object getAttribute(String name);
void removeAttribute(String name);
程式碼演示:演示Session的使用
(1) 在src下建立SessionDemo1.java
@WebServlet("/SessionDemo1")
public class SessionDemo1 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1\. 建立Session會話
HttpSession session = request.getSession();
//2\. 儲存資料
session.setAttribute("msg", "Hello! Session!");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
(2) 在src下建立SessionDemo2.java
@WebServlet("/SessionDemo2")
public class SessionDemo2 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1\. 獲取Session
HttpSession session = request.getSession();
//2\. 獲取資料
Object msg = session.getAttribute("msg");
System.out.println(msg);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
執行結果:
在瀏覽器位址列先輸入:http://localhost:8080/MyTest/SessionDemo1
後輸入:http://localhost:8080/MyTest/SessionDemo2
控制檯輸出:Hello! Session!
-
上述程式原理:Session底層是基於Cookie來實現的
注意:每個Session會話都有一個唯一的id值作為標識,getId方法可得到此id值
Session的細節
-
Session被銷燬的方式
(1)伺服器關閉
(2)Session物件呼叫invalidate()
(3)Session預設失效時間:30分鐘,可以到web.xml中修改配置檔案修改預設失效時間<session-config> <session-timeout>30</session-timeout> </session-config>
-
客戶端關閉之後伺服器不關閉,兩次獲取的Session是否為同一個?
(1) 預設情況下,不是,Cookie消失,其中的Session自然也消失
(2) 如果需要相同,進行如下操作:
-
客戶端不關閉,伺服器關閉之後,兩次獲取的Session是否為同一個?
不是同一個Session,但是為了保證資料的不丟失,Tomcat伺服器自動完成:
(1) Session的鈍化:
在伺服器正常關閉之前,將Session物件序列化到硬碟上
(2) Session的活化:
在伺服器啟動之後,將Session檔案反序列化成為記憶體中的Session物件
注意:也就是說即使獲取的不是同一個Session,但是Session中的資料都是相同的 -
Session的特點
(1) Session用於儲存一次會話的多次請求資料,存在伺服器端,一次會話只有一個session物件
(2) Session可以儲存任意型別,任意大小的資料 -
Session與Cookie的區別:
(1) Session儲存資料在伺服器端,Cookie在客戶端
(2) Session沒有資料大小的限制,Cookie有(4KB)
(3) Session資料安全,Cookie相對不安全
Cookie案例:免使用者名稱登入
說明:成功登入之後,重啟瀏覽器,再次登入時,瀏覽器記住了上次登入的使用者名稱
程式碼演示:免使用者名稱登入的使用
(1) 建立login.jsp
<body>
<form action="http://localhost:8080/MyTest/LoginServlet" method="post">
使用者名稱:<input type="text" name="username" value="${cookie.username.value}"> <br>
密碼:<input type="password" name="password"> <br>
<input type="submit" value="登入">
</form>
</body>
(2) 建立LoginServlet.java
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
//設定正確的使用者名稱為周杰倫,密碼是123
if ("jay".equals(username) && "123".equals(password)) {
Cookie cookie = new Cookie("username", username);
cookie.setMaxAge(60 * 60 * 24 * 7); //cookie儲存一週
response.addCookie(cookie);
System.out.println("登陸成功!");
} else {
System.out.println("登陸失敗!");
}
}
}
執行結果:
使用正確的使用者名稱和密碼之後,再次訪問登陸頁面,使用者名稱輸入框會自動的填入jay
谷歌瀏覽器檢視Cookie
驗證碼的底層原理
谷歌圖片驗證碼的使用
谷歌驗證碼的使用步驟:
- 匯入谷歌驗證碼的jar包:
- 在web.xml中進行如下的配置(寫成一樣的即可):
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
注:代表訪問這個Servlet就會生成驗證碼及圖片,並將此驗證碼儲存到Session域中,每次訪問都會生成不同的驗證碼
- 在表單中使用img標籤顯示驗證碼
<body>
<form action="http://localhost:8080/MyTest/Servlet">
驗證碼:<input type="text" style="width: 80px;" name="code">
<img src="http://localhost:8080/MyTest/kaptcha.jpg" alt="驗證碼沒有找到"
style="width: 100px; height: 28px;" id="code_img"> <br>
<input type="submit" value="登入">
</form>
</body>
- 在伺服器處理獲取的驗證碼
public class Servlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取Session中的驗證碼
String attribute = (String) request.getSession().getAttribute(KAPTCHA_SESSION_KEY);
//刪除Session中的驗證碼
request.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
//獲取使用者輸入的驗證碼
String code = request.getParameter("code");
if (attribute.equalsIgnoreCase(code)) {
System.out.println("驗證碼正確!");
} else {
System.out.println("驗證碼錯誤!");
}
}
}
執行結果:
點選圖片切換驗證碼
程式碼演示:為上述驗證碼繫結單擊事件(使用script標籤)
window.onload = function () {
//通過驗證碼圖片的id屬性值繫結單擊事件
var elementById = document.getElementById("code_img");
elementById.onclick = function () {
//1\. 事件響應的function函式中的this物件是當前正在響應事件的標籤的dom物件
//2\. src屬性可讀可寫
this.src = "http://localhost:8080/MyTest/kaptcha.jpg?d=" + new Date();
}
}
執行結果:每次點選驗證碼的圖片都會變成新的驗證碼,並將新驗證碼儲存到session域中
最後
感謝你看到這裡,看完有什麼的不懂的可以在評論區問我,覺得文章對你有幫助的話記得給我點個贊,每天都會分享java相關技術文章或行業資訊,歡迎大家關注和轉發文章!