注册用户享全站资源 并成为粉丝 不定时福利发放
合作广告

合作广告

最大优惠

人事面试

人事面试

套路太深

面试过程中,面试官会向应聘者发问,而应聘者的回答将成为面试官考虑是否接受他的重要依据。对应聘者而言,了解这些问题背...

部分企业人事部收到求职者简历后,会预先进行一轮电话面试,来考察求职者的综合素质,因此了解懂得求职面试的基本技巧,将...

1、着装要适当  穿着不一定要名贵,但一定要合体、干净、整洁,而且颜色和图案的搭配一定要协调。鞋子应该是舒服而又引...

一、隐瞒真实个人资料的不诚实者简历是求职的第一步,只有面试官对你的简历有兴趣才会通知你面试。在简历中适当地突出个人...

一、首先你得已经成为公司里“最好”的程序员,或者你已经找不到可作为老师和导师的人关于这一点,很多人都会过度自信,所...

程序人生

程序人生

技术的另一面

女程序员这一物种是稀有物种,茫茫软件工程系,放眼望去满眼尽收“屌丝男士”。零星几只女性就显得尤为珍贵。这里有只女程...

你是否曾经遇到过这样的情况:你已经有了一个好主意,比如开发一个在线商店,制作一个应用等等,但是却只缺一个程序员,能...

在北京四环路西北部的中关村,聚集了这座城市最多的科技企业和最优秀的技术人员,因为腾讯、字节跳动等互联网巨头坐落于此...

作者 : 何俊林 王小波在《黄金时代》里写道,“那一天我二十一岁,在我一生的黄金时代。我有好多奢望。我想爱,想吃,...

在Stack Overflow上有这样的一个贴子《What’s your most controversial p...

程序员段子

程序员段子

乐一乐

皇上太拼了......  被电视剧蒙骗了好多年,三观毁灭!  这是传说中“帅气的王爷”与“美腻的王妃”,像不像屠夫...

足够自信的程序猿自信是通往成功路上的指明灯,自信的程序员更是加班夜里的探照灯,总能让BUG无所遁形。效率高的程序猿...

最近这段时间,小编絮絮叨叨说了很多严肃的东西,今天说点好玩的,轻松一下。娱乐圈有潜规则,小编认为IT圈一样,也有潜...

今天来说说一位女青年的老公以及他们的事儿。如有雷同,纯属巧合。十一年前我和程序猿第一次见面,还是大一军训期间。我甚...

公司高层公司副总A:咱们开个会研究一下这个事情怎么处理。公司副总B:如果老板没有救成功,下任是谁呢?会不会影响公司...

副标题

Web-第十天 Cookie&Session学习【悟空教程】

发表时间:2018-11-07 16:57来源:Java帮帮-微信公众号


Cookie&Session会话技术

今日内容介绍

  • 案例一:记录用户的上次访问时间

  • 案例二:一次性验证码

今日内容学习目标

  • 可以响应给浏览器Cookie信息

  • 可以接收浏览器携带的cookie信息

  • 理解cookie的执行原理

  • 可以对session作用域的数据进行操作:存放、获得、移除

  • 理解session的执行原理

第1章 案例:记录用户的上次访问的时间:

1.1 需求:

当用户访问某些Web应用时,经常会显示出该用户上一次的访问时间。例如,QQ登录成功后,会显示用户上次的登录时间。通过本任务,读者将学会如何使用Cookie技术实现显示用户上次的访问时间的功能。

1.2 相关知识点

1.2.1 会话的概述:

1.2.1.1 什么是会话

在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。Web应用中的会话过程类似于生活中的打电话过程,它指的是一个客户端(浏览器)与Web服务器之间连续发生的一系列请求和响应过程,例如,一个用户在某网站上的整个购物过程就是一个会话。

在打电话过程中,通话双方会有通话内容,同样,在客户端与服务器端交互的过程中,也会产生一些数据。例如,用户甲和乙分别登录了购物网站,甲购买了一个Nokia手机,乙购买了一个Ipad,当这两个用户结账时,Web服务器需要对用户甲和乙的信息分别进行保存。在前面章节讲解的对象中,HttpServletRequest对象和ServletContext对象都可以对数据进行保存,但是这两个对象都不可行,具体原因如下:


