javaweb-cookie&session

Cookie:

开始之前,先介绍下会话技术的概念

当用户打开浏览器的时候,访问不同的资源(发送不同的请求),直到用户将浏览器关闭,可以认为这是一次会话.        
作用:
        因为http协议是一个无状态的协议,它记录不论上次访问的内容.用户在访问过程中难免会产生一些数据,
        通过会话技术就可以将起保存起来.
例如:
        用户登录
        验证码
        购物车
        访问记录
        .....

1.概念介绍


    小饼干 小甜点

2.场景模拟

    (面试官三个屋子的场景)

   /******大学生面试进入三个不同的房间,只有在第一个面试官给额头上的密码才可以进入下一轮

    大学生就相当于浏览器,而面试官就相当于服务器,额头上的密码就相当于cookie****/
    cookie是由服务器生成,通过response将cookie写回浏览器(set-cookie),保留在浏览器上,
    下一次访问,浏览器根据一定的规则携带不同的cookie(通过request的头 cookie),我们服务器就可以接受cookie
    创建cookie,键值对的形式

可参见下图:

httpWatch可以看到写到浏览器后

3.常见API


    1.cookie的api:
        new Cookie(String key,String value)
   2. 写回浏览器:
        response.addCookie(Cookie c)
   3. 获取cookie:
        Cookie[] request.getCookies()
    4.cookie的常用方法:
        getName():获取cookie的key(名称)
        getValue:获取指定cookie的值

    5.设置cookie在浏览器端存活时间  以秒为单位
       setMaxAge(int 秒)

扫描二维码关注公众号,回复: 5992798 查看本文章

    6.删除cookie
       setMaxAge(0);

  7.当我们访问的路径中包含此cookie的path,则携带
     默认路径:     setPath(String path):

注意:

     访问serlvet的路径,从"/项目名称"开始,到最后一个"/"结束
           例如:
                    访问的serlvet路径:
                     /day06/a/b/hello
           默认路径为:
                     /day06/a/b(这样才会携带cookie,也就是关掉浏览器重新进去之访问相同的路径内容相同的)

                     /day06/a都不行

4.读取cookie

服务器接收到用户的HTTP请求报文之后,从报文头获取到该用户的Cookie,从里面找到所需要的东西。

5.案例实现+代码

code是和cookie用到的code

code是重要的code

package com.javaweb.RemServlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 记录上次访问时间
 */


public class RemServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


        //0.设置编码(因为是向浏览器写东西)
        response.setContentType("text/html;charset=utf-8");    
        PrintWriter w = response.getWriter();
        
        //1.获取指定名称的cookie自己构造(里面的参数为key-value)
        Cookie c=getCookieByName("lastTime",request.getCookies());
        
        //2.判断cookie是否为空
        if(c == null){
            //cookie为空 提示 第一次访问
            w.print("您是第一次访问!");
        }else{
            //cookie不为空  获取value 展示 上一次访问的时间
            String value = c.getValue();// lastTime=12312324234的形式,要转为long
            long time = Long.parseLong(value);
            Date date = new Date(time);
            w.print("您上次访问时间:"+date.toLocaleString());
        }
        
        //3.将当前访问时间记录
        //3.1创建cookie
        c=new Cookie("lastTime",new Date().getTime()+"");
        
        //持久化cookie一个小时
        c.setMaxAge(3600);


        //设置路径
        c.setPath(request.getContextPath()+"/");
        
        //3.2写回浏览器
        response.addCookie(c);
    }

    /**
     * 通过名称在cookie数组获取指定的cookie
     * @param name cookies名称
     * @param cookies  Cookie数组
     * @return
     * 私有构造注意     

    */
    private Cookie getCookieByName(String name, Cookie[] cookies) {
        if(cookies!=null){
            for (Cookie c : cookies) {                //foreach遍历
                //通过名称获取
                if(name.equals(c.getName())){
                    //返回
                    return c;
                }
            }
        }
        return null;
    }

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

}
 

6.案例实现+步骤分析+代码

6.1需求:

当用户访问一个商品的时候,需要将该商品保留在浏览记录中

6.2步骤分析:

6.2.1


    因为运行的是java代码,jsp可以,html不行,所以要先转换
    1.先将product_list.htm转成jsp
    2.点击一个商品,展示该商品的信息,将该商品id记录到cookie  (GetProductById)
    但是访问之前的商品信息也得记录
    在servlet中该如何做?

