JavaWeb = Cookie讲解

标签: JavaWeb  cookie

一。会话:

什么是会话:

日常生活中:从拨通电话到挂断电话之间的一连串你问我答的过程就是一个会话。

B/S架构中:从浏览器第一次给服务器发送请求时,建立会话;直到有一方断开,会话结束。

一次会话:包含多次请求响应。

会话技术

Http是一个无状态协议,同一个会话的连续两个请求相互独立,彼此并不了解

用于==存储==浏览器与服务器在请求和响应过程中产生的==数据==

在域对象中,HttpServletRequest对象和ServletContext对象 都可以对数据进行保存,但是这两个对象都不可行,具体原因如下:
例如,用户甲和乙分别登录了购物网站,甲购买了一个Nokia手机,乙购买了一个Ipad,当这两个用户结账时,Web服务器需
要对用户甲和乙的信息分别进行保存。在前面章节讲解的域对象中,HttpServletRequest对象和ServletContext对象
都可以对数据进行保存,但是这两个对象都不可行,具体原因如下:
1)客户端请求Web服务器时,针对每次HTTP请求,Web服务器都会创建一个HttpServletRequest对象,该对象
只能保存本次请求所传递的数据。由于购买和结账是两个不同的请求,因此,在发送结账请求时,之前购买请求中的
数据将会丢失。
2)使用ServletContext对象保存数据时,由于同一个Web应用共享的是同一个ServletContext对象,因此,当用
户在发送结账请求时,由于无法区分哪些商品是哪个用户所购买的,而会将该购物网站中所有用户购买的商品进行结
算,这显然也是不可行的。
3)为了保存会话过程中产生的数据,在Servlet技术中,提供了两个用于保存会话数据的对象,分别是Cookie
Session

客户端会话技术:cookie

服务器端会话技术:session

注意:

Servlet的会话技术主要有cookiesession两种 。

二。Cookie

1.Cookie:浏览器端的会话技术,它通过在浏览器中记录一些服务器传递过来的数据,解决会话从什么时候开始,到什么时候结
束。
Cookie作用:在一次会话的多次请求之间共享数据,将数据保存到客户端(浏览器)
 
应用场景:
 
1. 记住用户名
2. 自动登录(记住用户名和密码)
3. 记录用户上次访问时间
4. 浏览器商品记录
 
2.Cookie基本使用:
 
常用方法:
Cookie: 
Cookie(String name, String value) 
创建cookie对象
 String getName() 
获取cookie的名称 
String getValue() 
获取cookie的值 
void setPath(String uri) 
设置cookie的路径——浏览器根据这个路径判断那些cookie要发送给服务器
HttpServletResponse: 

void addCookie(Cookie cookie) 

将cookie发送给浏览器
HttpServletRequest:

 Cookie[] getCookies() 

获取浏览器发送的cookie
1. 设置数据到cookie中
	// 1.创建cookie对象,设置数据
		Cookie cookie = new Cookie(String name,String value);
	// 2.通过response,响应(返回)cookie
		response.addCookie(cookie);

2. 从cookie中获取数据
	// 1.通过request对象,接收cookie数组
		Cookie[] cookies = request.getCookies();
@WebServlet("/SetServlet")
public class SetServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.创建cookie对象,设置数据
        Cookie cookie = new Cookie("name","ack");
        // 2.通过response,响应(返回)cookie
        response.addCookie(cookie);
    }

}
@WebServlet("/GetServlet")
public class GetServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.通过request对象,接收cookie数组
        Cookie[] cookies = request.getCookies();
        // 2.遍历数组
        if(cookies!=null){
            for (Cookie c : cookies) {
                String name = c.getName();
                String value = c.getValue();
                System.out.println(name + " : " + value);
            }
        }
    }

}

3.工作原理

4.Cookie细节

(1)服务器发送多个cookie

是可以的
    // 1. 创建多个cookie对象
        Cookie cookie1 = new Cookie("name","lucy");
        Cookie cookie2 = new Cookie("age","18");
    // 2. 通过response响应多个
        response.addCookie(cookie1);
        response.addCookie(cookie2);

