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

前言

  1. 會話:一次會話中包含屢次請求和響應
    注:一次會話表示瀏覽器第一次給服務器發送請求,會話創建,直到有一方斷開爲止
  2. 功能:在一次會話的屢次請求間共享數據
  3. 方式:
    (1) 客戶端會話技術:Cookie
    (2) 服務器端會話技術:Session

Cookie

  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的設置:
html

(2) 在src下建立CookieTest1.javajava

@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.javaweb

@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

Cookie的特色和做用

1.Cookie在客戶端存儲數據,客戶端有了cookie以後,每次發送請求都會把cookie發送給服務器
2.瀏覽器對單個Cookie有大小限制(4KB),對同一個域名下的總cookie數量也有限制(20個)
3.做用:
(1)Cookie通常用於存儲少許的安全性較低的數據
(2)在不登錄的狀況下,完成服務器對客戶端的身份識別,如沒有登陸百度帳號的前提下打開百 度,設置搜索引擎搜索時不提示,之後打開瀏覽器訪問百度時,不會再出現搜索提示框,原 理:百度服務器將設置的Cookie信息保存到瀏覽器,下次訪問百度時,百度服務器獲取瀏覽 器的Cookie,根據Cookie的值決定要不要顯示提示框session

Cookie案例:記錄上一次訪問的時間

  1. 需求:訪問一個Servlet程序:
    (1) 若是是第一次訪問,提示:您好,歡迎您首次訪問
    (2) 若是不是第一次訪問,提示:歡迎回來,您上次的訪問時間是:xxxx
  2. 分析:
    使用Cookie來完成,在服務器判斷客戶端是否有一個名爲lastTime的cookie對象
    (1) 有,不是第一次訪問:
    ①在瀏覽器顯示:歡迎回來,您上次的訪問時間是:xxxx
    ②將如今的時間寫回名爲lastTime的cookie中
    (2) 無,是第一次訪問:
    ①在瀏覽器顯示:您好,歡迎您首次訪問
    ②將如今的時間寫回名爲lastTime的cookie中

代碼演示:使用jsp頁面完成此案例app

<%@ 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) 若是須要相同,進行以下操做:

  1. 客戶端不關閉,服務器關閉以後,兩次獲取的Session是否爲同一個?
    不是同一個Session,可是爲了保證數據的不丟失,Tomcat服務器自動完成:
    (1) Session的鈍化:
    在服務器正常關閉以前,將Session對象序列化到硬盤上
    (2) Session的活化:
    在服務器啓動以後,將Session文件反序列化成爲內存中的Session對象
    注意:也就是說即便獲取的不是同一個Session,可是Session中的數據都是相同的
  2. Session的特色
    (1) Session用於存儲一次會話的屢次請求數據,存在服務器端,一次會話只有一個session對象
    (2) Session能夠存儲任意類型,任意大小的數據
  3. 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相關技術文章或行業資訊,歡迎你們關注和轉發文章!

相關文章
相關標籤/搜索