6.2.2

  首先是设置编码
        获取之前的浏览记录 例如名称:ids
  判断cookie是否为空
        若为空 将当前商品的id起个名称 ids 放入cookie中  ids=1
        若不为空,获取值 例如:ids=2-1  当前访问的id=1  使用"-"分割商品id
   判断之前记录中有无该商品
         若有:
              将当前的id放入前面  结果 ids=1-2
        若没有:
               继续判断长度是否>=3
               若>=3,移除最后一个,将当前的id放入最前面
               若<3,直接将当前的id放入最前面.
            
                   若 ids=3-2-1 现在访问1 结果 ids=1-3-2
                  若 ids=4-3-2 现在访问1 结果 ids=1-4-3

6.2.3

    3.再次回到product_list.jsp页面,需要将之前访问商品展示在浏览记录中
        获取ids  例如:ids=2-3-1(的形式)
        切割

代码如下

Utils的代码(通过制定名称来获取cookie)

package com.javaweb.utils;

import javax.servlet.http.Cookie;

public class CookUtils {
    public static Cookie getCookieByName(String name, Cookie[] cookies) {
        if(cookies!=null){
            for (Cookie c : cookies) {
                //通过名称获取
                if(name.equals(c.getName())){
                    //返回
                    return c;
                }
            }
        }
        return null;
    }

}

package com.javaweb.servlet;

import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.javaweb.utils.CookUtils;

/**
 * 记录商品浏览器历史
 */
public class GetProductByIDServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //0.设置编码(这里不需要设置编码,获取的是word)
        //0.1获取当前访问的商品id(给之前的每个商品设置id)
        String id=request.getParameter("id");
        
        //1.获取指定的cookie ids
        Cookie c = CookUtils.getCookieByName("ids", request.getCookies());
        
        String ids="";
        //2.判断cookie是否为空
        if(c==null){
            //若cookie为空  需要将当前商品id放入ids中
            ids=id;
        }else{
            //若cookie不为空 继续判断ids中是否已经该id // ids=2-11-21


            //获取值
            ids=c.getValue();
            String[] arr = ids.split("-");
            //将数组转成集合  此list长度不可变
            List<String> asList = Arrays.asList(arr);
            //将aslist放入一个新list中
            LinkedList<String> list = new LinkedList<>(asList);
            if(list.contains(id)){
                //若ids中包含id  将id移除 放到最前面
                list.remove(id);
                list.addFirst(id);
            }else{
                //若ids中不包含id  继续判断长度是否大于2
                if(list.size()>2){
                    //长度>=3 移除最后一个 将当前的放入最前面
                    list.removeLast();
                    list.addFirst(id);
                }else{
                    //长度<3 将当前放入最前面
                    list.addFirst(id);
                }
            }
            
            ids="";
            //将list转成字符串
            for (String s : list) {
                ids+=(s+"-");
            }
            ids=ids.substring(0, ids.length()-1);
        }
        
        //将ids写回去
        c=new  Cookie("ids",ids);
        //设置访问路径
        c.setPath(request.getContextPath()+"/");
        //设置存活时间
        c.setMaxAge(3600);
        
        //写会浏览器
        response.addCookie(c);
        
        
        //3.跳转到指定的商品页面上(product_info这里需要自己去修改)
        response.sendRedirect(request.getContextPath()+"/product_info"+id+".htm");
        
    }

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

}

7.删除cookie代码实现

package com.javaweb.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class CleanHistory extends HttpServlet {
   
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          //创建一个cookie
                Cookie c=new Cookie("ids", "");
                c.setPath(request.getContextPath()+"/");//   
                
           //设置时间
               c.setMaxAge(0);
                
           //写会浏览器
                response.addCookie(c);
                
            //页面跳转(product_list.jsp是需要自己写的)
               response.sendRedirect(request.getContextPath()+"/product_list.jsp");
    }

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

}
 

注意:

 cookie不能跨浏览器
 cookie中不支持中文

 

 

Session

1.session介绍

Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。

如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。

2.获取session


 HttpSession(返回值)  request.getSession()

3.域对象

不错,session也是一个域对象,目前为止,学到现在,已经三个域对象了

ServletContext(全局)

Request(一次请求)

Session(私有)

xxxAttribute
        生命周期:
            创建:第一次调用request.getsession()创建
            销毁:
                1.服务器非正常关闭
                2.session超时
                    默认时间超时:30分钟  web.xml有配置 
                    手动设置超时:setMaxInactiveInterval(int 秒) 了解就可以了
                3.手动干掉session
                    ★session.invalidate()
       session 存放的私有的数据. 一个浏览器一个session

4.案例实现+步骤分析+代码

需求:将商品添加到购物车

