??一.回顧C(jī)ookie與Session
??1.1 Cookie
HTTP 協(xié)議自身是屬于 “無(wú)狀態(tài)” 協(xié)議.
“無(wú)狀態(tài)” 的含義指的是:
默認(rèn)情況下 HTTP 協(xié)議的客戶端和服務(wù)器之間的這次通信, 和下次通信之間沒(méi)有直接的聯(lián)系.但是實(shí)際開發(fā)中, 我們很多時(shí)候是需要知道請(qǐng)求之間的關(guān)聯(lián)關(guān)系的.
例如登陸網(wǎng)站成功后, 第二次訪問(wèn)的時(shí)候服務(wù)器就能知道該請(qǐng)求是否是已經(jīng)登陸過(guò)了
回憶之前的例子:
- 到了醫(yī)院先掛號(hào). 掛號(hào)時(shí)候需要提供身份證, 同時(shí)得到了一張 "就診卡"
Cookie
, 這個(gè)就診卡就相當(dāng)于患者的 “令牌”. - 后續(xù)去各個(gè)科室進(jìn)行檢查, 診斷, 開藥等操作, 都不必再出示身份證了, 只要憑就診卡即可識(shí)別出當(dāng)前患者的身份.
- 看完病了之后, 不想要就診卡了, 就可以注銷這個(gè)卡. 此時(shí)患者的身份和就診卡的關(guān)聯(lián)就銷毀了. (類似于網(wǎng)站的注銷操作)
- 又來(lái)看病, 可以辦一張新的就診卡, 此時(shí)就得到了一個(gè)新的 “令牌”
此時(shí)在服務(wù)器這邊就需要記錄令牌信息, 以及令牌對(duì)應(yīng)的用戶信息, 這個(gè)就是 Session 機(jī)制所做的工作
??1.2 Session
服務(wù)器同一時(shí)刻收到的請(qǐng)求是很多的. 服務(wù)器需要清除的區(qū)分清楚每個(gè)請(qǐng)求是從屬于哪個(gè)用戶, 就需要在服務(wù)器這邊記錄每個(gè)用戶令牌以及用戶的信息的對(duì)應(yīng)關(guān)系.在上面的例子中, 就診卡就是一張 “令牌”. 要想讓這個(gè)令牌能夠生效, 就需要醫(yī)院這邊通過(guò)系統(tǒng)記錄每個(gè)就診卡和患者信息之間的關(guān)聯(lián)關(guān)系.
會(huì)話的本質(zhì)就是一個(gè) “哈希表”, 存儲(chǔ)了一些鍵值對(duì)結(jié)構(gòu). key 就是令牌的 ID(token/sessionId), value 就是用戶信息(用戶信息可以根據(jù)需求靈活設(shè)計(jì)).
sessionId 是由服務(wù)器生成的一個(gè) “唯一性字符串”, 從 session 機(jī)制的角度來(lái)看, 這個(gè)唯一性字符串稱為 “sessionId
”. 但是站在整個(gè)登錄流程中看待, 也可以把這個(gè)唯一性字符串稱為 “token”.sessionId 和 token 就可以理解成是同一個(gè)東西的不同叫法(不同視角的叫法)
用戶登陸:
●當(dāng)用戶登陸的時(shí)候, 服務(wù)器在 Session 中新增一個(gè)新記錄, 并把 sessionId / token 返回給客戶端.(例如通過(guò) HTTP 響應(yīng)中的 Set-Cookie 字段返回).
●客戶端后續(xù)再給服務(wù)器發(fā)送請(qǐng)求的時(shí)候, 需要在請(qǐng)求中帶上 sessionId/ token. (例如通過(guò) HTTP 請(qǐng)求中的 Cookie 字段帶上).
●服務(wù)器收到請(qǐng)求之后, 根據(jù)請(qǐng)求中的 sessionId / token 在 Session 信息中獲取到對(duì)應(yīng)的用戶信息,再進(jìn)行后續(xù)操作.
Servlet 的 Session 默認(rèn)是保存在內(nèi)存中的. 如果重啟服務(wù)器則 Session 數(shù)據(jù)就會(huì)丟失.
??1.3Cookie 和 Session 的區(qū)別
●Cookie 是客戶端的機(jī)制. Session 是服務(wù)器端的機(jī)制.
●Cookie 和 Session 經(jīng)常會(huì)在一起配合使用. 但是不是必須配合.
●完全可以用 Cookie 來(lái)保存一些數(shù)據(jù)在客戶端. 這些數(shù)據(jù)不一定是用戶身份信息, 也不一定是token / sessionId
●Session 中的 token / sessionId 也不需要非得通過(guò) Cookie / Set-Cookie 傳遞.
??二.Servlet會(huì)話管理操作
??2.1核心方法
HttpServletRequest 類中的相關(guān)方法
方法 | 描述 |
---|---|
HttpSession getSession() | 在服務(wù)器中獲取會(huì)話. 參數(shù)如果為 true, 則當(dāng)不存在會(huì)話時(shí)新建會(huì)話; 參數(shù)如果為 false, 則當(dāng)不存在會(huì)話時(shí)返回 null |
Cookie[] getCookies() | 返回一個(gè)數(shù)組, 包含客戶端發(fā)送該請(qǐng)求的所有的 Cookie 對(duì)象. 會(huì)自動(dòng)把Cookie 中的格式解析成鍵值對(duì). |
Part getPart(String name) | 獲取請(qǐng)求中給定 name 的文件 |
Collection getParts() | 獲取所有的文件 |
HttpServletResponse 類中的相關(guān)方法
方法 | 描述 |
---|---|
void addCookie(Cookie cookie) | 把指定的 cookie 添加到響應(yīng)中. |
HttpSession 類中的相關(guān)方法
一個(gè) HttpSession 對(duì)象里面包含多個(gè)鍵值對(duì). 我們可以往 HttpSession 中存任何我們需要的信息.
方法 | 描述 |
---|---|
Object getAttribute(Stringname) | 該方法返回在該 session 會(huì)話中具有指定名稱的對(duì)象,如果沒(méi)有指定名稱的對(duì)象,則返回 null. |
void setAttribute(Stringname, Object value) | 該方法使用指定的名稱綁定一個(gè)對(duì)象到該 session 會(huì)話 |
boolean isNew() | 判定當(dāng)前是否是新創(chuàng)建出的會(huì)話 |
Cookie 類中的相關(guān)方法
每個(gè) Cookie 對(duì)象就是一個(gè)鍵值對(duì).
方法 | 描述 |
---|---|
String getName() | )該方法返回 cookie 的名稱。名稱在創(chuàng)建后不能改變。(這個(gè)值是 SetCooke 字段設(shè)置給瀏覽器的) |
String getValue() | 該方法獲取與 cookie 關(guān)聯(lián)的值 |
void setValue(String newValue) | 該方法設(shè)置與 cookie 關(guān)聯(lián)的值 |
HTTP 的 Cooke 字段中存儲(chǔ)的實(shí)際上是多組鍵值對(duì). 每個(gè)鍵值對(duì)在 Servlet 中都對(duì)應(yīng)了一個(gè) Cookie對(duì)象.
●通過(guò) HttpServletRequest.getCookies() 獲取到請(qǐng)求中的一系列 Cookie 鍵值對(duì).
●通過(guò) HttpServletResponse.addCookie() 可以向響應(yīng)中添加新的 Cookie 鍵值對(duì).
Part 類方法
方法 | 描述 |
---|---|
String getSubmittedFileName() | 獲取提交的文件名 |
String getContentType() | 獲取提交的文件類型 |
long getSize() | 獲取文件的大小 |
void write(String path) | 把提交的文件數(shù)據(jù)寫入磁盤文件 |
??三.常見案例實(shí)現(xiàn)
??3.1登錄邏輯的實(shí)現(xiàn)
我們經(jīng)常上網(wǎng)查詢一些網(wǎng)站什么的,很多網(wǎng)站都會(huì)讓你先登錄,才能使用其中的一些功能,登錄完成之后,一般都會(huì)跳到一個(gè)主頁(yè)網(wǎng)站,下面我們就來(lái)簡(jiǎn)單地實(shí)現(xiàn)一下這一套邏輯。
第一步,約定前后端接口
我們需要實(shí)現(xiàn)兩套交互邏輯,一是登錄跳轉(zhuǎn),二是獲取主頁(yè)
登錄跳轉(zhuǎn)約定:
約定使用POST請(qǐng)求,響應(yīng)采用302重定向
獲取主頁(yè)約定:
采用GET請(qǐng)求,響應(yīng)返回一個(gè)頁(yè)面
第二步,編寫前端交互頁(yè)面
我們的重點(diǎn)是來(lái)學(xué)習(xí)登錄的邏輯,因此登錄的界面不需要很好看很復(fù)雜,只要能夠有兩個(gè)輸入框和一個(gè)提交按鈕讓我們輸入賬號(hào)密碼就行。目標(biāo)頁(yè)面如下:
在pom.xml中引入Servlet依賴
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
前端代碼
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="login" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="登錄">
</form>
</body>
</html>
后端代碼登陸
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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf8");
resp.setCharacterEncoding("utf8");
//獲取用戶賬號(hào)
String username = req.getParameter("username");
String password = req.getParameter("password");
//驗(yàn)證賬戶
//驗(yàn)證按照正常流程應(yīng)該從數(shù)據(jù)庫(kù)讀數(shù)據(jù),但是為了便于演示登錄的邏輯,我們直接將賬號(hào)密碼寫死
//假設(shè)正確的賬號(hào)與密碼是 zhangsan 123
if ("zhangsan".equals(username) && "123".equals(password)) {
//登錄成功
//創(chuàng)建會(huì)話,為后續(xù)需登錄的頁(yè)面做準(zhǔn)備
HttpSession httpSession = req.getSession(true);
httpSession.setAttribute("username", username);
//初始情況下設(shè)置登錄次數(shù)
httpSession.setAttribute("count", 0);
//跳轉(zhuǎn)到目標(biāo)頁(yè)面index
resp.sendRedirect("index");
} else {
//登錄失敗
resp.getWriter().write("登錄失敗!");
}
}
}
登陸后重定向頁(yè)面響應(yīng)
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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//返回一個(gè)主頁(yè)
//獲取會(huì)話,參數(shù)必須是false
HttpSession httpSession = req.getSession(false);
//取出會(huì)話信息
String username = (String) httpSession.getAttribute("username");
Integer cnt = (Integer) httpSession.getAttribute("count");
//訪問(wèn)次數(shù)加1
cnt++;
//寫回到會(huì)話中
httpSession.setAttribute("count", cnt);
//構(gòu)造頁(yè)面。我們簡(jiǎn)單構(gòu)造一下就好
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("<h3>歡迎您!" + username + "</h3> <h4>這個(gè)主頁(yè)已經(jīng)被訪問(wèn)了" + cnt + "次</h4>");
}
}
??3.2上傳文件
前端代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>file</title>
</head>
<body>
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="myfile">
<input type="submit" value="提交">
</form>
</body>
</html>
后端代碼文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-489394.html
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
@MultipartConfig
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//獲取Part對(duì)象
Part part = req.getPart("myfile");
//輸出文件信息
//文件名
System.out.println("文件名:" + part.getSubmittedFileName());
//文件類型
System.out.println("文件類型:" + part.getContentType());
//文件大小
System.out.println("文件大小:" + part.getSize());
//將文件寫入磁盤
part.write("D:\\上傳文件");
//返回響應(yīng)
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("上傳成功!");
}
}
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-489394.html
到了這里,關(guān)于Servlet【 ServletAPI中的會(huì)話管理Cookie與Session】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!