1. 程式人生 > 實用技巧 >金九銀十已到!Cookie 和 Session的這些知識你必須知道,面試必問!

金九銀十已到!Cookie 和 Session的這些知識你必須知道,面試必問!

前言

  1. 會話:一次會話中包含多次請求和響應
    注:一次會話表示瀏覽器第一次給伺服器傳送請求,會話建立,直到有一方斷開為止
  2. 功能:在一次會話的多次請求間共享資料
  3. 方式:
    (1) 客戶端會話技術:Cookie
    (2) 伺服器端會話技術:Session
  1. 概念:將資料儲存到客戶端,客戶端有了Cookie之後,每次請求都會發送給伺服器
  2. 使用步驟:
    (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

  1. 上述程式原理:基於響應頭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案例:記錄上一次訪問的時間

  1. 需求:訪問一個Servlet程式:
    (1) 如果是第一次訪問,提示:您好,歡迎您首次訪問
    (2) 如果不是第一次訪問,提示:歡迎回來,您上次的訪問時間是:xxxx
  2. 分析:
    使用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的介紹

  1. 概念:Session是伺服器端會話技術,在一次會話的多次請求間共享資料,將資料儲存到伺服器 端,常用來儲存使用者登入之後的資訊
  2. 快速入門:
    (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!

  1. 上述程式原理:Session底層是基於Cookie來實現的

    注意:每個Session會話都有一個唯一的id值作為標識,getId方法可得到此id值

Session的細節

  1. Session被銷燬的方式
    (1)伺服器關閉
    (2)Session物件呼叫invalidate()
    (3)Session預設失效時間:30分鐘,可以到web.xml中修改配置檔案修改預設失效時間

     <session-config>
         <session-timeout>30</session-timeout>
     </session-config>
    
    
  2. 客戶端關閉之後伺服器不關閉,兩次獲取的Session是否為同一個?
    (1) 預設情況下,不是,Cookie消失,其中的Session自然也消失
    (2) 如果需要相同,進行如下操作:

  3. 客戶端不關閉,伺服器關閉之後,兩次獲取的Session是否為同一個?
    不是同一個Session,但是為了保證資料的不丟失,Tomcat伺服器自動完成:
    (1) Session的鈍化:
    在伺服器正常關閉之前,將Session物件序列化到硬碟上
    (2) Session的活化:
    在伺服器啟動之後,將Session檔案反序列化成為記憶體中的Session物件
    注意:也就是說即使獲取的不是同一個Session,但是Session中的資料都是相同的

  4. Session的特點
    (1) Session用於儲存一次會話的多次請求資料,存在伺服器端,一次會話只有一個session物件
    (2) Session可以儲存任意型別,任意大小的資料

  5. 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

驗證碼的底層原理

谷歌圖片驗證碼的使用

谷歌驗證碼的使用步驟:

  1. 匯入谷歌驗證碼的jar包:
  2. 在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域中,每次訪問都會生成不同的驗證碼

  1. 在表單中使用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>

  1. 在伺服器處理獲取的驗證碼
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相關技術文章或行業資訊,歡迎大家關注和轉發文章!