@WebServlet("/MultipleCookie")
public class MultipleCookie extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 创建多个cookie对象
        Cookie cookie1 = new Cookie("name","lucy");
        Cookie cookie2 = new Cookie("age","18");
        // 2. 通过response响应多个
        response.addCookie(cookie1);
        response.addCookie(cookie2);
    }

}

(2)Cookie在浏览器保存时间

* 默认情况下
    浏览器关闭(会话结束),cookie销毁(内存)
    
* 设置cookie的存活时间
        cookie.setMaxAge(int second); -- 单位是秒
            正数:指定存活时间,持久化浏览器的磁盘中,到期后自动销毁
            负数:默认浏览器关闭,cookie销毁
            零:立即销毁

void setMaxAge(int expiry)
 
设置cookie的最大生存时间(单位:秒),超过了该时间后Cookie会自动销毁
注意 : 当时间为0的时候 , 意思为立即删除此Cookie(前提:path和name必须一致)。
@WebServlet("/MaxAgeCookie")
public class MaxAgeCookie extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.创建cookie对象
        Cookie cookie = new Cookie("product", "xiaomi");
        // 2.设置cookie存活时间
        // cookie.setMaxAge(-1); // 默认值,浏览器关闭自动销毁
        // cookie.setMaxAge(60);// 存活30秒,到期自动销毁
        cookie.setMaxAge(0); // 立即销毁...

        //3. response响应cookie
        response.addCookie(cookie);
    }

}

(3)Cookie是否可以存储中文

* tomcat8之前的版本,不支持中文
        URLEncoder 编码
        URLDecoder 解码

* tomcat8以后的版本,支持中文...
    Rfc6265Cookie规范,不允许使用 分号、空格、逗号等一些特殊符号...

我们给cookie添加数据的时候需要注意数据的内容,在cookie值中不能使用分号(;)、逗号(,)、空格。
如果存入的数据不合法,会出现一个错误:
java.lang.IllegalArgumentException:
An invalid character [32] was present in the Cookie value
 
那么如果我们一定要保存非法数据在cookie中,该如何操作呢?
答:cookie对于基本符号、数字、和字母是可以存储的,因此,我们只需要将非法数据转换成符号、数字、和字母
形式存储,要使用的时候再转换成正常的数据(解码)即可。

API介绍:

(1) URLEncoder类: static String encode(String s, String enc) 

将指定的字符串,按指定的编码表编码

(2)URLDecoder类: static String decode(String s, String enc) 

将指定的字符串,按指定的编码表解码

 

@WebServlet("/EncodeCookie")
public class EncodeCookie extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String product = "华为荣耀";
        product=  URLEncoder.encode(product, "UTF-8");

        // 1.创建cookie对象
        Cookie cookie = new Cookie("product", product);
        // 2.response响应cookie
        response.addCookie(cookie);
    }

}
@WebServlet("/GetServlet")
public class GetServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.通过request对象,接收cookie数组
        Cookie[] cookies = request.getCookies();
        // 2.遍历数组
        if(cookies!=null){
            for (Cookie c : cookies) {
                String name = c.getName();
                String value = c.getValue();
                // 解码
                value = URLDecoder.decode(value, "UTF-8");
                System.out.println(name + " : " + value);
            }
        }
    }

}

(4)Cookie共享数据的范围?

在一个tomca服务器中,部署了多个web项目,那么这些web项目的Cookie能否共享?**

* 默认情况下不可以
	默认cookie的携带路径,是当前设置cookie的serlvet父路径。。。。
		设置cookie:http://localhost:8080/dcookie/EncodeCookie
		默认携带路径:http://localhost:8080/dcookie
		
* 指定cookie的携带路径
		cookie.setPath(String path);
		举例:
			cookie.setPath("/");
				/ 相当于 http://localhost:8080/
			此cookie携带路径
				访问
                    http://localhost:8080/dcookie
                    http://localhost:8080/dresponse
                    
* 注意
		cookie的携带路径不同,名称可以重复....
=======================================================================
=======================================================================

设置cookie
		http://localhost:8080/dcookie/aa/SetCookie
	接收cookie
		http://localhost:8080/dcookie/bb/GetCookie
		
	默认情况下,是否能获取aa目录下的cookie数据?
		是不可以....
	在当前项目下共享cookie
		cookie.setPath("/项目名")
