JavaWeb开发教程之Cookie的使用

什么是Cookie?

Cookie翻译过来的意思是饼干。

Cookie是指一种在用户计算机上存储的小型文本文件,通常用于跟踪和存储有关用户的信息。当用户访问一个网站时,网站会将一个包含有关用户信息的Cookie发送到用户的浏览器。浏览器将该Cookie存储在用户的计算机上,并在以后的请求中将该Cookie发送回服务器。

Cookie通常用于记录用户的偏好设置、登录状态、购物车内容等信息,以提供个性化的用户体验。通过使用Cookie,网站可以识别用户身份以及记录用户的历史操作,例如将商品放入购物车后,网站可以利用Cookie改写浏览器本地的Cookie,添加购物车里的商品数据,这样,当用户关闭网页或者隔几天再来访问时,就会发现购物车中依然保留了之前挑选的商品。

需要注意的是,Cookie并不能用于执行恶意代码或访问用户的计算机文件。另外,由于Cookie包含有关用户的信息,因此用户需要注意保护自己的隐私安全,避免将包含敏感信息的Cookie泄露给未经授权的第三方。

  • Cookie是服务器通知客户端保存用户信息的一种技术,使用key-value格式保存用户信息。
  • 每个Cookie的大小不超过4KB
    Cookie的大小限制因浏览器而异,但通常来说,每个Cookie的大小限制在4KB左右。因此,一个Web站点通常可以发送大约20个Cookie,而一个浏览器可以保存的总Cookie数量通常限制在300个左右。因此,Cookie的大小限制可能会影响网站的性能和用户体验,因为过多的Cookie可能会导致浏览器在处理请求时需要花费更多的时间和带宽。因此,在设计Cookie时应该遵循最佳实践,并尽量减小Cookie的大小,以确保网站的性能和安全性。

在Java Web开发中,Cookie的使用可以通过Java的内置类库来实现。以下是一些常见的使用方法:

  1. 创建Cookie:使用javax.servlet.http.Cookie类创建一个Cookie对象,并设置其名称和值。例如:
Cookie cookie = new Cookie("cookieName", "cookieValue");
  1. 设置Cookie属性:可以通过设置Cookie的属性来控制Cookie的行为。例如,可以设置Cookie的有效期、路径、域名等。例如:
cookie.setMaxAge(60 * 60 * 24 * 7); // 设置有效期为一周(以秒为单位)  
cookie.setPath("/"); // 设置Cookie的路径为根目录  
cookie.setDomain(".example.com"); // 设置Cookie的域名
  1. 将Cookie添加到响应中:在处理请求时,可以将创建的Cookie对象添加到响应中,以便将其发送给客户端。例如:
response.addCookie(cookie);
  1. 读取客户端发送的Cookie:在处理请求时,可以从请求中读取客户端发送的Cookie。例如:
Cookie[] cookies = request.getCookies(); // 获取所有Cookie数组  
for (Cookie cookie : cookies) {  
    String name = cookie.getName();  
    String value = cookie.getValue();  
    // 处理每个Cookie的逻辑  
}
  1. 删除Cookie:如果要删除一个已经存在的Cookie,可以将其有效期设置为一个过去的时间点。例如:
cookie.setMaxAge(0); // 设置有效期为立即过期  
response.addCookie(cookie); // 将修改后的Cookie添加到响应中

需要注意的是,使用Cookie时应该遵循最佳实践,如限制Cookie的大小、设置安全的Cookie属性、使用HttpOnly属性等,以确保安全性和性能。同时,应该注意保护用户的隐私和数据安全,避免将敏感信息存储在Cookie中。

案例实操

创建Cookie的过程
  • 客户端第一次发送请求没有Cookie,服务器会给客户端创建一个Cookie对象后响应给客户端
  • 客户端有了Cookie后,每次请求都会发送给服务器
Cookie的创建
public class CookieServlet extends HttpServlet {
    
    //服务器创建Cookie对象并通知客户端保存
    //该方式基于JDK17,局部变量类型推断
    protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        //1. 创建cookie对象
        var cookie = new Cookie("key1","value1");
        //2. 响应cookie对象给客户端(通知客户端保存Cookie)
        resp.addCookie(cookie);
        //通知客户端Cookie创建成功
        resp.getWriter().write("Cookie创建成功!");
    }
}

服务器获取 Cookie

服务器获取Cookie
public class CookieServlet extends HttpServlet {
    //服务器获取客户端发送的Cookie
    protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 获取客户端发送的Cookie
        Cookie[] cookies = req.getCookies();
        //2. 遍历Cookie
        for (var c: cookies) {
            resp.getWriter().write("Cookie[" + c.getName() + "," + c.getValue() + "]<br/>");
        }
        //3. 获取指定的Cookie
        Cookie isNullCookie = CookieUtils .findCookie("key1",cookies);
        if (isNullCookie  != null) {
            response.getWriter.write("获取到了指定Cookie");
      }
   }
}

Cookie工具类

自定义Cookie工具类CookieUtils,编写获取指定Cookie的方法。

