JavaEE基础之-session&cookie

发布于:2025-03-01 ⋅ 阅读:(13) ⋅ 点赞:(0)

目录

1.Cookie概述

1.1 什么叫Cookie

1.2 Cookie规范

1.3 Cookie的作用

2. Cookie示例(精通)

2.1. 保存Cookie到客户端

2.2 服务器端读取Cookie

3. Cookie生命周期(熟练)

4. Cookie的浏览器管理(熟练)

4.1. Google Chrom

4.1.1. 查看cookie

4.1.2. 清理cookie

4.2. Firefox

4.2.1. 查看Cookie

4.2.2. 清理Cookie

5. Cookie的路径(熟练)

5.1. Cookie的path属性

5.2. Cookie 路径的作用:

5.3. Cookie路径的使用

6. Cookie保存中文(熟练)

7. Cookie的禁用(熟练)

8. HttpSession概述(熟练)

9. HttpSession原理(依赖Cookie)(精通)

10. HttpSession失效(精通)

11. 面试题

11.1. Session和Cookie的区别(精通)

11.2 使用Cookie实现自动登录

练习2

练习3:


1.Cookie概述

1.1 什么叫Cookie

        Cookie翻译成中文是小甜点,小饼干的意思。在HTTP中它表示服务器送给客户端浏览器的小甜点。其实Cookie就是一个键和一个值构成的,随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器

1.2 Cookie规范

        你大可以放心,Cookie不会占满你的硬盘。因为一个Cookie最多只有4KB,并且浏览器最多可以保存300个Cookie。当然,在浏览器大战的今天,一些浏览器为了打败对手,可能对Cookie规范“扩展”了一些,例如每个Cookie的大小为8KB,最多可保存500个Cookie等!但也不会出现把你硬盘占满的可能!

        不同的浏览器之间不能共享Cookie!!!(比如自己的电脑肯定接受不了其他人的)

1.3 Cookie的作用

        Cookie的作用可大了,但无论怎么夸大Cookie的作用都离不开“ 跟踪客户端状态 ”这句话。我们知道Cookie是服务器保存在客户端的信息,然后客户端会在下次请求时把Cookie再还给服务器,这样服务器就可以通过信息来识别客户端了。


2. Cookie示例(精通)

2.1. 保存Cookie到客户端

        这是响应工作的一部分,所以这个方法是response对象的。并且Cookie是HTTP协议中的内容,所以保存Cookie是HttpServletResponse类的方法。

        Ø void addCookie(Cookie c):添加Cookie对象到当前response对象中,这个方法可以被调用多次,从而完成添加多个Cookie对象到response中。

Cookie cookie = new Cookie("admin", "Houlili");
response.addCookie(cookie);

        通过浏览器的开发者工具我们可以看到,该请求的响应头中被添加了Set-Cookie的值:

        同样根据浏览器的开发者工具我们可以看到http://localhost:8080的网址的cookie中被加入了admin=Houlili 的信息:

        这时我们再对服务器进行访问就会发现,访问服务器时请求时客户端浏览器带着cookie的值的:

2.2 服务器端读取Cookie

        我们现在已经可以保存Cookie到客户端了,但还没有学习让服务器如何读取Cookie。

        如果浏览器保存了Cookie,那么会在下一次请求时把Cookie放到请求头中发送给服务器,这时服务器需要在请求中读取Cookie。既然是在请求中读取,那么当然是使用request对象来读取了。

        HttpServletRequest:Cookie[] getCookies()

示例:

Cookie[] cookies = request.getCookies();
if(cookies != null){
    for(Cookie cookie : cookies){
            System.out.println(cookie.getName() +":"+ cookie.getValue());
    }
}

 


3. Cookie生命周期(熟练)

        Cookie会在客户端存活多久呢?这就是Cookie的生命了。默认情况下,Cookie只在浏览器的内存中存活,也就是说,当你关闭浏览器后,Cookie就会消失

        可以使用 Cookie#setMaxAge(int expiry) 来设置Cookie的存活时间。参数expiry表示Cookie存活的秒数。

        Ø cookie.setMaxAge(60*60*24*30*12):表示cookie对象可存活1年。就算关闭浏览器,就算重启客户端电脑,cookie也会存活1小时。因为当maxAge大于0时,浏览器不仅会把cookie保存在浏览器内存中,还会把cookie保存到硬盘上。

        Ø cookie.setMaxAge(-1):cookie的maxAge属性的默认值就是-1(其实只要是负数都是一个意思),表示只在浏览器内存中存活。一旦关闭浏览器窗口,那么cookie就会消失。

        Ø cookie.setMaxAge(0):cookie被作废!表示cookie即不在内存中存活,也不在硬盘上存活,这样的cookie设置只有一个目的,那就是覆盖客户端原来的这个cookie,使其作废。