@WebServlet("/PathCookie")
public class PathCookie extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String product = "小米";
        product = URLEncoder.encode(product, "UTF-8");

        // 1.创建cookie对象
        Cookie cookie = new Cookie("product", product);
        // 2.设置cookie的携带路径
        cookie.setPath("/");
        // 3.response响应cookie
        response.addCookie(cookie);
    }

}

不同tomcat服务器之间Cookie能否共享

* 默认情况下不可以

* 多个服务器之间的数据共享cookie,需要在同一个一级域名下
        cookie.setDomain(".jd.com")

五。Cookie特点

1. cookie存储数据都在客户端(浏览器)

2. cookie的存储数据只能是字符串

3. cookie单个大小不能超过4KB

4. 同一个域名下cookie数量不能超过50个

5. cookie路径不同,可以重名出现

6. cookie存储的数据不太安全

三,案例

1.访问上次记录

@WebServlet("/LastTimeServlet")
public class LastTimeServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        // 1.接收cookie数组,取出指定名称cookie对象
        Cookie cookie = CookieUtils.findByName("last_time", request.getCookies());
        // 2.判断
        if (cookie == null) {
            // 不存在
            response.getWriter().write("<h1>欢迎您,首次访问....</h1>");
        } else {
            // 存在
            String value = cookie.getValue();
            response.getWriter().write("<h1>欢迎回来,您上次访问时间:" + value + "</h1>");
        }
        // 3.创建cookie对象,记录本次访问时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日-HH:mm:ss");
        String currentTime = simpleDateFormat.format(new Date());
        cookie = new Cookie("last_time", currentTime);
        // 4.设置cookie存活1年
        cookie.setMaxAge(60 * 60 * 24 * 365);
        // 5.response响应cookie
        response.addCookie(cookie);
    }

}
public class CookieUtils {

    /*
        根据指定名称,查找cookie对象
     */
    public static Cookie findByName(String name, Cookie[] cookies) {
        // 非空判断
        if (cookies != null && cookies.length > 0) {
            // 遍历
            for (Cookie cookie : cookies) {
                // 判断是否有指定名称的cookie
                if (name.equals(cookie.getName())) {
                    return cookie;
                }
            }
        }
        // 没找到返回null
        return null;
    }
}

关于JSP:

  • Java服务器端页面(Java Server Pages)

  • 简单来说:一个特殊的页面,即可定义html标签,又可以定义java代码

  • 作用:简化书写,展示动态页面

  • 本质:是servlet

* 脚本:Jsp通过脚本方式来定义java代码
		<%  java代码 %>  就相当于servlet中service方法...

* 内置对象:在Jsp页面中不需要获取和创建,可以直接使用的对象
		request
		response
		out
			注意:在jsp响应内容,使用out
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>demo</title>
</head>
<body>
<h3>我是标题</h3>



<table border="1" width="200" align="center">
    <tr>
        <td>我是静态资源...</td>
    </tr>
</table>

<%
    System.out.println("我是jsp哈哈哈...");

    request.getServletContext();
    out.write("out输出的hehe");
    // response.getWriter().write("hehe");
%>

</body>
</html>

2.商品浏览记录

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>商品目录</title>
</head>
<style type="text/css">
    a{
        font-size: 20px;
    }

</style>
<body>

<h1>商品列表</h1>

<ul>
    <li><a href="/d18/GoodsInfoServlet?name=小米10">小米10</a></li>
    <li><a href="/d18/GoodsInfoServlet?name=华为mate">华为mate</a></li>
    <li><a href="/d418/GoodsInfoServlet?name=oppo">oppo</a></li>
    <li><a href="/d18/GoodsInfoServlet?name=iphone">iphone</a></li>
    <li><a href="/d418/GoodsInfoServlet?name=锤子">锤子</a></li>
    <li><a href="/d418/GoodsInfoServlet?name=一加">一加</a></li>
</ul>

</body>
</html>
<%@ page import="com.wsl.zy.CookieUtils" %>
<%@ page import="java.util.Arrays" %>
<%@ page import="java.util.List" %><%--
  Created by IntelliJ IDEA.
  User: apple
  Date: 2020/4/18
  Time: 19:05
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>浏览历史</title>
</head>
<body>