步骤分析:


    1.点击添加到购物车的时候,提交到一个servlet add2CartServlet
        需要将商品名称携带过去


    2.add2CartServlet中的操作
        获取商品的名称
       将商品添加到购物车 购物车的结构 Map<String 名称,Integer 购买数量>
            将购物车放入session中就可以了
        
        将商品添加到购物车分析:
            获取购物车
            判断购物车是否为空
                若为空:
                    第一次添加
                    创建一个购物车
                    将当前商品put进去.数量:1
                    将购物车放入session中
                若不为空:继续判断购物车中是否有该商品
                    若有:
                        取出count 将数量+1 
                        将商品再次放入购物车中
                    若没有:
                        将当前商品put进去 数量:1
                    
        提示信息:你的xx已添加到购物车中
    
    
    3.点击购物车连接的时候 cart.jsp
        从session获取购物车
            判断购物车是否为空
                若为空:提示信息
                若不为空:遍历购物车打印即可

代码如下:

package com.javaweb.addCart;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 
 */
public class Add2Cart extends HttpServlet {
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //0.设置编码
        //对提示信息有用,这个设置编码对0步骤没用
        response.setContentType("text/html;charset=utf-8");
        PrintWriter w = response.getWriter();
        
        //1.获取商品的名称(是汉字的话有可能是乱码)
        String name=request.getParameter("name");
        name=new String(name.getBytes("iso8859-1"),"utf-8");
        
        //2.将商品添加到购物车
        //2.1 从session中获取购物车
        Map<String,Integer> map=(Map<String, Integer>) request.getSession().getAttribute("cart");
        
        Integer count=null;
        //2.2判断购物车是否为空
        if(map==null){
            //第一次购物  创建购物车
            map=new HashMap<>();
            
            //将购物车放入session中g
            request.getSession().setAttribute("cart", map);
            
            count=1;
        }else{
            //购物车不为空 继续判断购物车中是否有该商品
            count = map.get(name);
            if(count==null){
                //购物车中没有该商品
                count=1;
            }else{
                //购物车中有该商品
                count++;
            }
        }
        
        //将商品放入购物车中
        map.put(name, count);
        
        //3.提示信息
        w.print("已经将<b>"+name+"</b>添加到购物车中<hr>");
        w.print("<a href='"+request.getContextPath()+"/product_list.jsp'>继续购物</a>&nbsp;&nbsp;&nbsp;&nbsp;");
        w.print("<a href='"+request.getContextPath()+"/cart.jsp'>查看购物车</a>&nbsp;&nbsp;&nbsp;&nbsp;");
    }
    

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

}
 

效果展示

1.product_jsp(首页)

2.点击妹子1

3.点击购物车

5.清空购物车

    思路1:将购物车移除
    思路2:将session干掉
步骤分析:
    在cart.jsp上添加一个超链接 清空购物车
        <a href="/day1101/clearCart">清空购物车</a>
    在clearCart中需要调用session.invalidate()
    重定向到购物车页面

cart.jsp

<%@page import="java.util.Map"%><!--这个也是可以导入的-->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <table border="1" align="center" width="20%">
        <tr>
            <td>商品名称</td>
            <td>商品数量</td>
        </tr>
        <%
            //1.获取购物车
            Map<String,Integer> map=(Map<String,Integer>)session.getAttribute("cart");
            
            //2.判断购物车是否为空
            if(map==null){
                //2.1若为空 : 亲,购物车空空,先去逛逛~~
                out.print("<tr><td colspan='2'>亲,购物车空空,先去逛逛~~</td></tr>");
            }else{
                //2.2若不为空 :遍历购物车
                for(String name:map.keySet()){
                    out.print("<tr>");
                    out.print("<td>");
                    out.print(name);
                    out.print("</td>");
                    out.print("<td>");
                    out.print(map.get(name));
                    out.print("</td>");
                    out.print("</tr>");
                    
                }
            }
        %>
    </table>
    
    <hr>
    <center>
        <a href="/day1101/product_list.jsp">继续购物</a>&nbsp;&nbsp;&nbsp;
        <a href="/day1101/clearCart">清空购物车</a>
    </center>
</body>
</html>

ClearServlet

package com.itheima.web.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *清空浏览记录
 */
public class ClearHistroyServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建一个cookie
        Cookie c=new Cookie("ids", "");
        c.setPath(request.getContextPath()+"/");//   
        
        //设置时间
        c.setMaxAge(0);
        
        //写会浏览器
        response.addCookie(c);
        
        //页面跳转
        response.sendRedirect(request.getContextPath()+"/product_list.jsp");
    }

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

}

6.session底层就是cookie

虽然Session保存在服务器,对客户端是透明的,它的正常运行仍然需要客户端浏览器的支持。这是因为Session 需要使用Cookie作为识别标志。HTTP协议是无状态的,Session不能依据HTTP连接来判断是否为同一客户,因此服务器向客户端浏览器发送一 个名为JSESSIONID的Cookie,它的值为该Session的id(也就是HttpSession.getId()的返回值)。Session 依据该Cookie来识别是否为同一用户。

