JavaEE基础之-session&cookie

目录

1.Cookie概述

[1.1 什么叫Cookie](#1.1 什么叫Cookie)

[1.2 Cookie规范](#1.2 Cookie规范)

[1.3 Cookie的作用](#1.3 Cookie的作用)

[2. Cookie示例(精通)](#2. Cookie示例(精通))

[2.1. 保存Cookie到客户端](#2.1. 保存Cookie到客户端)

[2.2 服务器端读取Cookie](#2.2 服务器端读取Cookie)

[3. Cookie生命周期(熟练)](#3. Cookie生命周期(熟练))

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

[4.1. Google Chrom](#4.1. Google Chrom)

[4.1.1. 查看cookie](#4.1.1. 查看cookie)

[4.1.2. 清理cookie](#4.1.2. 清理cookie)

[4.2. Firefox](#4.2. Firefox)

[4.2.1. 查看Cookie](#4.2.1. 查看Cookie)

[4.2.2. 清理Cookie](#4.2.2. 清理Cookie)

[5. Cookie的路径(熟练)](#5. Cookie的路径(熟练))

[5.1. Cookie的path属性](#5.1. Cookie的path属性)

[5.2. Cookie 路径的作用:](#5.2. Cookie 路径的作用:)

[5.3. Cookie路径的使用](#5.3. Cookie路径的使用)

[6. Cookie保存中文(熟练)](#6. Cookie保存中文(熟练))

[7. Cookie的禁用(熟练)](#7. Cookie的禁用(熟练))

[8. HttpSession概述(熟练)](#8. HttpSession概述(熟练))

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

[10. HttpSession失效(精通)](#10. HttpSession失效(精通))

[11. 面试题](#11. 面试题)

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

[11.2 使用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中。

java 复制代码
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()

示例:

java 复制代码
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信息。

java 复制代码
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。

到现在我们还没说过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:

java 复制代码
Cookie cookie1 = new Cookie("username", 
URLEncoder.encode(username,"UTF-8"));

读取cookie:

java 复制代码
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超时

XML 复制代码
<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实现自动登录

html 复制代码
<!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代码:

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代码:

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代码:

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);
    }
}
相关推荐
小志开发7 分钟前
Java 多态:代码中的通用设计模式
java·开发语言
serendipity_hky24 分钟前
【easy视频 | day03】客户端获取视频分类 + 上传投稿
java·spring boot·缓存·音视频·idea
计算机毕设定制辅导-无忧学长32 分钟前
Maven 私服的搭建与使用(二)
java·maven
August_._33 分钟前
【Maven】基于IDEA学习 Maven依赖 与 工程继承、聚合关系
java·windows·后端·学习·maven·intellij-idea
Neil__Hu1 小时前
Go的基本语法学习与练习
java·c语言·c++·python·qt·学习·golang
彬sir哥1 小时前
水仙花数(华为OD)
java·c语言·javascript·c++·python·算法
码熔burning1 小时前
(十 八)趣学设计模式 之 观察者模式!
java·观察者模式·设计模式
Eugene__Chen1 小时前
java常见面试01
java·开发语言·面试
ZIM学编程1 小时前
JavaWeb5、Maven
java·maven
大G哥2 小时前
jenkins集成docker发布java项目
java·运维·开发语言·docker·jenkins