1)客户端请求Web服务器时,针对每次HTTP请求,Web服务器都会创建一个HttpServletRequest对象,该对象只能保存本次请求所传递的数据。由于购买和结账是两个不同的请求,因此,在发送结账请求时,之前购买请求中的数据将会丢失。


2)使用ServletContext对象保存数据时,由于同一个Web应用共享的是同一个ServletContext对象,因此,当用户在发送结账请求时,由于无法区分哪些商品是哪个用户所购买的,而会将该购物网站中所有用户购买的商品进行结算,这显然也是不可行的。


3)为了保存会话过程中产生的数据,在Servlet技术中,提供了两个用于保存会话数据的对象,分别是CookieSession。关于CookieSession的相关知识,将在下面的小节进行详细讲解。

  • Cookie  和浏览器缓存有什么区别?

共同点:浏览器缓存可以缓存任意内容(上网浏览的所有内容)、cookie只是服务器需要浏览器缓存数据(浏览器缓存中一部分)


1.2.1.2 什么是Cookie

在现实生活中,当顾客在购物时,商城经常会赠送顾客一张会员卡,卡上记录用户的个人信息(姓名,手机号等)、消费额度和积分额度等。顾客一旦接受了会员卡,以后每次光临该商场时,都可以使用这张会员卡,商场也将根据会员卡上的消费记录计算会员的优惠额度和累加积分。

Web应用中,Cookie的功能类似于这张会员卡,当用户通过浏览器访问Web服务器时,服务器会给客户端发送一些信息,这些信息都保存在Cookie中。这样,当该浏览器再次访问服务器时,都会在请求头中将Cookie发送给服务器,方便服务器对浏览器做出正确的响应。

服务器向客户端发送Cookie时,会在HTTP响应头字段中增加Set-Cookie响应头字段。Set-Cookie头字段中设置的Cookie遵循一定的语法格式,具体示例如下:

Set-Cookie: user=javahelp; Path=/;

在上述示例中,user表示Cookie的名称,javahelp表示Cookie的值,Path表示Cookie的属性。需要注意的是,Cookie必须以键值对的形式存在,其属性可以有多个,但这些属性之间必须用分号;和空格分隔。

了解了Cookie信息的发送方式后,接下来,通过一张图来描述Cookie在浏览器和服务器之间的传输过程,具体如图5-1所示。

图5-1Cookie在浏览器和服务器之间传输的过程

在图5-1中,描述了Cookie在浏览器和服务器之间的传输过程。当用户第一次访问服务器时,服务器会在响应消息中增加Set-Cookie头字段,将用户信息以Cookie的形式发送给浏览器。一旦用户浏览器接受了服务器发送的Cookie信息,就会将它保存在浏览器的缓冲区中,这样,当浏览器后续访问该服务器时,都会在请求消息中将用户信息以Cookie的形式发送给Web服务器,从而使服务器端分辨出当前请求是由哪个用户发出的。


1.2.1.3 Cookie的基本使用

Cookie将用户的信息保存到客户端浏览器的一个技术,当下次访问的时候,浏览器会自动携带Cookie的信息过来到服务器端.

  • Cookie的基本使用:

创建cookie

new Cookie(name,value) javax.servlet.http.Cookie

cookie发送给浏览器:

HttpServletResponse.addCookie(javax.servlet.http.Cookie)

接收浏览器携带的所有cookie

HttpServletRequest.getCookies()

1.3 案例分析

1.3.1 流程分析

1.3.2 步骤分析

第一步.获得从客户端带过来的所有的Cookie:

第二步.从所有的Cookie中查找指定名称的Cookie:

第三步.判断是否是第一次访问:

* 是第一次:显示欢迎

* 不是第一次:显示欢迎 同时显示上次访问时间.

第四步.记录当前的时间,并且利用Cookie将时间回写到浏览器端.  


1.4 代码实现

public class VisitServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

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