该Cookie为服务器自动生成的,它的maxAge属性一般为–1,表示仅当前浏览器内有效,并且各浏览器窗口间不共享,关闭浏览器就会失效。

7.Session和cookie的区别

1、存放位置不同

Cookie保存在客户端,Session保存在服务端。

2 、存取方式的不同

 Cookie中只能保管ASCII字符串,假如需求存取Unicode字符或者二进制数据,需求先进行编码。Cookie中也不能直接存取Java对象。若要存储略微复杂的信息,运用Cookie是比拟艰难的。 

而Session中能够存取任何类型的数据,包括而不限于String、Integer、List、Map等。Session中也能够直接保管Java Bean乃至任何Java类,对象等,运用起来十分便当。能够把Session看做是一个Java容器类。 

3、安全性(隐私策略)的不同 

Cookie存储在浏览器中,对客户端是可见的,客户端的一些程序可能会窥探、复制以至修正Cookie中的内容。而Session存储在服务器上,对客户端是透明的,不存在敏感信息泄露的风险。 假如选用Cookie,比较好的方法是,敏感的信息如账号密码等尽量不要写到Cookie中。最好是像Google、Baidu那样将Cookie信息加密,提交到服务器后再进行解密,保证Cookie中的信息只要本人能读得懂。而假如选择Session就省事多了,反正是放在服务器上,Session里任何隐私都能够有效的保护。 

4、有效期上的不同 

只需要设置Cookie的过期时间属性为一个很大很大的数字,Cookie就可以在浏览器保存很长时间。 由于Session依赖于名为JSESSIONID的Cookie,而Cookie JSESSIONID的过期时间默许为–1,只需关闭了浏览器(一次会话结束),该Session就会失效。

5、对服务器造成的压力不同 

Session是保管在服务器端的,每个用户都会产生一个Session。假如并发访问的用户十分多,会产生十分多的Session,耗费大量的内存。而Cookie保管在客户端,不占用服务器资源。假如并发阅读的用户十分多,Cookie是很好的选择。

6、 跨域支持上的不同 

Cookie支持跨域名访问,例如将domain属性设置为“.baidu.com”,则以“.baidu.com”为后缀的一切域名均能够访问该Cookie。跨域名Cookie如今被普遍用在网络中。而Session则不会支持跨域名访问。Session仅在他所在的域名内有效。 
 

可以参考下面博客:cookie和session的区别

http://blog.csdn.net/shuaishenkkk/article/details/8634917

为什么会有cookie呢,大家都知道,http是无状态的协议,客户每次读取web页面时,服务器都打开新的会话,而且服务器也不会自动维护客户的上下文信息,那么要怎么才能实现网上商店中的购物车呢,session就是一种保存上下文信息的机制,它是针对每一个用户的,变量的值保存在服务器端,通过   SessionID来区分不同的客户,session是以cookie或URL重写为基础的,默认使用cookie来实现,系统会创造一个名为   JSESSIONID的输出cookie,我们叫做session  cookie,以区别persistent   cookies,也就是我们通常所说的cookie,注意session   cookie是存储于浏览器内存中的,并不是写到硬盘上的,这也就是我们刚才看到的JSESSIONID,我们通常情是看不到JSESSIONID的,但是当我们把浏览器的cookie禁止后,web服务器会采用URL重写的方式传递Sessionid,我们就可以在地址栏看到sessionid=  KWJHUG6JJM65HS2K6之类的字符串。   
            明白了原理,我们就可以很容易的分辨出persistent   cookies和session   cookie的区别了,网上那些关于两者安全性的讨论也就一目了然了,session   cookie针对某一次会话而言,会话结束session   cookie也就随着消失了,而persistent  cookie只是存在于客户端硬盘上的一段文本(通常是加密的),而且可能会遭到cookie欺骗以及针对cookie的跨站脚本攻击,自然不如   session  cookie安全了。  
            通常session   cookie是不能跨窗口使用的,当你新开了一个浏览器窗口进入相同页面时,系统会赋予你一个新的sessionid,这样我们信息共享的目的就达不到了,此时我们可以先把sessionid保存在persistent  cookie中,然后在新窗口中读出来,就可以得到上一个窗口SessionID了,这样通过session   cookie和persistent  cookie的结合我们就实现了跨窗口的session   tracking(会话跟踪)。  
            在一些web开发的书中,往往只是简单的把Session和cookie作为两种并列的http传送信息的方式,session  cookies位于服务器端,persistent   cookie位于客户端,可是session又是以cookie为基础的,明白的两者之间的联系和区别,我们就不难选择合适的技术来开发web   service了。
 

猜你喜欢

转载自blog.csdn.net/JQ210245253/article/details/89303709