保存会话数据的两种技术之Cookie

 

两个会话技术

会话概念:打开浏览器,可以访问WEB资源,多次访问WEB资源,关闭浏览器,整个过程一次会话。
* 购买商品
用户点击超链接通过一个servlet购买了一个商品,程序应该保存用户购买的商品,
以便于用户点结帐servlet时,结帐servlet可以得到用户商品为用户结帐。
* 把商品存入到ServletContext获取request域中呢?

cookie和seesion的原理

保存会话数据的两种技术:

Cookie

Cookie 客户端技术,程序把每个用户的数据以 cookie 的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的 web 资源时,就会带着各自的数据去。这样, web 资源处理的就是用户各自的数据了。

Session

Session 服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其 独享的 session 对象 ,由于 session 为用户浏览器独享,所以用户在访问服务器的 web 资源时,可以把各自的数据放在各自的 session 中,当用户再去访问服务器中的其它 web 资源时,其它 web 资源再从用户各自的 session 中取出数据为用户服务。
 

Cookie的响应头set-cookie:product=1,浏览器的内存会保存cookie的内容,再发送请求时,会带着头cookie:product=1去访问。之后累加。

Session在服务器端开辟一块空间,分配一个唯一的标识,每次请求响应都带着唯一的标识,最终结算通过标识找到空间。

cookie

* 显示上次的访问时间(案例)
* 第一次访问,输出欢迎,在服务器端,记录当前的时间,把当前的时间通过cookie回写到浏览器。
* 第二次访问,会带着上次的时间,获取时间,可以把时间显示到页面上,记录当前的时间,再把回写浏览器。
输出上次的访问时间。

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

2 Cookie规范

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

不同的浏览器之间不能共享Cookie!!!

3 Cookie的作用

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

就好比你去医院看病,第一次去需要买卡片,然后你去任何科室都需要你出示卡片。只要你出示卡片,医生就会知道你去过哪些科室,看了哪些病!卡片上只有一个ID,它就是Cooke,而你本人就是客户端,而医生就是服务器了。 

4 Cookie的属性

Cookie最重要的4个属性:

  名字(name);

  值(value);

  路径(path);

  域(domain)。

Cookie的API

* cookie的构造方式 Cookie(String name, String value) 
* String getName()  获取cookie的名称
* String getValue() 获取cookie的值

* void setMaxAge(int expiry)   :设置有效时间
* 失效cookie setMaxAge(0); 前提条件:设置有效路径(和之前设置过相同)

* void setPath(String uri)   :设置有效路径
* 默认的有效路径()
* 配置 /last 默认路径 /day11
* 配置 /servlet/last 默认路径 /day11/servlet

* void setDomain(String pattern)   :设置有效域名
* www.sina.com.cn
* sports.sina.com.cn
* xxx.sina.com.cn
* 设置有效域名 setDomain(".sian.com.cn");

* 会话级别的cookie:默认保存到浏览器的内存中。
* 持久的cookie:把cookie保存到磁盘上。通过setMaxAge(int a)进行设置。

* 显示用户上次访问过的商品信息(需求)
 *  1.获取请求参数
 *  2.获取cookie数组,通过指定的名称(自己指定)查找cookie
 *  3.如果cookie==null,第一次访问
 *  * 如果是第一次访问,创建cookie,回写浏览器
 *  4.如果cookie!=null,不是第一次访问
 *  * 如果不是第一次访问,说明我的cookie中已经存在id
 *  * 判断,当前的id是否已经存在cookie的中value
 *  * 如果存在,不用操作
 *  * 如果不存在,在后面追加(product=1,2)
 *  5.重定向到商品页面

5 保存Cookie到客户端

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

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

public class AServlet extends HttpServlet {

    public void doGet(HttpServletRequest request,

            HttpServletResponse response)

            throws ServletException, IOException {

        Cookie c = new Cookie("id""itcast")[涛1] ;

        response.addCookie(c)[涛2] ;

    }

}


创建名为id,值为itcast的Cookie对象。

把Cookie对象添加到response对象中去。

保存会话数据的两种技术之Cookie_第1张图片

 

6 Cookie的生命

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

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

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

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

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

7 服务器端读取Cookie

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

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

HttpServletRequest:Cookie[] getCookies()

注意,它返回的是Cookie数组,而不是一个Cookie对象。如果请求中没有Cookie,那么该方法返回null。

        Cookie[] cs = request.getCookies()[涛1] ;

        if (cs != null[涛2] ) {

            for (Cookie c : cs) [涛3] {

                String str = c.getName() + ": " + c.getValue()[涛4]  + "
"
;

                response.getWriter().print(str);

            }

        }