/**

* 1.获得从客户端带过来的所有的Cookie:

* 2.从所有的Cookie中查找指定名称的Cookie

* 3.判断是否是第一次访问:

*   * 是第一次:显示欢迎

*   * 不是第一次:显示欢迎 同时显示上次访问时间.

* 4.记录当前的时间,并且利用Cookie将时间回写到浏览器端.

*/

// 获得客户端的所有的Cookie:

Cookie[] cookies = request.getCookies();

// cookies的数组中查找指定名称的Cookie:

Cookie cookie = CookieUtils.findCookie(cookies, "visitTime");

// 判断是否是第一次访问:

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

if(cookie == null){

// 第一次访问

response.getWriter().println("<h1>欢迎来到本网站!</h1>");

}else{

// 不是第一次

long time = Long.parseLong(cookie.getValue());

Date date = new Date(time);

response.getWriter().println("<h1>欢迎来到本网站!您的上次访问时间是:"+date.toLocaleString()+"</h1>");

}

// 记录当前的时间,回写到Cookie.

Cookie c = new Cookie("visitTime",""+System.currentTimeMillis());

response.addCookie(c);

}

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

doGet(request, response);

}

}


1.5 总结:

1.5.1 Cookie的分类

  • 会话级别的Cookie:默认的.关闭了浏览器Cookie就销毁了.

  • 持久级别的Cookie:需要设置有效时长的.关闭浏览器也不会销毁的Cookie.

    • setMaxAge(int expiry);  以秒为单位的时间,超过了该时间后Cookie会自动销毁. setMaxAge(0),手动删除持久性的Cookie。(前提:path和name必须一致)

    • setPath(String uri); 设置Cookie的有效路径.

  • 例如:

       1)cookie.setPath("/day16/demo");

       表示day16 项目下,【demo目录】下所有的servlet,

        都可以访问当前cookie。但“/day16”或“/day16/aaa”

        将不能访问。

       2)cookie.setPath("/day16");

       表示【day16 项目】下的所有servlet都可以访问当前cookie

       3)cookie.setPath("/");

       表示【tomcat下】的所有的web项目,都可以访问当前cookie

  • cookie唯一表示:

    • 唯一标示:domain + path + name (类似Java中 包 + 类名)

      • domain 域名,不同的网站使用的是不同的域名,cookie就不同。

      • path 路径,通过cookie.setPath(…)设置的内容。

      • name cookie名称,通过 new Cookie(name , …) 确定的内容。

    • 例如:以下表示的是两个cookie,可以同时存在。

      • /web/a/b/cookieName

      • /web/a/cookieName

      • 如果路径和名称一样,两次addCookie(),后者将覆盖前者。

1.5.2 CookieAPI:

方法名

描述

getName()

获得cookie名称。

getValue()

获得cookie的值。

setMaxAge(int expiry)

设置cookie的有效时间。

  • 如果没有设置,cookie只缓存浏览器缓存中,浏览器关闭,cookie删除。

  • 如果设置有效时间,在时间范围内,cookie被写入到浏览器端,关闭浏览器下次访问仍可获得,直到过期。

setPath(java.lang.String uri)

设置cookie允许被访问的路径。设置的路径,以及子路径都被允许访问。

  • 例如:setPath("/web/a/b");

http://localhost:8080/web/a/b/oneServlet,可访问(当前路径)

http://localhost:8080/web/a/b/c/oneServlet,可访问(子路径)

http://localhost:8080/web/a/c/oneServlet,不允许访问(无关路径)

  • 常见设置:setPath(“/”) ,当前tomcat下的所有的web项目都可以访问

第2章 案例:一次性验证码的校验

2.1 需求:

  • 验证码的作用:

    • 防止恶意提交表单

2.2 相关知识点:

2.2.1 Session的概述

2.2.1.1 什么是Session

当人们去医院就诊时,就诊病人需要办理医院的就诊卡,该卡上只有卡号,而没有其它信息。但病人每次去该医院就诊时,只要出示就诊卡,医务人员便可根据卡号查询到病人的就诊信息。