4. Cookie的浏览器管理(熟练)

4.1. Google Chrom

4.1.1. 查看cookie

4.1.2. 清理cookie

设置-隐私设置和安全性-清除浏览数据:

4.2. Firefox

4.2.1. 查看Cookie

4.2.2. 清理Cookie

选项 - 隐私与安全 - Cookie和网站数据 - 清除数据


5. Cookie的路径(熟练)

5.1. Cookie的path属性

Cookie还有一个path属性,可以通过 Cookie#setPath(String) 方法来设置。你可以使用HttpWatch查看响应中的Set-Cookie中是否存在路径。下面是通过Chrome查看Cookie信息。

 

Cookie cookie2=new Cookie("newC","newCValue");
cookie2.setPath("/login");
response.addCookie(cookie2);

 

        也就是说,就算你不设置Cookie的path,Cookie也是有路径的。这个路径就是请求的路径。例如在请求:

http://localhost:8080/cookie_demo/path

时,服务器响应了一个Cookie,那么这个Cookie的默认路径就是/cookie_demo。

        如果是在请求:

http://localhost:8080/cookie_demo/path/son

时,服务器响应了一个Cookie,那么这个Cookie的默认路径就是/cookie_demo/path。

5.2. Cookie 路径的作用:

        到现在我们还没说过Cookie的path有什么用,现在我们来聊聊path的作用。

                首先声明一点,path不是指Cookie在客户端存放的路径!!!不同的浏览器存放Cookie的路径是不同的!!!你不能通过Cookie的path来指定Cookie文件的存放路径!!!

        那么Cookie的path是干什么的呢?假设你的浏览器当前已经有了两个Cookie:

Ø cookie1:name=path1;value=pathvalue1;path=/cookie_demo;

Ø cookie2:name=path1;value=pathvalue2;path=/cookie_demo/path;

        当访问http://localhost:8080/cookie_demo/*时,请求头中会包含cookie1,而不会包含cookie2。

        当访问http://localhost:8080/cookie_demo/path/*时,请求头中会包含cookie1和cookie2。

        也就是说,在访问子路径时,会包含其父路径的Cookie,而在访问父路径时,不包含子路径的Cookie。

        在访问login.html时,不包含子路径

5.3. Cookie路径的使用

        如果你想在BServlet中设置的Cookie,在客户端访问AServlet时也包含在请求头中,那么就需要设置BServlet中的Cookie的path:

Ø c2.setPath(“/cookie_demo”):硬编码;

Ø c2.setPath(request.getContextpath() + “/”):活编码。

        

        这样就可以设置Cookie的路径,保存在访问AServlet时,也会包含BServlet中添加的Cookie。

        Cookie的 SetPath 设置cookie的路径,这个路径直接决定服务器的请求是否会从浏览器中加载某些cookie

        首先默认情况如果不设置cookie的path,默认是 /项目名称/当前路径的上一层地址如:请求路径:/cookie_demo/servlet/login, cookie的路径:/cookie_demo/servlet

        如果我们设置path,如果当前访问的路径包含了cookie的路径(当前访问路径在cookie路径基础上要比cookie的范围小)cookie就会加载到request对象之中。


6. Cookie保存中文(熟练)

        Cookie中保存中文,次要

        Cookie中是不可以设置中文的,但可以使用URLEncodor.encode()方法编码后在存放到Cookie中。在获取Cookie时,需要先使用URLDecoder.decode()方法解码,再使用。

添加cookie:

Cookie cookie1 = new Cookie("username", 
URLEncoder.encode(username,"UTF-8"));

 读取cookie:

String username=request.getParameter("username");
String password=request.getParameter("password");
Cookie cookie1 = new Cookie("admin", "Houlili");
response.addCookie(cookie1);

Cookie cookie2=new Cookie("newC","newCValue");
cookie2.setPath("/login");
response.addCookie(cookie2);

Cookie cookie3 = new Cookie("username",
        URLEncoder.encode(username,"UTF-8"));
response.addCookie(cookie3);

Cookie[] cookies = request.getCookies();
if(cookies != null){
    for(Cookie cookie : cookies){
        System.out.println(cookie.getName() +":"+ cookie.getValue());
    }
}
再次访问时:

7. Cookie的禁用(熟练)

        默认情况下浏览器的cookie是 被启用的,但是其实我们是可以手动的禁用cookie的,强烈不建议禁用cookie;
        Cookie一旦被禁用掉绝大多数互联网的网站都无法登录,这个跟我们后续要讲解的session有关。
        那么我们如何通过程序来通过程序判断用户的浏览器上的cookie是否被禁用了呢,其实很简单,我们可以通过去刚刚添加的cookie,如果没有取到,说明cookie被禁用。