获取当前请求中所有Cookie对象

如果返回的数组不是null

循环遍历所有Cookie对象

获取当前Cookie对象的名字与值

7 Cookie的路径

Cookie路径会影响请求中是否包含Cookie,次要。

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

也就是说,就算你不设置Cookie的path,Cookie也是有路径的。这个路径就是请求的路径。例如在请求http://localhost/day07_03/AServlet时,服务器响应了一个Cookie,那么这个Cookie的默认路径就是/day07_03/。

例如请求的路径是http://localhost/day07_03/servlet/BServlet时,服务器响应了一个Cookie,那么这个Cookie的默认路径就是/day07_03/servlet/。

到现在我们还没说过Cookie的path有什么用,现在我们来聊聊path的作用。首先声明一点,path不是指Cookie在客户端存放的路径!!!不同的浏览器存放Cookie的路径是不同的!!!你不能通过Cookie的path来指定Cookie文件的存放路径!!!

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

  c1:name=id; value=itcast;path=/day07_03/;

  c2:name=name;value=qdmmy6; path=/day07_03/servlet/。

当访问http://localhost/day07_03/*时,请求头中会包含c1,而不会包含c2。

当访问http://localhost/day07_03/servlet/*时,请求头中会包含c1和c2。

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

保存会话数据的两种技术之Cookie_第2张图片

 

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

  c2.setPath(“/day07_03/”):硬编码

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

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

8 Cookie的域

Cookiedomain属性可以让网站中二级域共享Cookie,次要!

百度你是了解的对吧!

http://www.baidu.com

http://zhidao.baidu.com

http://news.baidu.com

http://tieba.baidu.com

现在我希望在这些主机之间共享Cookie(例如在www.baidu.com中响应的cookie,可以在news.baidu.com请求中包含)。很明显,现在不是路径的问题了,而是主机的问题,即域名的问题。处理这一问题其实很简单,只需要下面两步:

  设置Cookiepath为“/”:c.setPath(“/”);

设置Cookiedomain为“.baidu.com”:c.setDomain(“.baidu.com”)。 

domain为“.baidu.com”时,无论前缀是什么,都会共享Cookie的。但是现在我们需要设置两个虚拟主机:www.baidu.com和news.baidu.com。 

第一步:设置windowsDNS路径解析

找到C:\WINDOWS\system32\drivers\etc\hosts文件,添加如下内容

127.0.0.1       localhost

127.0.0.1       www.baidu.com

127.0.0.1       news.baidu.com

第二步:设置Tomcat虚拟主机

找到server.xml文件,添加元素,内容如下:

     

            unpackWARs="true" autoDeploy="true"

            xmlValidation="false" xmlNamespaceAware="false"/>

     

            unpackWARs="true" autoDeploy="true"

            xmlValidation="false" xmlNamespaceAware="false"/>

第三步:创建A项目,创建AServlet,设置Cookie。

        Cookie c = new Cookie("id""baidu");

        c.setPath("/");

        c.setDomain(".baidu.com");

        c.setMaxAge(60*60);

        response.addCookie(c);

        response.getWriter().print("OK");

把A项目的WebRoot目录复制到F:\webapps\www目录下,并把WebRoot目录的名字修改为ROOT。

第四步:创建B项目,创建BServlet,获取Cookie,并打印出来。

        Cookie[] cs = request.getCookies();

        if(cs != null) {

            for(Cookie c : cs) {

                String s = c.getName() + ": " + c.getValue() + "
"
;

                response.getWriter().print(s);

            }

        }

把B项目的WebRoot目录复制到F:\webapps\news目录下,并把WebRoot目录的名字修改为ROOT。

第五步:访问www.baidu.com\AServlet,然后再访问news.baidu.com\BServlet。

9 Cookie中保存中文

  Cookie中保存中文,次要。

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

向客户端响应中添加Cookie

        String name = URLEncoder.encode("姓名""UTF-8");

        String value = URLEncoder.encode("张三""UTF-8");

        Cookie c = new Cookie(name, value);

        c.setMaxAge(3600);

        response.addCookie(c);

从客户端请求中获取Cookie

        response.setContentType("text/html;charset=utf-8");

        Cookie[] cs = request.getCookies();

        if(cs != null) {

            for(Cookie c : cs) {

                String name = URLDecoder.decode(c.getName(), "UTF-8");

                String value = URLDecoder.decode(c.getValue(), "UTF-8");

                String s = name + ": " + value + "
"
;

                response.getWriter().print(s);

            }

        }

10 Cookie练习

