java的會話管理:Cookie和Session
1.什么是會話
此處的是指客戶端(瀏覽器)和服務端之間的數據傳輸。例如用戶登錄,購物車等
會話管理就是管理瀏覽器客戶端和服務端之間會話過程產生的會話數據
常用的會話技術
之前學會了域對象的作用,所以在會話管理的時候也可以使用域對象的概念來找到解決方法。
常用的解決方法主要有兩種:
數據保存在客戶端的Cookie技術
數據保存在服務端的Session技術
2.Cookie技術
2.1.什么是Cookie
Cookie是客戶端技術,程序把每個用戶的數據以cookie的形式寫給用戶各自的瀏覽器,當用戶使用瀏覽器再去訪問服務器中的web資源時,就會帶着各自的數據去。這樣,web資源處理的就是各自用戶自己的數據了
特點是會話數據保存在瀏覽器客戶端
2.2.Cookie技術核心API
Cookie類:用於存儲會話數據。常用方法如下:
1.構造Cookie對象
Cookie(java.lang.String name, java.lang.String value)
2.設置cookie
void setPath(java.lang.String uri) :設置cookie的有效訪問路徑
void setMaxAge(int expiry) : 設置cookie的有效時間
void setValue(java.lang.String newValue) :設置cookie的值
3.發送cookie到瀏覽器端保存
void response.addCookie(Cookie cookie) : 發送cookie
4.服務器端接收cookie
Cookie[] request.getCookies() : 接收cookie
代碼示例:
/**
* 測試Cookie的方法
*/
@WebServlet(name = "CookieDemo")
public class CookieDemo extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.創建Cookie對象
Cookie cookie = new Cookie("name","eric");
//2.設置Cookie參數
//2.1.設置Cookie的有效路徑
cookie.setPath("/hello");//默認就是web項目的地址
//2.2.設置Cookie的有效時間
cookie.setMaxAge(20);//該cookie只存活20秒,從最后不調該cookie開始計算
cookie.setMaxAge(-1);//該cookie保存在瀏覽器內存中,關閉瀏覽器則銷毀該cookie
cookie.setMaxAge(0);//刪除根該cookie同名的cookie
//3.把數據發送到瀏覽器
response.addCookie(cookie);
//4.服務端接收來自瀏覽器的cookie
//方法1:
// String name = request.getHeader("cookie");
// System.out.println(name);
//方法2:
Cookie[] cookies = request.getCookies();
//注意:判斷null,否則空指針
if(cookies!=null){
//遍歷
for(Cookie c:cookies){
String name = c.getName();
String value = c.getValue();
System.out.println(name+"="+value);
}
}else{
System.out.println("沒有接收cookie數據");
}
}
}
2.3.Cookie原理
1.服務器創建Cookie對象,把會話數據存儲到Cookie對象中
new Cookie("name","value");
2.服務器發送cookie信息到瀏覽器
response.addCookie(cookie);
其實是隱藏發送了一個set-cookie名稱的響應頭
3.瀏覽器得到服務器發送的cookie,然后保存在瀏覽器端
4.瀏覽器在下次訪問服務器時,會帶着cookie信息
包含在http的請求頭里
5.服務器接收到瀏覽器帶來的cookie信息
request.getCookies();
2.4.Cookie的細節
1.void setPath(java.lang.String uri)
:設置Cookie的有效訪問路徑,有效訪問路徑指的事Cookie的有效路徑保存在哪里,那么瀏覽器在有效路徑下訪問服務器的時就會帶着Cookie信息,否則不帶Cookie信息,默認是在當時錢web項目的路徑下
2.void setMaxAge(int expiry)
:設置Cookie的有效時間
expiry可以是正整數,負整數,和零
正整數:表示Cookie數據保存瀏覽器的緩存到硬盤中,數值表示保存的時間
負整數:表示Cookie數據保存到瀏覽器的內存中,瀏覽器關閉Cookie就丟失了
零:表示刪除同名的Cookie數據
3.Cookie數據類型只能保存非中文字符串類型的。可以保存多個Cookie,但是瀏覽器一般只允許存放300個Cookie,每個站點最多存放20個Cookie,每個Cookie的大小限制為4KB。
2.5.Cookie案例:顯示用戶上次訪問的時間
功能實現邏輯:
將時間保存在Cookie中,每次訪問從Cookie里面調用
第一次訪問:
1.獲取當前時間,顯示到瀏覽器中
2.創建Cookie對象,時間作為cookie值,名為:lastTime
3.把cookie發送到瀏覽器保存
第N次訪問:
1.獲取cookie的數據,取出名為lastTime的cookie
2.得到cookie的值(上次訪問時間)
3.顯示上次訪問時間到瀏覽器中
4.更新名為lastTime的cookie。值設置為當前時間
5.把更新后的cookie發送給瀏覽器保存
代碼實現:
/**
* 案例-用戶上次訪問的時間
*/
@WebServlet("/last")
public class HistServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//獲取當前時間
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String curTime = format.format(new Date());
//取得cookie
Cookie[] cookies = request.getCookies();
String lastTime = null;
//第n次訪問
if(cookies!=null){
for (Cookie cookie : cookies) {
if(cookie.getName().equals("lastTime")){
//有lastTime的cookie,已經是第n次訪問
lastTime = cookie.getValue();//上次訪問的時間
//第n次訪問
//1.把上次顯示時間顯示到瀏覽器
response.getWriter().write("歡迎回來,你上次訪問的時間為:"+lastTime+",當前時間為:"+curTime);
//2.更新cookie
cookie.setValue(curTime);
cookie.setMaxAge(1*30*24*60*60);
//3.把更新后的cookie發送到瀏覽器
response.addCookie(cookie);
break;
}
}
}
/**
* 第一次訪問(沒有cookie 或 有cookie,但沒有名為lastTime的cookie)
*/
if(cookies==null || lastTime==null){
//1.顯示當前時間到瀏覽器
response.getWriter().write("你是首次訪問本網站,當前時間為:"+curTime);
//2.創建Cookie對象
Cookie cookie = new Cookie("lastTime",curTime);
cookie.setMaxAge(1*30*24*60*60);//保存一個月
//3.把cookie發送到瀏覽器保存
response.addCookie(cookie);
}
}
}
2.6.Cookie案例:查看用戶瀏覽過的商品
邏輯圖
這個項目的代碼較多,按照功能的不同放在不同的包里面
公司域名的倒寫+項目名字+功能名字
cenyu.hist.entity 存放實體對象
cenyu.hist.dao Data Access Object 數據訪問對象,主要存放實體對象的一些方法(CRUD-create,read,update,delete)
cenyu.hist.servlet 存放servlet程序
cenyu.hist.ytil 存放工具類
cenyu.hist.test 存放測試類
等等
寫的順序:實體對象-->DAO類-->Servlet程序
代碼:暫無
3.Session技術
3.1.什么是Session
Session是服務器端技術,利用這個技術,服務器在運行時可以為每一個用戶的數據創建一個其獨享的Session對象,由於Session為用戶瀏覽器獨享,所以當用戶在訪問服務器的web資源時,可以把各自的數據放在各自的Session中,當用戶再去訪問服務器中的其他的web資源的時候,其他的web資源再從用戶各自的Session中取出數據為用戶服務
3.2.Session的核心技術
Session的類是HttpSession類:用於保存會話數據
1.創建或得到session對象
HttpSession getSession()
直接創建一個Session對象
HttpSession getSession(boolean create)
接收布爾值,設置為true時,在沒有找到匹配Session編號的對象時新建一個Sessionu對象。如果設置false,則當找不到匹配的Session時,返回null,建議不要用
2.設置session對象
void setMaxInactiveInterval(int interval)
: 設置session的有效時間
java.lang.String getId()
: 得到session編號
void invalidate()
: 銷毀session對象
Session對象的方法:
1.setMaxInactiveInterval方法默認30分鍾自動回收Session對象
2.使用setMaxInactiveInterval方法修改銷毀時間
3.在web.xml文件中全局修改Session默認回收時間
<!-- 修改session全局有效時間:分鍾 -->
<session-config>
<session-timeout>1</session-timeout>
</session-config>
4.通過invalidate方法,手動銷毀Session對象
3.保存會話數據到session對象
void setAttribute(java.lang.String name, java.lang.Object value) : 保存數據
java.lang.Object getAttribute(java.lang.String name) : 獲取數據
void removeAttribute(java.lang.String name) : 清除數據
4.如何避免瀏覽器的JSESSIONID的cookie隨着瀏覽器關閉而丟失的問題:
解決方法是手動發送一個硬盤保護的cookie給瀏覽器
代碼見案例:
/**
* 測試Session的方法
*/
@WebServlet(name = "SessionServletDemo")
public class SessionServletDemo extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.創建Session對象
HttpSession session = request.getSession();
//2.保存會話數據
session.setAttribute("name","eric");
//3.取出會話數據
String name = (String)session.getAttribute("name");
System.out.println(name);
//4.
//拿到Session的id
System.out.println(session.getId());
//修改Session有效時間
session.setMaxInactiveInterval(20);
//銷毀session
if (session!=null){
session.invalidate();
}
//手動發送一個硬盤保存的cookie給瀏覽器
Cookie c = new Cookie("JSESSION", session.getId());
c.setMaxAge(60*60);
response.addCookie(c);
}
}
3.3.Session原理
代碼解讀:HttpSession session = request.getSession();
偽碼分析執行過程
1.第一次訪問創建Session對象,給Session對象分配一個唯一的ID,叫JSESSIONID。
new HttpSession();
2.把JSESSIONID作為Cookie的值發送給瀏覽器保存
Cookie cookie = new Cookie("JSESSIONID", sessionID);
response.addCookie(cookie);
3.第二次訪問的時候,瀏覽器帶着JSESSIONID的cookie訪問服務器
4.服務器得到JSESSIONID,在服務器的內存中搜索是否存放對應編號的session對象
5.如果找到對應編號的session對象,直接返回該對象
6.如果找不到對應編號session對象,創建新的session對象,繼續走1的流程
結論通過JSESSION的cookie值在服務器找session對象
3.4.Session案例:用戶登錄效果
需求:實現用戶登錄效果,如果登錄成功顯示:歡迎回來,×××。如果失敗,顯示登錄失敗
使用Session區分不同的用戶來實現,整個代碼實現分為三塊,登錄表單提交之后的處理邏輯,登錄邏輯,登出邏輯:
默認登錄界面。index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>登錄頁面</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
</head>
<body>
<form action="/day12/LoginServlet" method="post">
用戶名:<input type="text" name="userName"/>
<br/>
密碼:<input type="text" name="userPwd"/>
<br/>
<input type="submit" value="登錄"/>
</form>
</body>
</html>
登錄失敗頁面:fail.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>信息提示頁面</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
</head>
<body>
<font color='red' size='3'>親, 你的用戶名或密碼輸入有誤!請重新輸入!</font><br/>
<a href="/day12/login.html">返回登錄頁面</a>
</body>
</html>
表單提交之后的主處理邏輯:IndexServlet.java
/**
* 用戶主頁的邏輯
*
*/
public class IndexServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
String html = "";
/**
* 接收request域對象的數據
*/
/*
String loginName = (String)request.getAttribute("loginName");
*/
/**
* 二、在用戶主頁,判斷session不為空且存在指定的屬性才視為登錄成功!才能訪問資源。
* 從session域中獲取會話數據
*/
//1.得到session對象
HttpSession session = request.getSession(false);
if(session==null){
//沒有登錄成功,跳轉到登錄頁面
response.sendRedirect(request.getContextPath()+"/login.html");
return;
}
//2.取出會話數據
String loginName = (String)session.getAttribute("loginName");
if(loginName==null){
//沒有登錄成功,跳轉到登錄頁面
response.sendRedirect(request.getContextPath()+"/login.html");
return;
}
html = "<html><body>歡迎回來,"+loginName+",<a href='"+request.getContextPath()+"/LogoutServlet'>安全退出</a></body></html>";
writer.write(html);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
登錄處理邏輯:LoginServlet.java
/**
* 處理登錄的邏輯
*
*/
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
//1.接收參數
String userName = request.getParameter("userName");
String userPwd = request.getParameter("userPwd");
//2.判斷邏輯
if("eric".equals(userName)
&& "123456".equals(userPwd)){
//登錄成功
/**
* 分析:
* context域對象:不合適,可能會覆蓋數據。
* request域對象: 不合適,整個網站必須得使用轉發技術來跳轉頁面
* session域對象:合適。
*/
/*
request.setAttribute("loginName", userName);
//request.getRequestDispatcher("/IndexServlet").forward(request, response);
response.sendRedirect(request.getContextPath()+"/IndexServlet");
*/
/**
* 一、登錄成功后,把用戶數據保存session對象中
*/
//1.創建session對象
HttpSession session = request.getSession();
//2.把數據保存到session域中
session.setAttribute("loginName", userName);
//3.跳轉到用戶主頁
response.sendRedirect(request.getContextPath()+"/IndexServlet");
}else{
//登錄失敗
//請求重定向
response.sendRedirect(request.getContextPath()+"/fail.html");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
退出處理邏輯:LogoutServlet.java
/**
* 退出邏輯
*
*/
public class LogoutServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 三、安全退出:
* 刪除掉session對象中指定的loginName屬性即可!
*/
//1.得到session對象
HttpSession session = request.getSession(false);
if(session!=null){
//2.刪除屬性
session.removeAttribute("loginName");
}
//2.回來登錄頁面
response.sendRedirect(request.getContextPath()+"/login.html");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
3.5.案例:Session實現通訊錄
暫無