Session技术就好比医院发放给病人的就医卡和医院为每个病人保留病例档案的过程。当浏览器访问Web服务器时,Servlet容器就会创建一个Session对象和ID属性,其中,Session对象就相当于病历档案,ID就相当于就诊卡号。当客户端后续访问服务器时,只要将标识号传递给服务器,服务器就能判断出该请求是哪个客户端发送的,从而选择与之对应的Session对象为其服务。

需要注意的是,由于客户端需要接收、记录和回送Session对象的ID,因此,通常情况下,Session是借助Cookie技术来传递ID属性的。

为了使读者更好的理解Session,接下来,以网站购物为例,通过一张图来描述Session保存用户信息的原理,具体如图5-5所示。

图1-1 Session保存用户信息的过程

在图5-5中,用户甲和乙都调用buyServlet将商品添加到购物车,调用payServlet进行商品结算。由于甲和乙购买商品的过程类似,在此,以用户甲为例进行详细说明。当用户甲访问购物网站时,服务器为甲创建了一个Session对象(相当于购物车)。

当甲将Nokia手机添加到购物车时,Nokia手机的信息便存放到了Session对象中。

同时,服务器将Session对象的ID属性以Cookie (Set-Cookie: JSESSIONID=111)的形式返回给甲的浏览器。当甲完成购物进行结账时,需要向服务器发送结账请求,这时,浏览器自动在请求消息头中将Cookie (Cookie: JSESSIONID=111)信息回送给服务器,服务器根据ID属性找到为用户甲所创建的Session对象,并将Session对象中所存放的Nokia手机信息取出进行结算。

2.2.1.2 为什么要使用会话

  • 使用servlet生成验证码时,我们需要在服务器记录一份生成的随机字符,当用户提交填写的数据时,将用户输入的数据和服务器缓存的数据进行比对。

  • 将随机字符串保存在ServletContext中或者request中是否可以?

    • 将数据存放到ServletContext,多个用户共享一个验证码。

    • 将数据存放到request作用域,多次请求不能共享数据。

  • 我们发现将数据保存到ServletContext和request中是存在问题的,那么就需要使用会话技术保存用户的私有信息.

2.2.1.3 CookieSession的选取?

* Cookie是有大小和个数的限制的.Session存到服务器端的技术,没有大小和个数的限制.

* Cookie相对于Session来讲不安全.


2.2.1.4 如何使用Session:

Session是与每个请求消息紧密相关的,为此,HttpServletRequest定义了用于获取Session对象的getSession()方法,该方法有两种重载形式,具体如下。

public HttpSession getSession(boolean create)

public HttpSession getSession()

上面重载的两个方法都用于返回与当前请求相关的HttpSession对象。不同的是,第一个getSession()方法根据传递的参数来判断是否创建新的HttpSession对象,如果参数为true,则在相关的HttpSession对象不存在时创建并返回新的HttpSession对象,否则不创建新的HttpSession对象,而是返回null。第二个getSession()方法则相当于第一个方法参数为true时的情况,在相关的HttpSession对象不存在时总是创建新的HttpSession对象。

要想使用HttpSession对象管理会话数据,不仅需要获取到HttpSession对象,还需要了解HttpSession对象的相关方法。HttpSession接口中定义的操作会话数据的常用方法如表5-2所示。

表5-1 HttpSession接口中的常用方法

方法声明

功能描述

String getId()

用于返回与当前HttpSession对象关联的会话标识号

long getCreationTime()

返回Session创建的时间,这个时间是创建Session的时间与19701100:00:00之间时间差的毫秒表示形式

long getLastAccessedTime()

返回客户端最后一次发送与Session相关请求的时间,这个时间是发送请求的时间与19701100:00:00之间时间差的毫秒表示形式

void  setMaxInactiveInterval(int interval)

用于设置当前HttpSession对象可空闲的以秒为单位的最长时间,也就是修改当前会话的默认超时间隔

boolean isNew()

判断当前HttpSession对象是否是新创建的

void invalidate()

用于强制使Session对象无效

ServletContext getServletContext()

用于返回当前HttpSession对象所属于的WEB应用程序对象,即代表当前WEB应用程序的ServletContext对象

