《Java Web程序设计任务教程》简要复盘:第五章 会话及其会话技术
作者:氯磷Rolin
目录:
- 第一章:网页开发基础(无)
- 第二章:Java Web概述
- 第三章:Servlet基础
- 第四章:请求与响应
- 第五章:会话及其会话技术
- 第六章:JSP技术
- 第七章:EL表达式和JSTL
- 第八章:Servlet的高级特性
- 第九章:JDBC
- 第十章:数据库连接池与DBUtils工具
- 第十一章:JSP开发模型
- 第十二章:文件的上传和下载
第五章:会话及其会话技术
当用户通过浏览器访问Web应用时,通常情况下,服务器需要对用户的状态进行跟踪
会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
会话概述
Web应用中的会话过程类似于生活中打电话的过程,它指的是一个客户端与Web服务器之间连续发生的一系列请求和响应过程
例如:一个用户在某网站上整个的购物过程就是一个会话
虽然HttpServletRequest对象和ServletContext对象都可以对数据进行保存,但是两个对象都不适用于会话跟踪,原因有二:
- 客户端请求Web服务器时,针对每次HTTP请求,Web服务器都会创建一个HttpServletRequest对象,该对象只能保存本次传递的数据,比如购买和结账是两个操作,对应两个请求,因此在发送结账请求时,之前购买请求中的数据就会消失
- 使用ServletContext对象保存数据时,由于同一个Web应用共享的是同一个ServletContext对象,因此当用户发送结算请求时,服务器无法分辨哪些商品是哪些用户购买的,而会对所有商品进行结算,这显然是不可行的
在程序中,会话跟踪是很重要的事情。理论上,一个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。例如,用户A在超市购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,这都是属于同一个会话的,不能放入用户B或用户C的购物车内,这不属于同一个会话。
为了保存会话中产生的数据,在Servlet技术中,提供了两个用于保存会话数据的对象分别是Cookie和Session
Cookie对象
Cookie是一种会话技术,它用于将会话过程中的数据保存到用户的浏览器中,从而使到服务器可以更好的进行数据的交互
什么是Cookie
Cookie意为“甜饼”,是由W3C组织提出,最早由Netscape社区发展的一种机制。目前Cookie已经成为标准,所有的主流浏览器如IE、Netscape、Firefox、Opera等都支持Cookie。
由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
- 服务器向客户端发送Cookie时,会在HTTP响应头字段中增加Set-Cookie响应头字段。
Set-Cookie头字段中设置的Cookie遵循着一定的语法格式:
Set-Cookie: user=Rolin; Path=/;
user表示Cookie的名称,Rolin表示Cookie的值,Path表示Cookie的属性
需要注意的是:Cookie必须以键值对的形式存在,其属性可以有多个,但这些属性之间必须用分号和空格间隔 - 工作原理:
当用户第一次访问服务器时,服务器会在响应消息中增加Set-Cookie头字段,将用户信息以Cookie的形式发送给浏览器。一旦用户浏览器接受了服务器发送的Cookie信息,就会将其保存到缓冲区中。这样,当浏览器后续访问该服务器时,都会在请求消息中将用户信息以Cookie的形式发送给服务器,从而使服务器端分辨出当前请求是由哪个用户发出的。
Cookie 属性
Cookie的name属性一旦确定,即不可更改
- Cookie常用属性
属性名 | 描述 |
---|---|
String name | Cookie的名称 |
Object value | Cookie的值。如果值为Unicode字符,需要为字符编码。如果值为二进制数据,则需要使用BASE64编码 |
int maxAge | 该Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为–1 |
boolean secure | 该Cookie是否仅被使用安全协议传输。安全协议。安全协议有HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false |
String path | 该Cookie的使用路径。如果设置为“/sessionWeb/”,则只有contextPath为“/sessionWeb”的程序可以访问该Cookie。如果设置为“/”,则本域名下contextPath都可以访问该Cookie。注意最后一个字符必须为“/” |
String domain | 可以访问该Cookie的域名。如果设置为“.google.com”,则所有以“google.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.” |
String comment | 该Cookie的用处说明。浏览器显示Cookie信息的时候显示该说明 |
int version | 该Cookie使用的版本号。0表示遵循Netscape的Cookie规范,1表示遵循W3C的RFC 2109规范 |
Cookie 规范
Http协议提供了有关Cookie的规范,如今市场上出现了大量的浏览器,一些浏览器对该Cookie规范进行了一些扩展,例如每个Cookie的大小为8KB,最多可保存500个Cookie等,但Cookie缓存文件不会占满硬盘空间。
HTTP协议的Cookie规范如下:
- Cookie通过请求头和响应头在服务器与客户端之间传输。
- Cookie大小上限为4KB。
- 一个服务器最多在客户端浏览器上保存20个Cookie。
- 一个浏览器最多保存300个Cookie。
Cookie API
为了封装Cookie信息,在Servlet API中提供一个javax.servlet.http.Cookie类,包含了生成Cookie信息和提取Cookie信息各个属性的方法
1.构造方法
- Cookie类有且仅有一个构造方法,具体语法:
public Cookie (java.lang.String name , java.lang.String value);
其中参数name是Cookie的名称,value用于指定Cookie的值
2.Cookie类的常用方法
方法声明 | 功能描述 |
---|---|
String getName() | 用于返回Cookie的名称 |
void setValue(String newValue) | 用于为Cookie设置一个新的值 |
String getValue() | 用于返回Cookie的值 |
void setMaxAge(int expiry) | 用于设置Cookie在浏览器上保持有效的秒数 |
int getMaxAge() | 用于返回Cookie在浏览器上保持有效的秒数 |
void setPath(String url) | 用于设置Cookie项的有效目录路径 |
String getPath() | 用于返回Cookie项的有效目录 |
void setDomain(String pattern) | 用于设置该Cookie的有效域 |
String getDomain() | 用于返回该Cookie的有效域 |
void setVersion(int v) | 用于设置该Cookie采用的协议版本 |
int getVersion() | 用于返回该Cookie采用的协议版本 |
void setComment(String purpose) | 用于设置该Cookie项的注解部分 |
String getComment() | 用于返回该Cookie的注解部分 |
void setSecure(boolean flag) | 用于设置该Cookie项是否只能使用安全的协议传送 |
boolean getSecure() | 用于返回该Cookie项是否只能使用安全的协议传送 |
Session对象
除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。
Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。
Session是一种将会话数据保存到服务器端的技术
什么是Session?
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。
Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。
- Session保存用户信息的过程
HttpSession API
- 方法重载
Session是与每个请求消息紧密相关的,为此HttoServletRequest定义了用于获取Session对象的getSession()方法,该方法有两种重载形式:
public HttpSession getSession(boolean create);
public HttpSession getSession();
getSession(boolean create) 根据传递的参数来判断是否创建新的HttpSession对象
如果参数为true,则在相关的HttpSession对象不存在时创建并返回新的HttpSession对象
如果参数为false,则在相关HttpSession对象不存在时返回null
- HttpSession接口中的常用方法
要想使用HttpSession对象管理会话数据,不仅需要获取到HttpSession对象,还需要了解其相关方法
方法声明 | 功能描述 |
---|---|
String getId() | 返回当前Session的标识号 |
long getCreationTime() | 返回创建Session的时间,该值是一个长整数 |
long getLastAccessedTime() | 返回Session与客户端最后一次请求的时间 |
void setMaxInactiveInterval(int interval) | 修改当前会话的默认超时间隔 |
boolean isNew() | 判断当前Session是否新创建的 |
void invalidate() | 强制使Session对象无效 |
ServletContext getServletContext() | 返回一个代表当前Web程序的的ServletContext对象 |
void setAttribite(String name,Object value) | 用于将一个对象与一个名称关联后存放到Session对象 |
String getAttribute() | 用于从当前Seesion对象中返回指定名称的属性对象 |
void removeAttribute(String name) | 用于从当前Session对象中删除指定名称的属性 |
超时管理
当客户端第一次访问某个能开启会话的资源时,Web服务器就会创建一个与该客户端对应的Session对象,即使客户端已经离开或者关闭了浏览器,Web服务器还要保留与之对应的HttpSession对象。随之时间的推移,这些不再使用的HttpSession对象会在Web服务器中累积的越来越多,从而使Web服务器的内存耗尽
为了解决上面的问题,Web服务器采用了超时限制的方法来判断客户端是否还在继续访问,如果超过一定时间客户端也没有来访问Web服务器,则将与该客户端会话所对应的Session对象变为垃圾对象,等待垃圾收集器彻底清除它。
- 有三种方案来管理超时的Session
-
配置tomcat全局超时管理
在tomcat服务器的 conf/web.xml 文件配置session的超时
时间是分钟为单位,此时配置session的超时管理适用于所有的web应用<session-config> <session-timeout>20</session-timeout> </session-config>
-
配置当前应用程序的超时管理
在当前的web应用的web.xml文件中配置session的超时管理,会覆盖tomcat服务器的web.xml文件中的配置<session-config> <!-- 配置session的超时管理,以分钟为单位 --> <session-timeout>30</session-timeout> </session-config>
-
通过session对象的方法实现超时管理
设置一个秒数,这个秒数表示客户端在不发出请求时,session被Servlet引擎维持的最长时间。session.setMaxInactiveInterval(5);
-
三个方案的优先级:方案3>>方案2>>方案1
要想使Session失效,除了可以等待会话时间超时外,还可以通过invalidate()
方法强制使会话无效
实例
1.显示用户上次访问时间
- 目标
当用户访问某些Web应用时,经常会显示出该用户上一次的访问时间。例如,QQ登录成功会后显示用户上次登录时间。 - 具体实现