JavaWeb = Session詳解與使用

前言

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的選擇

  1. cookie將數據保存在瀏覽器端,數據相對不安全.建議敏感的數據不要放在cookie中,而且數據大小是有限制的

    1. 成本低,對服務器要求不高

    2. 瀏覽器,解決這個不足,localStroage【項目二中講解...】

  2. session將數據保存在服務器端,數據相對安全.數據的大小要比cookie中數據靈活很多

    1. 成本較高,對服務器壓力較大

 

二、三大域對象總結:

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分鐘.
手動調用sessioninvalidate的方法
 

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);
    }
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章