使用Cookie来验证用户是否已经登录。

  index.jsp:登录页面,提供登录表单提交到LoginServlet;

  LoginServlet:验证登录,获取用户名,保存到Cookie中,转发到AServlet;

  AServlet:受保护Servlet,查看Cookie是否存在;

  BServlet:受保护Servlet,查看Cookie是否存在。

 index.jsp

    <h1>XXX系统h1>

    <hr/>

    <h3>请求输入你的姓名h3>

    <form action="/login/LoginServlet" method="get">

    姓名:<input type="text" name="username" /><br/>

    <input type="submit" value="提交"/>

    form>

LoginServlet.java

        String username = request.getParameter("username");

        response.setContentType("text/html;charset=utf-8");

        PrintWriter out = response.getWriter();

        if(username == null || "".equals(username)) {

            out.print("你瞎了!让你输入用户名,你没看见么?
"
);

            out.print("点击这里返回登录页面!");

            return;

        }

        CookieUtils.saveCookie(response, new Cookie("username", username));

        response.sendRedirect("/login/AServlet");

 AServlet.java

        response.setContentType("text/html;charset=utf-8");

        PrintWriter out = response.getWriter();

        out.print("

AServlet

");

        out.print("


");

        String name = CookieUtils.getCookie(request, "username");

        if(name == null) {

            out.print("您还没有登录,点击这里返回登录页面!");

            return;

        }

        out.print("您好:" + name + ", 欢迎登录本系统
"
);

        out.print("AServlet
"
);

        out.print("BServlet
"
);

 BServlet.java

        response.setContentType("text/html;charset=utf-8");

        PrintWriter out = response.getWriter();

        out.print("

BServlet

");

        out.print("


");

        String name = CookieUtils.getCookie(request, "username");

        if(name == null) {

            out.print("您还没有登录,点击这里返回登录页面!");

            return;

        }

        out.print("您好:" + name + ", 欢迎登录本系统
"
);

        out.print("AServlet
"
);

        out.print("BServlet
"
);

 CookieUtils

publicclass CookieUtils {

    publicstatic String getCookie(HttpServletRequest request, String name) {

        Cookie[] cs = request.getCookies();

        if(cs == null) {

            returnnull;

        }

        for(Cookie c : cs) {

            try {

                String n = URLDecoder.decode(c.getName(), "utf-8");

                if(n.equals(name)) {

                    return URLDecoder.decode(c.getValue(), "utf-8");

                }

            } catch (UnsupportedEncodingException e) {

                thrownew RuntimeException(e);

            }

        }

        return"";

    }  

    publicstaticvoid saveCookie(HttpServletResponse response, Cookie c) {

        try {

            String name = URLEncoder.encode(c.getName(), "utf-8");

            String value = URLEncoder.encode(c.getValue(), "utf-8");

            Cookie cookie = new Cookie(name, value);

            cookie.setPath(c.getPath());

            response.addCookie(cookie);

        } catch (UnsupportedEncodingException e) {

            thrownew RuntimeException(e);

        }

    }

}

javax.servlet.http.Cookie类用于创建一个Cookieresponse接口也中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。 同样,request接口中也定义了一个getCookies方法,它用于获取客户端提交的CookieCookie类的方法:

public Cookie(String name,String value)
setValue getValue 方法
setMaxAge getMaxAge 方法
setPath getPath 方法
setDomain getDomain 方法
getName 方法

Cookie细节

一个 Cookie 只能标识一种信息,它至少含有一个标识该信息的名称( NAME )和设置值( VALUE )。
一个 WEB 站点可以给一个 WEB 浏览器发送多个 Cookie ,一个 WEB 浏览器也可以存储多个 WEB 站点提供的 Cookie
浏览器一般只允许存放 300 Cookie 每个站点最多存放 20 Cookie 每个 Cookie 的大小限制为 4KB
如果创建了一个 cookie ,并将他发送到浏览器,默认情况下它是一个 会话级别的 cookie (即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该 cookie 存储在磁盘上 ,则需要 使用 maxAge ,并给出一个以秒为单位的时间。
删除持久 cookie ,可以将 cookie 最大时效设为 0 注意,删除 cookie 时, path 必须一致,否则不会删除

Cookie应用

显示用户上次浏览过的商品
编写商品信息列表,给每个商品起唯一的 id 值,通过 id 传值。
判断是否是第一次访问
如果是第一次访问,创建 cookie ,记录商品 id ,回写到浏览器
如果不是第一次访问,获取 cookie 中的商品信息,但是需要判断 cookie 中是否已经包含该商品,如果包含就不用处理,如果不包含,可以取出商品的 id ,累加操作。( 可以编写一个判断是否包含的方法
重定向到商品列表页面,把商品循环到列表页面
清除浏览记录

你可能感兴趣的:(保存会话数据的两种技术之Cookie)