void setAttribite(String name,Object value)

用于将一个对象与一个名称关联后存储到当前的HttpSession对象中

String getAttribute()

用于从当前HttpSession对象中返回指定名称的属性对象

void removeAttribute(String name)

用于从当前HttpSession对象中删除指定名称的属性

5-2列举了HttpSession接口中的常用方法,这些方法都是用来操作HttpSession对象的。

2.3 案例分析

2.4 代码实现:

  • 将随机生成的字母或数字存入到Session中:

  • 验证码的校验:

public class LoginServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

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

// 进行验证码校验:

String code1 = request.getParameter("checkcode");

String code2 = (String)request.getSession().getAttribute("checkcode");

request.getSession().removeAttribute("checkcode");

if(!code1.equalsIgnoreCase(code2)){

// 验证码有错误:

request.setAttribute("msg", "验证码输入错误!");

request.getRequestDispatcher("/demo4-checkcode/login.jsp").forward(request, response);

return;

}

// 登录代码:

}

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

doGet(request, response);

}

}


2.5 作用域总结:

2.5.1 Servlet 三个作用域总结:

  • ServletContext:针对一个WEB应用。一个WEB应用只有一个ServletContext对象,使用该对象保存的数据在整个WEB应用中都有效。

    • 创建:服务器启动的时候.

    • 销毁:服务器关闭的时候或者项目移除的时候.

  • HttpSession:针对一次会话。使用该对象保存数据,一次会话(多次请求)内数据有效。

    • 创建:服务器第一次调用getSession()的时候.服务器创建session的对象.

    • 销毁:

   1. 非正常关闭服务器(正常关闭:Session被序列化)

   2. Session过期了,默认时间是30分钟.

   3. 手动调用session的invalidate的方法.

  • HttpServletRequest :针对一次请求。使用该对象保存数据,一次请求(一个页面,如果是请求转发多个页面)内数据有效.

    • 创建:客户端向服务器发送一次请求

    • 销毁:服务器为这次请求作出响应之后,销毁request.

  • 三个作用域对象操作的API相同

    • 存放数据:setAttribute(name,value)

    • 获得数据:getAttribute(name)

    • 删除数据:removeAttribute(name)


第3章 案例:记录用户的商品的浏览记录:

3.1 需求:


3.2 案例分析

3.2.1 流程分析


3.2.2 步骤分析:

/**

* 1.接收参数ID

* 2.获得从浏览器带过来的Cookie的信息.

* 3.判断是否是第一次浏览商品:

*     * 如果是第一次:

*         * 创建一个Cookie将商品ID回写到浏览器.

*     * 如果不是第一次:

*         * 获得Cookie中的值(所有浏览过商品的ID)  1-3

*         * 判断现在浏览的商品是否已经在浏览器记录中.

*             * 已经存在:1-3 点击3

*                 * 删除当前元素,将该元素添加到最前面.

*             * 不存在: 1-3 点击 4  1-3-2 点击4

*                 * 判断长度:

*                     * 没有超出界限:直接添加到最前面.

*                     * 如果到达界限:删除最后面一个元素,将点击的这个添加到最前面.

*         * 创建一个Cookie将商品的ID们回写到浏览器.

* 4.页面跳转到商品详情的页面.

*/


3.3 代码实现:

public class HistoryServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

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

/**

* 1.接收参数ID

* 2.获得从浏览器带过来的Cookie的信息.

* 3.判断是否是第一次浏览商品:

*     * 如果是第一次:

*         * 创建一个Cookie将商品ID回写到浏览器.

*     * 如果不是第一次:

*         * 获得Cookie中的值(所有浏览过商品的ID)  1-3

*         * 判断现在浏览的商品是否已经在浏览器记录中.

*             * 已经存在:1-3 点击3

*                 * 删除当前元素,将该元素添加到最前面.

*             * 不存在: 1-3 点击 4  1-3-2 点击4

*                 * 判断长度:

*                     * 没有超出界限:直接添加到最前面.

*                     * 如果到达界限:删除最后面一个元素,将点击的这个添加到最前面.

*         * 创建一个Cookie将商品的ID们回写到浏览器.

* 4.页面跳转到商品详情的页面.

*/