<%
    Cookie[] cookies = request.getCookies();
    String value = CookieUtils.findByName("goodsname", cookies).getValue();
    System.out.println("浏览历史:"+value);
    if (value==null){
        response.getWriter().write("<h1>浏览历史为空</h1>");
    }else {
        List<String> strings = Arrays.asList(value.split("-"));
        out.write("浏览历史:<br><ul>");
        for (String string : strings) {
           out.write("<li>"+string+"</li>");
        }
        out.write("</ul>");
    }

%>

</body>
</html>
package com.wsl.zy;

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.util.Arrays;
import java.util.List;

@WebServlet("/GoodsInfoServlet")
public class GoodsInfoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          request.setCharacterEncoding("utf-8");
          response.setContentType("text/html;charset=utf-8");
        String name = request.getParameter("name");
        response.getWriter().write("<h2>您当前浏览的产品为:"+name+"</h2>");
        Cookie cookie = CookieUtils.findByName("goodsname", request.getCookies());
        if (cookie==null){
            cookie = new Cookie("goodsname",name);
        }else{
            String value = cookie.getValue();
            List<String> strings = Arrays.asList(value.split("-"));
            if (!strings.contains(name)){
                value=value+"-"+name;
            }
            cookie = new Cookie("goodsname",value);
        }
        cookie.setMaxAge(60*60*24*365);
        response.addCookie(cookie);
        response.getWriter().write("<br><h2><a href=\"/d18/goods.html\">继续浏览</a></h2>");
        response.getWriter().write("<br><h2><a href=\"/d18/history.jsp\">浏览历史</a></h2>");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

优化:

package cn.itcast.g_goods;

import cn.itcast.f_lasttime.CookieUtils;
import javafx.scene.shape.VLineTo;

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.util.Arrays;
import java.util.LinkedList;
import java.util.List;

@WebServlet("/GoodsInfoServlet")
public class GoodsInfoServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8"); // 请求解码
        response.setContentType("text/html;charset=utf-8"); // 响应编码
        // 1.获取请求参数 name 华为P
        String product = request.getParameter("name");
        // 2.展示当前商品详情
        response.getWriter().write("您当前浏览的商品为:" + product);
        // 3.获取指定名称cookie对象
        Cookie cookie = CookieUtils.findByName("goods_name", request.getCookies());
        // 4.判断是否存在...
        if (cookie == null) {
            // 5.如果不存在,将当前商品设置到cookie对象中...
            cookie = new Cookie("goods_name", product);
        } else {
            // 6.如果有,将浏览记录取出,格式:小米
            String value = cookie.getValue();
            // 将字符串转为数组,转为list集合
            String[] array = value.split("-");
            // List<String> list = Arrays.asList(array);  // 此list集合有坑,只能查询不能添加....
            // list.add(0, product);
            LinkedList<String> list = new LinkedList<>();
            for (String s : array) {
                list.add(s); // 这里应该是按照顺序添加..
            }
            // 7.判断当前商品是否在此cookie中
            if (list.contains(product)) {
                // 如果包含,删除
                list.remove(product);
            }
            // 8.追加list 压入最上方
            list.push(product);
            // 将list转为 字符串  格式:华为-小米-锤子
            value = String.join("-",list);
            // 9.将value,重置到cookie中
            cookie = new Cookie("goods_name", value);

          /*  // 7.判断当前商品是否在此cookie中
            List<String> list = Arrays.asList(value.split("-"));
            // 8.如果不包含,追加
            if (!list.contains(product)) {
                value = value + "-" + product; // 格式:小米10-华为P40
            }
            // 9.将value,重置到cookie中
            cookie = new Cookie("goods_name", value);*/
        }
        // 10.通过response响应到浏览器
        // 设置存活时间 为1年
        cookie.setMaxAge(60 * 60 * 24 * 365);
        response.addCookie(cookie);

        // 11.制作a标签,实现记录浏览商品功能
        response.getWriter().write("<br><a href='/d18cookie/goods.html'>继续浏览</a>");

        // 12.制作a标签,实现查看浏览记录功能
        response.getWriter().write("<br><a href='/d18cookie/history.jsp'>浏览记录</a>");
    }

}

总结:

 

 

资料:

Cookie

Cookie

 

 

 

 

版权声明:本文为u010581811原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010581811/article/details/105603942