一、会话技术简介
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。Web应用中的会话过程类似于生活中的打电话过程,它指的是一个客户端(浏览器)与Web服务器之间连续发生的一系列请求和响应的过程,例如,一个用户在某网站上的整个购物过程就是一个会话。
在打电话过程中,通话双方会有通话记录,同样,在客户端与服务器端交互的过程中,也会产生一些数据。例如,用户甲和乙分别登录了购物网站,甲购买了一个Nokia手机,乙购买了一个Ipad,当这两个用户结账时,Web服务器需要对用户甲和乙的信息分别进行保存。HttpServletRequest对象和ServletContext对象都可以对数据进行保存,但是这两个对象都不可行,具体原因如下:
(1)客户端请求Web服务器时,针对每次HTTP请求,Web服务器都会创建一个HttpServletRequest对象,该对象只能保存本次请求所传递的数据。由于购买和结账是两个不同的请求,因此,在发送结账请求时,之前购买请求中的数据将会丢失。
(2)使用ServletContext对象保存数据时,由于同一个Web应用共享的是同一个ServletContext对象,因此,当用户在发送结账请求时,由于无法区分哪些商品是哪个用户所购买的,而会将该购物网站中所有用户购买的商品进行结算,这显然也是不可行的。
为了保存会话过程中产生的数据,在Servlet技术中,提供了两个用于保存会话数据的对象,分别是Cookie和Session。
二、Cookie技术
2.1 什么是cookie
Cookie翻译成中文是小甜点,小饼干的意思。在HTTP中它表示服务器送给客户端浏览器的小甜点。其实Cookie就是一个键和一个值构成的,随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器。
Cookie是由服务器创建,然后通过响应发送给客户端的一个键值对。客户端会保存Cookie,并会标注出Cookie的来源(哪个服务器的Cookie)。当客户端向服务器发出请求时会把所有这个服务器Cookie包含在请求中发送给服务器,这样服务器就可以识别客户端了!
2.2 Cookie与HTTP头
Cookie是通过HTTP请求和响应头在客户端和服务器端传递的。
- 请求头,客户端发送给服务器端;
格式:Cookie: a=A; b=B; c=C。即多个Cookie用分号离开;
- 响应头,服务器端发送给客户端;
一个Cookie对象一个Set-Cookie:
Set-Cookie: a=A
Set-Cookie: b=B
Set-Cookie: c=C
注意:如果服务器端发送重复的Cookie那么会覆盖原有的Cookie。例如客户端的第一个请求服务器端发送的Cookie是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie: a=AA,那么客户端只留下一个Cookie,即:a=AA。
2.3 Cookie的生命
Cookie不只是有name和value,Cookie还是生命。所谓生命就是Cookie在客户端的有效时间,可以通过setMaxAge(int)来设置Cookie的有效时间。
- cookie.setMaxAge(-1):cookie的maxAge属性的默认值就是-1,表示只在浏览器内存中存活。一旦关闭浏览器窗口,那么cookie就会消失。
- cookie.setMaxAge(60*60):表示cookie对象可存活1小时。当生命大于0时,浏览器会把Cookie保存到硬盘上,就算关闭浏览器,就算重启客户端电脑,cookie也会存活1小时,过期浏览器自动删除该cookie信息
- cookie.setMaxAge(0):cookie生命等于0是一个特殊的值,它表示cookie被作废!也就是说,如果原来浏览器已经保存了这个Cookie,那么可以通过Cookie的setMaxAge(0)来删除这个Cookie。无论是在浏览器内存中,还是在客户端硬盘上都会删除这个Cookie。
2.4 Cookie的基本使用
【服务器端向客户端发送一个Cookie】
1)创建Cookie:Cookie cookie = new Cookie(String cookieName,String cookieValue);
示例:Cookie cookie = new Cookie("username","zhangsan");那么该cookie会以响应头的形式发送给客户端:
注意:Cookie中不能存储中文
2)设置Cookie在客户端的持久化时间:cookie.setMaxAge(int seconds); ---时间秒
注意:如果不设置持久化时间,cookie会存储在浏览器的内存中,浏览器关闭 cookie信息销毁(会话级别的cookie),如果设置持久化时间,cookie信息会被持久化到浏览器的磁盘文件里。
3)设置Cookie的携带路径:cookie.setPath(String path);
注意:如果不设置携带路径,那么该cookie信息会在访问产生该cookie的 web资源所在的路径都携带cookie信息
示例:cookie.setPath("/WEB16");——代表访问WEB16应用中的任何资源都携带cookie
cookie.setPath("/WEB16/cookieServlet");——代表访问WEB16中的cookieServlet时才携带cookie信息
4)向客户端发送cookie:response.addCookie(Cookie cookie);
5)删除客户端的cookie:如果想删除客户端已经存储的cookie信息,使用同名同路径的持久化时间为0的cookie进行覆盖即可
【服务器端接收客户端携带的Cookie】
cookie信息是以请求头的方式发送到服务器端的:
1)通过request获得所有的Cookie:Cookie[] cookies = request.getCookies();
2)遍历Cookie数组,通过Cookie的名称获得我们想要的Cookie
for(Cookie cookie : cookies){ if(cookie.getName().equal(cookieName)){ String cookieValue = cookie.getValue(); } }
2.5 案例:显示上次访问时间
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); // 创建Cookie对象,名为lasttime,值为当前时间创建Cookie对象,名为lasttime,值为当前时间 Cookie cookie = new Cookie("lasttime", new Date().toString()); // 设置Cookie在客户端的有效时间为1小时 cookie.setMaxAge(60 * 60); // 添加Cookie到response中 response.addCookie(cookie); // 获取请求中的Cookie Cookie[] cookies = request.getCookies(); String s = "您是首次访问本网站"; // 如果请求中存在Cookie if (cookies != null) { // 循环遍历请求中的Cookie for (Cookie c : cookies) { // 如果Cookie名为lasttime if (c.getName().equals("lasttime")) { // 设置s s = "您上次访问的时间是:" + c.getValue(); } } } // 打印s到响应端 response.getWriter().print(s); }
三、Session技术
3.1 什么是Session
当人们去医院就诊时,就诊病人需要办理医院的就诊卡,该卡上只有卡号,没有其它信息。但病人每次去该医院就诊时,只要出示就诊卡,医务人员便可根据卡号查询病人的就诊信息。Session技术就好比医院发放给病人的就诊卡和医院为每个病人保留病例档案的过程。当浏览器访问Web服务器时,Servlet容器就会创建一个Session对象和ID属性,其中,Session对象就相当于病历档案,ID就相当于就诊卡号。当客户端后续访问服务器时,只要将标识号传递给服务器,服务器就能判断出该请求是哪个客户端发送的,从而选择与之相应的Session对象为其服务。
需要注意的是,由于客户端需要接收、记录和回送Session对象的ID。因此,通常情况下,Session是借助Cookie技术来传递ID属性的。
为了更好理解Session,接下来以网站购物为例,通过一张图来描述Session保存用户信息的原理:
上图中,用户甲和乙都调用buyServlet将商品添加到购物车,调用payServlet进行商品结算。由于甲和乙购买商品的过程类似,在此,以用户甲为例进行详细说明。当用户甲访问购物网站时,服务器为甲创建了一个Session对象(相当于购物车)。当甲将Nokia手机添加到购物车时,Nokia手机的信息便存放到了Session对象中。同时,服务器将Session对象的ID属性以Cookie (Set-Cookie: JSESSIONID=111)的形式返回给甲的浏览器。当甲完成购物进行结账时,需要向服务器发送结账请求,这时,浏览器自动在请求消息头中将Cookie (Cookie: JSESSIONID=111)信息回送给服务器,服务器根据ID属性找到为用户甲所创建的Session对象,并将Session对象中所存放的Nokia手机信息取出进行结算。
【总结】:Session技术是将数据存储在服务器端的技术,会为每个客户端都创建一块内存空间存储客户的数据,但客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内存空间。所以说Session的实现是基于Cookie,Session需要借助于Cookie存储客 户的唯一性标识JSESSIONID
3.2 有了Cookie为什么还要Session
- Cookie是有大小和个数的限制的.Session存到服务器端的技术,没有大小和个数的限制.
- Cookie相对于Session来讲不安全.
3.3 如何获得Session对象
HttpSession session = request.getSession();
此方法会获得专属于当前会话的Session对象,如果服务器端没有该会话的Session 对象会创建一个新的Session返回,如果已经有了属于该会话的Session直接将已有的Session返回(实质就是根据JSESSIONID判断该客户端是否在服务器上已经存在session了)
3.4 怎样向session中存取数据
我们已经学习过HttpServletRequest、ServletContext,它们都是域对象,而session也是一个域对象,所以session对象也具有如下三个方法:
- void setAttribute(String name, Object value):用来存储一个对象,例如:session.setAttribute(“xxx”, “XXX”),在session中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。请注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同;
- Object getAttribute(String name):用来获取session中的数据,当前在获取之前需要先去存储才行,例如:String value = (String) session.getAttribute(“xxx”);,获取名为xxx的域属性;
- void removeAttribute(String name):用来移除HttpSession中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做;
3.5 Session对象的生命周期
【创建】:第一次执行request.getSession()时创建
【销毁】:
1)服务器(非正常)关闭时
2)session过期/失效(默认30分钟)
问题:时间的起算点 从何时开始计算30分钟?(从不操作服务器端的资源开始计时)
可以在工程的web.xml中进行配置
<session-config> <session-timeout>30</session-timeout> </session-config>
3)手动销毁session:session.invalidate();
【作用范围】:
默认在一次会话中,也就是说在,一次会话中任何资源公用一个session对象