8. HttpSession概述(熟练)

Ø 会话跟踪之session
        session也是域对象之一,它的范围是在 一个会话范围内有效(会话域对象)。session既然是域对象,那么当然就要有 getAttribute()和 setAttribute()系列方法了。
        在 一个会话内共享一个session对象,所以session中可以保存一个会话内的数据。例如当前用户的信息。
        session的范围大于request,可以在 一个会话中多个请求之间共享数据。但session的范围小于ServletContext(application),session不能在多个用户之间共享数据。
        目前所学过的域对象的作用范围:
                  ServletContext  > HttpSession > HttpServletRequest
                                应用域对象 会话域对象 请求域对象
Ø 获取session对象
        使用 request.getSession()方法就可以获取session对象。
        有了session,就不用使用Cookie来跟踪会话了!但是session不能像Cookie那样长命,一旦用户关闭浏览器窗口,那么session就死掉了。没有设置时长的。
  • Cookie:Cookie 分为会话 Cookie 和持久化 Cookie。
    • 会话 Cookie:它确实是在关闭浏览器时就会被删除,因为它没有设置过期时间,仅在当前浏览器会话期间有效。比如,你在一个购物网站上添加了一些商品到购物车,这些信息可能会临时存储在会话 Cookie 中,当你关闭浏览器后,再次打开时购物车可能就空了,除非网站使用了其他方式来保存购物车信息。
    • 持久化 Cookie:它会在浏览器中保存一段时间,具体时长由设置的过期时间决定,即使关闭浏览器,在过期时间到达之前,它依然存在于用户的计算机中。例如,你登录某些网站选择了 “记住我” 选项,那么网站会生成一个持久化 Cookie,在一定时间内你再次打开浏览器访问该网站时,会自动登录,无需重新输入用户名和密码。
  • Session:Session 也有不同的情况。
    • 默认情况:通常情况下,Session 的默认生命周期是浏览器会话期间,当你关闭浏览器时,与该浏览器会话相关的 Session 会被认为过期失效。比如你在一个论坛网站登录后进行一些操作,关闭浏览器后,再次打开浏览器访问论坛时,可能就需要重新登录,因为之前的 Session 已经结束。
    • 设置了持久化的情况:通过设置 Session 的持久化机制,比如设置较长的过期时间,或者使用服务器端的 Session 存储方案将 Session 数据持久化到数据库等,即使关闭浏览器,在 Session 的有效时间内,再次打开浏览器访问相关网站时,仍然可以使用同一个 Session。比如一些大型的电商平台,为了提供更好的用户体验,可能会设置较长时间的持久化 Session,用户在关闭浏览器后,短时间内再次打开访问平台,仍能保持登录状态和之前的一些操作记录。

9. HttpSession原理(依赖Cookie)(精通)

        我们都知道HTTP是无状态协议,但是为什么session可以跟踪会话状态呢?没错,session依赖Cookie。
        
        当客户端第一次访问服务器时,服务器会为 客户端创建一个session对象,然后把session对象放到session池中,在响应时把sessionId通过Cookie响应给客户端。注意, 只有在第一次访问时,服务器才会创建session,给客户端响应sessionId。从此以后就不会了!
        
        当客户端 再次访问服务器时,会在请求中 带着sessionId给服务器,服务器通过sessionId到session池中找到session对象,这就可以完成会话跟踪了。也就是说, 服务器端保存的是session对象,而客户端只有sessionId。每次访问都需要通过客户端的sessionId来匹配服务器端的session对象!这样用户在session中保存的数据就可以再次被使用了。
        
        sessionId是服务器通过Cookie发送给客户端浏览器的,这个Cookie的maxAge为 -1,即只在浏览器内存中存在。如果你关闭所有浏览器窗口,那么这个Cookie就会消失了!

10. HttpSession失效(精通)

        session失效有如下几个原因:
Ø session.invalidate()方法注销session
Ø session超时
<session-config>
    <!-- session的超时时间,以分钟为单位 -->    
<session-timeout>1</session-timeout>
</session-config>

Ø Cookie被禁用


11. 面试题

11.1. Session和Cookie的区别(精通)

        Ø session 在服务器端,cookie 在客户端(浏览器)

        Ø session 默认被存在在服务器的一个文件里(不是内存)

        Ø session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)

        Ø session 可以放在 文件、数据库、或内存中都可以。

        Ø 用户验证这种场合一般会用 session 因此,维持一个会话的核心就是客户端的唯一标识,即 session id

11.2 使用Cookie实现自动登录

<!DOCTYPE html><html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="login" method="post">
    用户:<input type="text" name="username"/><br>
    密码:<input type="password" name="password"/><br>
    <input type="checkbox" value="1" name="auto"/> 一天内自动登陆<br>
    <input type="submit" value="登陆"/>