// 1.接收参数ID:

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

// 2.获得从客户端带过来的所有的Cookie:

Cookie[] cookies = request.getCookies();

// 3.查找指定名称Cookie,

Cookie cookie = CookieUtils.findCookie(cookies, "history");

// 4.判断是否是第一次浏览商品:

if(cookie == null){

// 第一次浏览商品:

Cookie c = new Cookie("history",id);

// 设置有效路径:

c.setPath("/day11");

// 设置有效时长:

c.setMaxAge(7*24*60*60);

// Cookie回写到浏览器:

response.addCookie(c);

}else{

// 不是第一次访问: 1-3

// 判断浏览的商品是否已经在浏览记录中:

String value = cookie.getValue(); // 1-3

// 切分:

String[] ids = value.split("-"); // [1,3]

// 创建LinkedList:进行增删改的时候比较方便.

LinkedList<String> list = new LinkedList<String>(Arrays.asList(ids));

// 判断是否商品已经在浏览记录中:

if(list.contains(id)){

// 说明商品已经在浏览记录中. 1-3 点击 3 --3-1

list.remove(id);

list.addFirst(id);

}else{

// 商品没有在浏览记录中  

if(list.size()>=3){

// 超过长度   1-3-2 点击 4 --> 4-1-3

list.removeLast();

list.addFirst(id);

}else{

// 没有超过    1-3 点击 4--4-1-3

list.addFirst(id);

}

}

// 使用-连接集合中的数据:

StringBuffer sb = new StringBuffer();

for (String string : list) {

sb.append(string).append("-");

}

String history = sb.toString().substring(0, sb.toString().length()-1);

Cookie c = new Cookie("history",history);

// 设置有效路径:

c.setPath("/day11");

// 设置有效时长:

c.setMaxAge(7*24*60*60);

// Cookie回写到浏览器:

response.addCookie(c);

}

// 页面的跳转:

response.sendRedirect(request.getContextPath()+"/demo2-history/product_info"+id+".htm");

}

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

doGet(request, response);

}

}


3.4 总结:

3.4.1 清空浏览记录:

public class ClearHistoryServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

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

// 删除持久性的Cookie:

Cookie cookie = new Cookie("history","");

cookie.setPath("/day11");

cookie.setMaxAge(0);

response.addCookie(cookie);

response.sendRedirect(request.getContextPath()+"/demo2-history/product_list.jsp");

}

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

doGet(request, response);

}

}

3.4.2 扩展:另一种实现流程

3.4.3 扩展:显示多个浏览历史记录

第4章 总结



Java帮帮公众号生态

Java帮帮公众号生态

总有一款适合你

Java帮帮-微信公众号

Java帮帮-微信公众号

将分享做到极致

Python帮帮-公众号

Python帮帮-公众号

人工智能,爬虫,学习教程

大数据驿站-微信公众号

大数据驿站-微信公众号

一起在数据中成长

九点编程-公众号

九点编程-公众号

深夜九点学编程

程序员服务区-公众号

程序员服务区-公众号

吃喝玩乐,听学吐画

Java帮帮学习群生态

Java帮帮学习群生态

总有一款能帮到你

Java学习群

Java学习群

与大牛一起交流

大数据学习群

大数据学习群

在数据中成长

九点编程学习群

九点编程学习群

深夜九点学编程

python学习群

python学习群

人工智能,爬虫

测试学习群

测试学习群

感受测试的魅力

Java帮帮生态承诺

Java帮帮生态承诺

一直坚守,不负重望

初心
勤俭
诚信
正义
分享
合作品牌 非盈利生态-优质内容分享传播者
关于我们
友链申请
友链交换:加帮主QQ2524138991 留言即可 24小时内答复  
全站内容非商业用途,内容来源于网友,并遵循 CC BY-NC 4.0 许可,如有异议请联系客服。
会员登录
获取验证码
登录
登录
我的资料
留言
回到顶部