JavaWeb會話技術(shù)
HTTP通信協(xié)議的特點(diǎn):
1.應(yīng)答式的協(xié)議古劲,只能是客戶端先發(fā)送請求然后服務(wù)器作出響應(yīng)斥赋。
2.明文傳輸,傳輸?shù)臄?shù)據(jù)是明文,沒有做加密之類處理
3.簡單快速产艾。HTTP協(xié)議相對簡單疤剑,所以傳輸較快。
4.無狀態(tài)闷堡,HTTP通信骚露,不會記錄客戶端的請求信息。默認(rèn)通信完成缚窿,傳輸斷開棘幸。
基于無狀態(tài)這點(diǎn),如果客戶端和服務(wù)器需要進(jìn)行二次會話倦零,且可能需要之前會話的數(shù)據(jù)這樣的需求場景误续。
所以,WEB技術(shù)中扫茅,提供了2種解決方案蹋嵌,這兩種解決方案就被稱之為會話技術(shù)。分別是:Session和Cookie葫隙。
1.如果一方需要之前溝通的記錄栽烂,在生活中是怎么處理的?
方案一: 將數(shù)據(jù)存儲起來,需要時進(jìn)行查看。Session
方案二:重新將之前的記錄發(fā)送一次腺办。Cookie
2.WEB中的Session技術(shù)
WEB中的Session技術(shù)焰手,是在服務(wù)器創(chuàng)建一個Session容器,可以將數(shù)據(jù)存儲在這個容器怀喉,然后將查找到這個容器key,給客戶端书妻,那么每次客戶端來請求服務(wù)器時,可以將這個key帶給服務(wù)器躬拢,服務(wù)器就可以根據(jù)這個key躲履,找到客戶端寄存在服務(wù)器的Session(數(shù)據(jù)容器),然后從session中獲取存儲的數(shù)據(jù)聊闯。
例如: 在超市里工猜,將物品進(jìn)行寄存,有一個寄存的號碼牌菱蔬,需要時篷帅,可以根據(jù)號碼牌,拿到寄存的物品汗销。
注意:
1.session是在服務(wù)器的內(nèi)存中犹褒,開辟了一存儲空間抵窒,默認(rèn)是有效時間是30分鐘弛针,若沒有主動釋放,則30分鐘會釋放內(nèi)存李皇。
2.session容器是一個map結(jié)構(gòu)的容器削茁,根據(jù)key查找對應(yīng)的session,若key不對掉房,那么session將找不到(找不到不代表它消失了)茧跋。一般關(guān)閉瀏覽器,或者使用新的瀏覽器卓囚,服務(wù)器會分配一個新的key給瀏覽器瘾杭,此時就找不到之前的那個session了,但是之前的session是在內(nèi)存中的哪亿。
3.客戶端從存儲session對應(yīng)的key是使用cookie技術(shù)存儲的粥烁,所以session技術(shù)也是依賴cookie技術(shù)。
2.1.session使用
session作為一個會話對象蝇棉,其中可以存儲多次請求需要共享的數(shù)據(jù)讨阻。例如:驗(yàn)證碼,當(dāng)前登錄用戶都可以存在session篡殷。所以首先要有session容器钝吮。
在調(diào)試時發(fā)現(xiàn),當(dāng)?shù)谝淮卧L問jsp頁面時,會有Cookie奇瘦,且Cookie中存在JSESSIONID的值棘催,但是訪問servlet的時候沒有,因?yàn)镴SP默認(rèn)會創(chuàng)建session對象(session是JSP的內(nèi)置對象之一)链患,但是session是不會主動創(chuàng)建session對象的巧鸭。所以在servlet中使用session,首先要創(chuàng)建一個session對象麻捻,而session與客戶端的請求關(guān)聯(lián)的纲仍,因?yàn)閟ession表示會話,會話包含多個請求贸毕,所以需要根據(jù)請求對象郑叠,找到關(guān)聯(lián)的session對象。
以上圖片明棍,瀏覽器中Cookie中JSESSIONID對應(yīng)的值乡革,與服務(wù)器中產(chǎn)生的sesion對象的ID值一致,說明服務(wù)器將自己創(chuàng)建的session對象的ID值給了瀏覽器摊腋。且使用的是Cookie沸版。所以session是依賴Cookie,因?yàn)樾枰褂肅ookie存儲自己的唯一標(biāo)識兴蒸,便于瀏覽器找到對應(yīng)的Session.
package com.sxt.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @ClassName: SessionController
* @Description: 演示session的API
* @author: Mr.T
* @date: 2020年2月14日 上午11:36:30
*/
public class SessionController extends HttpServlet {
private static final long serialVersionUID = -6539113475281947079L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("service方法執(zhí)行了");
// getSession() : 返回與當(dāng)前請求關(guān)聯(lián)的session 如果沒有則創(chuàng)建一個新的session
// getSession(create) : 返回當(dāng)前關(guān)聯(lián)的session對象, 如果create 為true,當(dāng)前session不存在時創(chuàng)建一個视粮,為false則返回null
//一般都是使用 getSession()
HttpSession session = req.getSession();
System.out.println("session的ID:"+session.getId());
//resp.getWriter().println("Hello Session");
//session中核心方法
//session 作為作用域 其核心作用是數(shù)據(jù)管理
//setAttribute(name, value) :向session 作用域中存儲數(shù)據(jù)
//getAttribute(name) : 從session作用域中獲取數(shù)據(jù)
//getAttributeNames() : 從session作用域中獲取所有存儲數(shù)據(jù)的name值
//session生命周期方法
//setMaxInactiveInterval(long) : 設(shè)置session 有效時間 單位是秒
//如果設(shè)置為0 或者 負(fù)數(shù),那么session 將永遠(yuǎn)不會失效 不建議 因?yàn)閟ession占服務(wù)器內(nèi)存
// tomcat 服務(wù)器 默認(rèn)是 30分鐘
//session.setMaxInactiveInterval(interval);
//invalidate() : 是這個session不關(guān)聯(lián)任何對象,即取消session和request的關(guān)聯(lián)
//這樣當(dāng)前request 就無法找到這個session
//session.invalidate();
}
}
2.2session目前的不足
session是存儲在服務(wù)器的內(nèi)存中,所以session只支持單應(yīng)用橙凳,而不支持負(fù)載形式的應(yīng)用架構(gòu)蕾殴。
所以session只支持單應(yīng)用的架構(gòu),只支持只有一臺服務(wù)器的架構(gòu)岛啸。
2.3.使用session記錄當(dāng)前用戶
一般在開發(fā)中钓觉,會將當(dāng)前登錄用戶,存儲在內(nèi)存中坚踩,便于其他地方使用荡灾。而在web程序,會將當(dāng)前的登錄用戶瞬铸,存儲在session中批幌。然后,在其他頁面或者servlet中赴捞,若要使用當(dāng)前用戶信息逼裆,則可以直接從session中獲取,不必根據(jù)用戶名和密碼重新查詢赦政,只需要登錄一次即可胜宇。
代碼:
package com.sxt.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sxt.pojo.User;
/**
* @ClassName: UserController
* @Description: 用戶控制類
* @author: Mr.T
* @date: 2020年2月14日 下午2:40:11
*/
public class UserController extends HttpServlet {
private static final long serialVersionUID = 7723086583204133716L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userName = req.getParameter("userName");
String password = req.getParameter("password");
//根據(jù)用戶名和密碼查詢用戶
//假設(shè) 用戶名和密碼 值都是 admin 當(dāng)做登錄成功
if("admin".equals(userName) && "admin".equals(password)) {
//將用戶信息存在session中
User user = new User(1, "admin", "password","韓梅梅");
//放入session 便于在當(dāng)前會話中 任何頁面或者servlet 都可以直接拿到當(dāng)前登錄用戶信息
req.getSession().setAttribute("user", user);
}
//去登錄成功頁面
resp.sendRedirect("success.jsp");
}
}
package com.sxt.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.sxt.pojo.User;
/**
* @ClassName: TestController
* @Description: 用于測試 可以從session中獲取當(dāng)前登錄用戶
* @author: Mr.T
* @date: 2020年2月14日 下午2:47:58
*/
public class TestController extends HttpServlet {
private static final long serialVersionUID = -5123674255870472885L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
User user = (User) session.getAttribute("user");
System.out.println("當(dāng)前登錄的用戶是:"+user.getRealName());
}
}
package com.sxt.pojo;
public class User {
private Integer userId;
private String userName;
private String password;
private String realName;
public User() {}
public User(Integer userId, String userName, String password, String realName) {
super();
this.userId = userId;
this.userName = userName;
this.password = password;
this.realName = realName;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登錄頁面</title>
</head>
<body>
<form action="user.do">
<p>用戶名:<input type="text" name="userName" /></p>
<p>用戶名:<input type="password" name="password" /></p>
<input type="submit" value="登錄"/>
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 從session 獲取當(dāng)前登錄用戶的真實(shí)姓名 -->
歡迎:${user.realName}
</body>
</html>
2.4.使用session存儲驗(yàn)證碼
一般在web網(wǎng)頁上看到的圖片耀怜,其實(shí)是服務(wù)器將圖片數(shù)據(jù)使用字節(jié)流,輸出給瀏覽器桐愉,然后瀏覽器拿到數(shù)據(jù)后财破,將數(shù)據(jù)解析成圖片,渲染在頁面从诲。
那么左痢,在頁面上看到的驗(yàn)證碼圖片,其實(shí)就是服務(wù)器生成的一張圖片系洛,然后將圖片使用字節(jié)流發(fā)送給了俊性,瀏覽器。然后瀏覽器解析描扯。并且定页,在處理登錄請求的servlet時,拿到用戶輸入的驗(yàn)證碼和之前產(chǎn)生的驗(yàn)證碼要進(jìn)行比對绽诚。
那么此時典徊,就是在登錄的servlet,要使用造驗(yàn)證碼的servlet產(chǎn)生的數(shù)據(jù)恩够,但是造驗(yàn)證碼servlet程序已經(jīng)執(zhí)行完成了卒落,內(nèi)存已經(jīng)釋放了。之前造的驗(yàn)證碼字符串已經(jīng)消失了蜂桶,無法進(jìn)行比對儡毕。基于這樣的情況屎飘,所以一般是將產(chǎn)生驗(yàn)證碼的字符串妥曲,存儲在session中贾费,這樣在登錄請求的servlet中钦购,也可以拿到之前產(chǎn)生的驗(yàn)證碼,從而進(jìn)行比對褂萧。
產(chǎn)生驗(yàn)證碼:
package com.sxt.controller;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @ClassName: CheckCodeController
* @Description: 產(chǎn)生驗(yàn)證碼的servlet
* @author: Mr.T
* @date: 2020年2月14日 下午3:27:44
*/
public class CheckCodeController extends HttpServlet {
private static final long serialVersionUID = -1597171426922505140L;
/**
* 驗(yàn)證碼池
*/
static String[] codes = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d"};
/**
* 驗(yàn)證碼的本質(zhì) 其實(shí)就是 一個有隨機(jī)字符串的圖片
* 服務(wù)器押桃,將圖片轉(zhuǎn)化為字節(jié)流輸出給瀏覽器
* 瀏覽器解析流數(shù)據(jù),將圖片渲染在頁面
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//要使用Java程序 造一個含有隨機(jī)字符串的圖片
//1. 創(chuàng)建一個背景圖 畫布
BufferedImage image = new BufferedImage(200, 100, BufferedImage.TYPE_INT_RGB);
//2. 獲取一個跟畫布關(guān)聯(lián)的畫筆
Graphics graphics = image.getGraphics();
//3.使用畫筆繪制信息
//為畫筆設(shè)置顏色
graphics.setColor(Color.WHITE);
//繪制一個填充的矩形 將默認(rèn)黑色的畫布 涂成白色
graphics.fillRect(0, 0, 200, 100);
//1. 獲取驗(yàn)證碼字符串 4個字符長度的驗(yàn)證碼
String code = getCode(4);
//將驗(yàn)證碼 放入session 便于在其他地方使用
req.getSession().setAttribute("code", code);
// 設(shè)置畫筆的字體 宋體 加粗 傾斜 35磅值
Font font = new Font("宋體", Font.BOLD | Font.ITALIC, 60);
graphics.setFont(font);
//2.根據(jù)循環(huán)將字符 繪制到圖片上
for (int i = 0; i < code.length(); i++) {
//隨機(jī)改變畫筆顏色
Color c = getColor();
graphics.setColor(c);
//獲取具體的字符
String str = code.charAt(i)+"";
//讓文字的橫坐標(biāo)值變大,從而向右側(cè)移動
int x = 20 + i*40;
graphics.drawString(str, x,65);
}
ImageIO.write(image, "jpg", resp.getOutputStream());
}
/**
* @Title: getColor
* @author: Mr.T
* @date: 2020年2月14日 下午3:54:56
* @Description: 隨機(jī)產(chǎn)生顏色
* @return
* @return: Color
*/
private Color getColor() {
//因?yàn)镽GB顏色 是由 0-255,0-255,0-255 的數(shù)值組成
Random random = new Random();
int r = random.nextInt(255);
int g = random.nextInt(255);
int b = random.nextInt(255);
return new Color(r, g, b);
}
/**
* @Title: getCode
* @author: Mr.T
* @date: 2020年2月14日 下午3:57:55
* @Description: 產(chǎn)生隨機(jī)字符串
* @param count 驗(yàn)證碼的個數(shù)
* @return
* @return: String
*/
private String getCode(int count) {
String code = "";
Random random = new Random();
for (int i = 0; i < count; i++) {
int index = random.nextInt(codes.length);
code = code + codes[index];
}
return code;
}
/**
* @Title: method
* @author: Mr.T
* @date: 2020年2月14日 下午4:03:38
* @Description: 繪制驗(yàn)證碼相關(guān)API的演示
* @return: void
*/
private void method(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 要使用Java程序 造一個含有隨機(jī)字符串的圖片
// 1. 創(chuàng)建一個背景圖 畫布
BufferedImage image = new BufferedImage(200, 100, BufferedImage.TYPE_INT_RGB);
// 2. 獲取一個跟畫布關(guān)聯(lián)的畫筆
Graphics graphics = image.getGraphics();
// 3.使用畫筆繪制信息
// 為畫筆設(shè)置顏色
graphics.setColor(Color.WHITE);
// 繪制一個填充的矩形 將默認(rèn)黑色的畫布 涂成白色
graphics.fillRect(0, 0, 200, 100);
// 可以在白色畫布上繪制文字 注意 此時畫筆是白色 繪制信息也是白色 所以需要改變畫筆的顏色
// 畫筆設(shè)置為紅色
graphics.setColor(Color.RED);
// 設(shè)置畫筆的字體 宋體 加粗 傾斜 35磅值
Font font = new Font("宋體", Font.BOLD | Font.ITALIC, 30);
graphics.setFont(font);
graphics.drawString("情人節(jié)快樂", 10, 55);
// 繪制干擾線 2點(diǎn) 連起來 就是一條線
graphics.drawLine(0, 0, 200, 100);
// 使用輸出流 將圖片數(shù)據(jù)輸出給瀏覽器
ImageIO.write(image, "jpg", resp.getOutputStream());
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登錄頁面</title>
</head>
<body>
<form action="user.do">
<p>用戶名:<input type="text" name="userName" /></p>
<p>用戶名:<input type="password" name="password" /></p>
<p>用戶名:<input type="password" name="checkCode" style="width: 50px" />
<img onclick="refreshCode()" src="checkCode.do" style="height: 50px" id="checkCodeImg" />
</p>
<input type="submit" value="登錄"/>
</form>
</body>
<script type="text/javascript">
//刷新驗(yàn)證碼
function refreshCode(){
console.log("點(diǎn)擊了");
//設(shè)置 src的值 值一旦發(fā)生改變 瀏覽器 會重新請求這個url地址
//瀏覽器存在緩存策略,當(dāng)src 后面值一樣,瀏覽器是不會重新請求
//那么servlet就不會產(chǎn)生新的驗(yàn)證碼 所以驗(yàn)證碼沒有發(fā)生改變
//基于這樣的情況 一般會在src 后面的url 拼接一個不可重復(fù)的字符 ,一般使用隨機(jī)數(shù) 或者 時間戳
document.getElementById("checkCodeImg").src = "checkCode.do?"+new Date();
}
</script>
</html>
使用Hutool生成驗(yàn)證碼:
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**
* width : 圖片的寬度
* height : 圖片高度
* codeCount : 驗(yàn)證碼的個數(shù)
* circleCount : 干擾元素個數(shù)
*/
LineCaptcha checkObj = CaptchaUtil.createLineCaptcha(200, 100, 4, 100);
//獲取具體的驗(yàn)證碼字符串
String code = checkObj.getCode();
//將生成的驗(yàn)證碼 放入session
req.getSession().setAttribute("code", code);
//將驗(yàn)證碼輸出到頁面
checkObj.write(resp.getOutputStream());
}
校驗(yàn)驗(yàn)證碼:
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//獲取用戶輸入的驗(yàn)證碼
String checkCode = req.getParameter("checkCode");
//從session中獲取產(chǎn)生時存儲的驗(yàn)證碼
Object code = req.getSession().getAttribute("code") ;
//對驗(yàn)證碼進(jìn)行對比
if(checkCode == null || !checkCode.equals(code.toString())) {
System.out.println("驗(yàn)證碼錯誤!");
resp.sendRedirect("login.jsp");
return;
}
String userName = req.getParameter("userName");
String password = req.getParameter("password");
//根據(jù)用戶名和密碼查詢用戶
//假設(shè) 用戶名和密碼 值都是 admin 當(dāng)做登錄成功
if("admin".equals(userName) && "admin".equals(password)) {
//將用戶信息存在session中
User user = new User(1, "admin", "password","韓梅梅");
//放入session 便于在當(dāng)前會話中 任何頁面或者servlet 都可以直接拿到當(dāng)前登錄用戶信息
req.getSession().setAttribute("user", user);
}
//去登錄成功頁面
resp.sendRedirect("success.jsp");
}
3.WEB中的Cookie技術(shù)
在WEB中导犹,Cookie技術(shù)是將需要的數(shù)據(jù)唱凯,由服務(wù)器寫入(響應(yīng))到瀏覽器中(內(nèi)存中,一個文件中)谎痢,然后磕昼,瀏覽器接下來的請求,都會將這些數(shù)據(jù)通過請求頭节猿,帶給服務(wù)器票从。服務(wù)器可以通過解析請求頭漫雕,從而解析這些數(shù)據(jù)。這種技術(shù)方案就被稱之為Cookie.
注意:
- Cookie的存儲2種方式峰鄙,一種是內(nèi)存中一種磁盤文件中浸间,這兩種方式是Cookie生命周期的體現(xiàn)。默認(rèn)Cookie的生命周期吟榴,是在內(nèi)存中魁蒜,基本是一次會話。
- Cookie是由服務(wù)器吩翻,通過響應(yīng)對象兜看,將數(shù)據(jù)通知給客戶端,讓客戶端在本地進(jìn)行一定的存儲狭瞎,且下次來請求帶過來铣减。
3.1.Cookie的使用
-
創(chuàng)建Cookie
Cookie cookie1 = new Cookie("name","value"); // cookie是map結(jié)構(gòu)
-
通過response對象,將創(chuàng)建的cookie給瀏覽器
resp.addCookie(cookie1); //通過響應(yīng)對象脚作,設(shè)置set-cookie的響應(yīng)頭葫哗,瀏覽器拿到這個響應(yīng)頭后 ,會將響應(yīng)頭找中的數(shù)據(jù)保存到瀏覽器的內(nèi)存中或者本地
以后的請求球涛,瀏覽器會將cookie信息帶給服務(wù)器劣针,服務(wù)器可以從請求頭中,解析cookie信息亿扁。
代碼示例:
/**
* @ClassName: CookieController
* @Description: 用于演示Cookie相關(guān)的API
* @author: Mr.T
* @date: 2020年2月16日 上午10:47:39
*/
public class CookieController extends HttpServlet {
private static final long serialVersionUID = 2285648241402004645L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//cookie是由服務(wù)器 告訴客戶端 要存儲哪些數(shù)據(jù)
//cookie是由服務(wù)器創(chuàng)建 然后 服務(wù)器將這個cookie 給客戶端 客戶端將cookie數(shù)據(jù)進(jìn)行存儲
//之后的請求,都會將cookie數(shù)據(jù)帶給服務(wù)器
//1. 創(chuàng)建Cookie --- cookie數(shù)據(jù)結(jié)構(gòu) map接口
Cookie cookie1 = new Cookie("cookieName", "cookieValue");
//設(shè)置cookie的有效期 單位是秒 如果設(shè)置為 0 則表示要刪除這個cookie
//如果設(shè)置了有效期,瀏覽器會將cookie存儲在自己本地的文件中,如果不清除,且沒有過有效期,那么cookie就有效
//之后請求,會將數(shù)據(jù)帶給服務(wù)器
cookie1.setMaxAge(60*2);//2分鐘
//設(shè)置cookie是否允許瀏覽器進(jìn)行操作 由于cookie是存在瀏覽器中,瀏覽器可以通過js對cookie進(jìn)行數(shù)據(jù)操作
//servlet 3.0 后 setHttpOnly(true) : 只有HTTP可以操作Cookie 瀏覽器無法操作Cookie
cookie1.setHttpOnly(true);
//注意捺典,cookie 默認(rèn)只對當(dāng)前項(xiàng)目生效 有效路徑 當(dāng)前項(xiàng)目 域名 項(xiàng)目名
//但是實(shí)際中,存在子域名,當(dāng)需要多個子域名cookie也生效,則需要設(shè)置這個屬性
//cookie1.setDomain(pattern);
//注意,默認(rèn)只對項(xiàng)目及項(xiàng)目的子目錄生效。限制生效的URI,通過setPath進(jìn)行設(shè)置
//cookie1.setPath(uri);
//2. 通過響應(yīng)對象 將cookie 給客戶端
resp.addCookie(cookie1);
resp.getWriter().print("Hello Cookie");
}
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//cookie數(shù)據(jù) 是瀏覽器 通過請求頭的信息 將數(shù)據(jù)傳給服務(wù)器的,所以解析cookie 要從請求對象中解析
// 獲取所有的cookie
Cookie[] cookies = req.getCookies();
//判斷cookie是否存在
if(cookies != null) {
//只能通過遍歷的方式進(jìn)行判斷 遍歷所有cookie 獲取每個cookie的name值 對比name 從而拿到自己需要的cookie對象
for (Cookie cookie : cookies) {
//獲取cookie的name
String name = cookie.getName();
//獲取cookie的Value值
String value = cookie.getValue();
if(name.equals("cookieName")) {
System.out.println("cookieName 對應(yīng)的值:"+value);
}
}
}
}
3.2.Cookie的不足
Cookie是將數(shù)據(jù)存儲在瀏覽器从祝,然后每次瀏覽器自動會將Cookie數(shù)據(jù)放在請求頭中襟己,傳遞給無服務(wù)器。
1.安全性相對較差,可以在傳輸?shù)倪^程中牍陌,修改Cookie中數(shù)據(jù)擎浴。
2.無法與其它終端共享數(shù)據(jù)。例如:用戶在PC端進(jìn)行了操作毒涧,數(shù)據(jù)存在Cookie中贮预,用戶在移動端是看不到用戶在PC端的操作的。
3.Cookie中存儲的數(shù)據(jù)有限.
3.3.Cookie的場景
1.早期時契讲,使用Cookie做購物車仿吞。將用戶的購買的商品放入Cookie中。但是在現(xiàn)在捡偏,使用Cookie作為購物車唤冈,無法滿足需求,因?yàn)闆]有辦法在其它終端共享數(shù)據(jù)银伟。所以你虹,為了共享數(shù)據(jù)凉当,會將數(shù)據(jù)存在服務(wù)器數(shù)據(jù)庫中,便于在任何平臺都能看到用戶的購物車售葡,前提是用戶登錄了看杭。所以,如果用戶沒有登陸挟伙,會將用戶購物車數(shù)據(jù)存儲在Cookie中楼雹,但是,當(dāng)用戶登錄后尖阔,將Cookie中的數(shù)據(jù)保存到數(shù)據(jù)庫中贮缅。
2.用戶的瀏覽記錄。一般會將用戶的瀏覽記錄放入Cookie介却。例如: 瀏覽器的訪問記錄.
3.使用Cookie記錄用戶的登錄憑證谴供,讓用戶免密登錄。記住密碼齿坷。
3.5.使用Cookie記住密碼
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登錄頁面</title>
</head>
<body>
<!-- 用戶登錄表單 -->
<form action="user.do" method="post">
<!-- 從cookie中 獲取 對應(yīng)的值 -->
<p>用戶名<input type="text" name="userName" value="${cookie.userName.value}" /></p>
<p>密碼:<input type="text" name="password" value="${cookie.password.value}" /></p>
<p>記住密碼:<input type="checkbox" name="remeber" value="1"/></p>
<p><input type="submit" value="登錄" /></p>
</form>
</body>
</html>
package com.sxt.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @ClassName: UserController
* @Description: @WebServlet 就是代替 web.xml中的servlet 配置
* "/user.do" 就是xml中 url-pattern的值
* @author: Mr.T
* @date: 2020年2月16日 下午2:34:42
*/
@WebServlet("/user.do")
public class UserController extends HttpServlet {
/**
* @fieldName: serialVersionUID
* @fieldType: long
* @Description: TODO
*/
private static final long serialVersionUID = 7723086583204133716L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//獲取用戶名
String userName = req.getParameter("userName");
//獲取密碼
String password = req.getParameter("password");
//是否記住密碼
String remeber = req.getParameter("remeber");
/**
* 如果記住密碼 可以將賬號密碼信息放入cookie 下次登錄 直接從cookie中取 不用再輸入賬號面
*
*/
if("1".equals(remeber)) {//表示記住密碼
//將賬號放入cookie
Cookie userNameCookie = new Cookie("userName", userName);
//由于 cookie 默認(rèn)是瀏覽器關(guān)閉就會消失,設(shè)置cookie的有效期
userNameCookie.setMaxAge(60*60*24*7);//1個星期
//通過resp 將cookie給瀏覽器
resp.addCookie(userNameCookie);
//將密碼 放入cookie
Cookie passwordCookie = new Cookie("password", password);
//由于 cookie 默認(rèn)是瀏覽器關(guān)閉就會消失,設(shè)置cookie的有效期
passwordCookie.setMaxAge(60*60*24*7);//1個星期
//通過resp 將cookie給瀏覽器
resp.addCookie(passwordCookie);
}
resp.getWriter().print("登錄成功");
}
}