</form>
</body>
</html>

 Java代码:

package cn.tx.servlet;
import cn.tx.model.User;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
/** * 模拟自动登陆方法 */
@WebServlet(name = "LoginServlet",urlPatterns = "/login")
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");
           String auto = request.getParameter("auto");
           // 统一设置response响应格式及编码
           response.setContentType("text/html;charset=utf-8");
           response.setCharacterEncoding("UTF-8");
           // 判断是否提交用户信息
           if(username == null && password == null && auto == null){
           // 用来接收cookie的value信息
                       String cookieValue = null;
                       // 获取用户端cookies 
                       Cookie[] cookies = request.getCookies();
                       // 如果cookies不为null  尝试获取name为txjavac的cookie的value
                       if(cookies != null){
                             for(Cookie ck : cookies){
                                    if(ck.getName().equals("txjavac")){
                                            cookieValue = ck.getValue();
                                    }                
                             }            
                       }            
                       // 如果没有获取到cookie的value 返回信息
                       if(cookieValue == null){
                             response.getWriter().write("您还未进行登陆,请进行登陆!!!");                
                             return;            
                       }else{
                       // 如果获取到                
                       // 对该信息进行解码                
                       BASE64Decoder decoder = new BASE64Decoder();                
                       cookieValue = new String(decoder.decodeBuffer(cookieValue));                
                       // 对解码后的字符串进行切分                
                       String[] split = cookieValue.split(":");                
                       // 获取用户名和密码                
                       username = split[1];                
                       password = split[2];                
                       // 创建用户对象                
                       User user = new User(username,password);                
                       // 获取session                
                       HttpSession session = request.getSession();                
                       // 把用户对象存储到session中                
                       session.setAttribute("user",user);                
                       // 返回内容                
                       response.getWriter().write("尊敬的"+username+",欢迎您!!!");                
                       return;            
                       }        
        }        
        // 判断用户名或密码是否正确        
        if(username!=null && password!=null && username.equals("admin") && password.equals("txjava")){            
            // 创建用户对象            
            User user = new User(username,password);            
            // 获取session会话对象            
            HttpSession session = request.getSession();            
            // 把用户存入session中            
            session.setAttribute("user",user);            
            // 用户名密码正确的话,判断是否勾选了一天内自动登陆            
            if(auto != null && auto.equals("1")){                
                // 拼接存储于cookie的value值                
                String value = "txjava:" + username + ":" + password + ":" + 24*3600;                
                // 进行BASE64编码                
                BASE64Encoder encoder = new BASE64Encoder();                
                value = encoder.encode(value.getBytes());                
                // 创建cookie并且设置一天失效后添加到response                
                Cookie cookie = new Cookie("txjavac",value);                
                cookie.setMaxAge(24*3600);                
                response.addCookie(cookie);            
             }            
             response.getWriter().write("尊敬的"+username+",欢迎您!!!");            
             return;        
       }else {            
           response.getWriter().write("用户名或密码错误!!!");            
           return;        
       }    
   }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);    
        }
}

练习2

        设置cookie时长,关闭浏览器,查看是否还能获取到session

关闭浏览器:

        事实证明,关闭浏览器再进入,通过cookie获得sessionID还能获取session。

练习3:

获取上次访问时间:

html代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>获取上次访问时间</title>
</head>
<body>
<form action="lt" method="get">
    <input type="text" name="username"/>
    <input type="password" name="password"/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

java代码:

package cn.tx.response;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

@WebServlet(name = "lt",urlPatterns = "/lt")
public class LastServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/html;charset=UTF-8");
            // 获取当前时间戳
            long currentTimeStamp = System.currentTimeMillis();

            Cookie[] cookies = req.getCookies();
            String lasttimeStr = null;
            if (cookies != null) {
                for (Cookie c : cookies) {
                    if ("lastTime".equals(c.getName())) {
                        lasttimeStr = c.getValue();
                        break;
                    }
                }
            }

            PrintWriter out = resp.getWriter();
            if (lasttimeStr != null) {
                try {
                    long lastTimeStamp = Long.parseLong(lasttimeStr);
                    // 将时间戳转换为日期字符串
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
                    String lastVisitDate = sdf.format(new Date(lastTimeStamp));
                    out.write("上次访问时间为:" + lastVisitDate);
                } catch (NumberFormatException e) {
                    out.write("无法解析上次访问时间戳,请稍后重试。");
                }
            } else {
                out.write("这是第一次登录访问");
            }

            Cookie lastTimeCookie = new Cookie("lastTime", String.valueOf(currentTimeStamp));
            lastTimeCookie.setMaxAge(24 * 60 * 60);
            lastTimeCookie.setPath("/");
            resp.addCookie(lastTimeCookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到