public void CookieUtils {
    //获取指定的Cookie
    public static Cookie findCookie(String cookieName, Cookie[] cookies) {
        if (cookieName != null || cookies.length > 0 || cookies != null) {
            for (var c : cookies) {
                if (cookieName.equals(c.getName())) {
                    return c;
                }
            }
        }
        return null;
    }
}

Cookie值的修改

    //Cookie的修改方式1
    protected void updateCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 创建一个要修改的同名的Cookie对象,同时通过构造器方法赋予新的Cookie值
        var cookie = new Cookie("key1","updateCookie");
        //2. 然后再调用addCookie(Cookie cookie)方法,将Cookie通知给客户端修改同名的Cookie值
        resp.addCookie(cookie);
        resp.getWriter().write("Cookie的名为key1的值被修改成功");
    }
    
    //Cookie的修改方式2
    protected void setCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 查找指定要修改的Cookie对象
        var cookie = findCookie("key1",req.getCookies());
        //判断cookie是否存在
        if (cookie != null) {
            //2. 调用setValue()赋予新的Cookie值
            cookie.setValue("setCookie");
            //通知客户端保存(覆盖)修改后的Cookie值
            resp.addCookie(cookie);
            resp.getWriter().write("Cookie的名为key1的值被修改成功");
        }
    }

Cookie的生命周期控制

Cookie 的生命周期控制指的是如何管理Cookie有效时长。即Cookie什么时候被销毁(删除)

  • setMaxAge(参数) 设置Cookie有效时长。

参数说明:
setMaxAge(正数) ,表示在指定的秒数后过期
setMaxAge(-1),表示浏览器一关,Cookie 就会被删除(默认值是-1)
setMaxAge(0),表示马上删除 Cookie

public class CookieServlet extends HttpServlet {
    //Cookie的生命控制设置(存活时间设置)
    public void lifeCookie(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
        //1. 创建Cookie对象
        var cookie = new Cookie("key1","LifeCookie");
        //2. 设置Cookie的有效时长(单位:秒)
        cookie.setMaxAge(60 * 60 * 24 * 10); //有效时长10天
        response.addCookie(cookie);
        response.getWriter().write("Cookie十天后将被删除");
    }

    //设置立即删除Cookie
    public void deleteNowCookie(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
        //1. 创建Cookie对象
        var cookie = new Cookie("key1","deleteCookie");
        //2. 设置Cookie的有效时长(单位:秒)
        cookie.setMaxAge(0); //立即删除
        response.addCookie(cookie);
        response.getWriter().write("Cookie已被删除");
    }
}

     //默认Session级别删除Cookie
    public void defaultDelCookie(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
        //1. 创建Cookie对象
        var cookie = new Cookie("key1","deleteCookie");
        //2. 设置Cookie的有效时长(单位:秒)
        cookie.setMaxAge(-1); //seesion级别删除,即:浏览器关闭删除
        response.addCookie(cookie);
        response.getWriter().write("Cookie已被删除");
    }
}

设置Cookie的有效请求

Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器。哪些不发。
path 属性是通过请求的地址来进行有效的过滤。
如设置有效路径:
CookieA path=/工程路径
CookieB path=/工程路径/abc

请求地址如下:
http://ip:port/工程路径/a.html
CookieA 发送
CookieB 不发送

http://ip:port/工程路径/abc/a.html
CookieA 发送
CookieB 发送

protected void testPath(HttpServletRequest req, HttpServletResponse resp) throws    
    ServletException,IOException {
    Cookie cookie = new Cookie("path1", "path1");
    // getContextPath() ===>>>> 得到工程路径
    cookie.setPath( req.getContextPath() + "/abc" ); // ===>>>> /工程路径/abc
    resp.addCookie(cookie);
    resp.getWriter().write("创建了一个带有 Path 路径的 Cookie");
}

综合练习

场景:实现用户免登陆(10天免登):

  1. 记住用户名和密码十天 setMaxAge(60 * 60 * 24 * 10)
  2. 十天免登录
<body>
    <form action="http://localhost:8080/pro03/login" method="get">
        <input type="text" name="username" value="${ cookie.username.value }" maxlength="10"/><br/>
        <input type="password" name="pwd" maxlength="8"/><br/>
        <input type="submit" value="登录"/>
        <input type="reset" value="重置">
    </form>
</body>
public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("pwd");
        String uname = "lisi";
        String pwd = "123456";
        if(uname.equalsIgnoreCase(username) && pwd.equalsIgnoreCase(password)){
            Cookie cookie = new Cookie(username, password);
            cookie.setMaxAge(60*60*24*10); //设置cookie内十天有效
            resp.addCookie(cookie);
            System.out.println("登录成功!");
        } else {
            System.out.println("登录失败!");
        }
    }
}
  <servlet>
    <servlet-name>loginServlet</servlet-name>
    <servlet-class>cn.evan.servlet.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>loginServlet</servlet-name>
    <url-pattern>/login</url-pattern>
  </servlet-mapping>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容