41
IT资资资资资 WWW.IT315.ORG 资资资 IT 资资 资资 Java Web 资资资资

张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

  • Upload
    cedric

  • View
    112

  • Download
    8

Embed Size (px)

DESCRIPTION

张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕. WEB 应用中的会话与会话状态 Cookie 在 Servlet 程序中使用 Cookie Session Session 的典型案例 Session 的持久化管理. 第 7 讲 会话与状态管理. 在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。 WEB 应用中的会话是指一个客户端浏览器与 WEB 服务器之间连续发生的一系列请求和响应过程。 - PowerPoint PPT Presentation

Citation preview

Page 1: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

张孝祥 IT课堂-深入体验 Java Web 开发内幕

Page 2: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

第 7 讲 会话与状态管理 WEB 应用中的会话与会话状态 Cookie 在 Servlet 程序中使用 Cookie Session Session 的典型案例 Session 的持久化管理

Page 3: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

会话与会话状态简介 在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。 WEB 应用中的会话是指一个客户端浏览器与 WEB 服务器之间连续发生的一系列请求和响应过程。 WEB 应用的会话状态是指 WEB 服务器与浏览器在会话过程中产生的状态信息,借助会话状态, WEB 服务器能够把属于同一会话中的一系列的请求和响应过程关联起来。

Page 4: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

如何实现有状态的会话 某个用户从网站的登录页面登入后,再进入购物页面购物时,负责处理购物请求的服务器程序必须知道处理上一次请求的程序所得到的用户信息。 HTTP 协议是一种无状态的协议, WEB 服务器本身不能识别出哪些请求是同一个浏览器发出的 ,浏览器的每一次请求都是完全孤立的。 WEB 服务器端程序要能从大量的请求消息中区分出哪些请求消息属于同一个会话,即能识别出来自同一个浏览器的访问请求,这需要浏览器对其发出的每个请求消息都进行标识,属于同一个会话中的请求消息都附带同样的标识号,而属于不同会话的请求消息总是附带不同的标识号,这个标识号就称之为会话 ID ( Se

ssionID )。 会话 ID 可以通过一种称之为 Cookie 的技术在请求消息中进行传递,也可以作为请求 URL 的附加参数进行传递。会话 ID 是 WEB 服务器为每客户端浏览器分配的一个唯一代号,它通常是在 WEB 服务器接收到某个浏览器的第一次访问时产生,并且随同响应消息一道发送给浏览器。 会话过程由 WEB 服务器端的程序开启,一旦开启了一个会话,服务器端程序就要为这个会话创建一个独立的存储结构来保存该会话的状态信息,同一个会话中的访问请求都可以且只能访问属于该会话的存储结构中的状态信息。

Page 5: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

什么是 Cookie Cookie 是一种在客户端保持 HTTP 状态信息的技术,它好比商场发放的优惠卡。 Cookie 是在浏览器访问 WEB 服务器的某个资源时,由 WEB 服务器在 HTTP 响应消息头中附带传送给浏览器的一片数据, WEB 服务器传送给各个客户端浏览器的数据是可以各不相同的。 一旦 WEB 浏览器保存了某个 Cookie ,那么它在以后每次访问该 WEB 服务器时,都应在 HTTP 请求头中将这个 Cookie 回传给 WEB 服务器。 WEB 服务器通过在 HTTP 响应消息中增加 Set-Cookie 响应头字段将 Cookie 信息发送给浏览器,浏览器则通过在 HTTP 请求消息中增加 Cookie 请求头字段将 Cookie 回传给 WEB 服务器。 一个 Cookie 只能标识一种信息,它至少含有一个标识该信息的名称( NAME )和设置值( VALUE )。 一个 WEB 站点可以给一个 WEB 浏览器发送多个 Cookie ,一个 WEB 浏览器也可以存储多个 WEB 站点提供的 Cookie 。 浏览器一般只允许存放 300 个 Cookie ,每个站点最多存放 20 个 Cookie ,每个Cookie 的大小限制为 4KB 。

Page 6: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Cookie 的传送过程示意图 ①第一次访问不存在Server1的 Cookie

④写入 Server1的 Cookie

③第一次响应Set-Cookie2: name=value

②第一次访问请求

WEBServer1

WEBServer2

浏览器

Server1的 Cookie

Server2的 Cookie

Cookie存储区

⑤后续访问存在Server1的 Cookie

⑥后续访问请求Cookie: name=value

Page 7: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Set-Cookie2 响应头字段 Set-Cookie2 头字段用于指定 WEB 服务器向客户端传送的 Cookie 内容,但是按照 Netscape 规范实现 Cookie 功能的 WEB 服务器,使用的是 Set-Cookie 头字段,两者的语法和作用类似。 Set-Cookie2 头字段中设置的 cookie 内容是具有一定格式的字符串,它必须以 Cookie 的名称和设置值开头,格式为“名称 = 值”,后面可以加上 0 个或多个以分号( ; )和空格分隔的其它可选属性,属性格式一般为“属性名 = 值”。

举例: Set-Cookie2: user=it315; Version=1; Path=/ 除了“名称 = 值”对必须位于最前面外,其它的可选属性的先后顺序可以任意。 Cookie 的名称只能由普通的英文 ASCII 字符组成,浏览器不用关心和理解 Cookie 的值部分的意义和格式,只要 WEB 服务器能理解值部分的意义就行。 大多数现有的 WEB 服务器都是采用某种编码方式将值部分的内容编码成可打印的 ASCII 字符, RFC 2965 规范中没有明确限定编码方式。

Page 8: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Set-Cookie2 头字段中的属性 Comment=value Discard Domain=value

例如: Set-Cookie2: user=it315; Version=1; Path=/; Domain=.it315.org Max-Age=value Path=value Port[="portlist"] Secure Version=value

多想一想:如果浏览器接收到两个名称完全相同的 Cookie ,后面接收的 Cookie 是否会替换前面接收的 Cookie

Page 9: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Cookie 请求头字段 浏览器使用 Cookie 请求头字段将 Cookie 信息回送给 WEB 服务器。 多个 Cookie 信息通过一个 Cookie 请求头字段回送给 WEB 服务器。 浏览器根据下面的几个规则决定是否发送某个 Cookie 信息: 请求的主机名是否与某个存储的 Cookie 的 Domain 属性匹配; 请求的端口号是否在该 Cookie 的 Port 属性列表中; 请求的资源路径是否在该 Cookie 的 Path 属性指定的目录及子目录中; 该 Cookie 的有效期是否已过。

Cookie 请求头字段中的每个 Cookie 之间用逗号( ,)或分号( ; )分隔。在 Cookie 请求头字段中除了必须有“名称 =值”的设置外,还可以有 Version、Path、 Domain、 Port等几个属性。在 Version、 Path、 Domain、 Port等属性名之前,都要增加一个“$”字符作为前缀。Version 属性只能出现一次,且要位于 Cookie 请求头字段设置值的最前面,如果需要设置某个 Cookie 信息的 Path、 Domain、 Port等属性,它们必须位于该Cookie 信息的“名称 =值”设置之后。Path 属性指向子目录的 Cookie排在 Path 属性指向父目录的 Cookie 之前。 举例: Cookie: $Version=1; Course=Java; $Path=/it315/lesson; Course=vc; $Path=/it315

Page 10: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

在 Servlet 程序中使用 Cookie Servlet API中提供了一个 javax.servlet.http.Cookie类来封装 Cookie 信息,它包含有生成 Cookie 信息和提取 Cookie 信息的各个属性的方法。 Cookie类的方法: 构造方法: public Cookie(java.lang.String name,java.lang.String value) getName 方法 setValue 与 getValue 方法 setMaxAge 与 getMaxAge 方法 setPath 与 getPath 方法 setDomain 与 getDomain 方法 setVersion 与 getVersion 方法 setComment 与 getComment 方法 setSecure 与 getSecure 方法

HttpServletResponse 接口中定义了一个 addCookie方法,它用于在发送给浏览器的 HTTP 响应消息中增加一个 Set-Cookie 响应头字段。HttpServletRequest 接口中定义了一个 getCookies方法,它用于从 HTTP 请求消息的 Cookie 请求头字段中读取所有的 Cookie项。

Page 11: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Cookie 的综合实例功能说明 程序包含两个 Servlet 组件: CookieServlet1.java 和 CookieServlet2.java 。 CookieServlet1 中产生四个名称分别为 name、 nickname、 email、phone 的 Cookie 信息。 name 和 nickname 这两个 Cookie 的值是通过请求参数来设置的,并且 nickname 这个 Cookie 保持有效的时间为1年, email 和 phone 这两个 cookie 的值是在程序中硬编码指定的。 在产生 Cookie 信息之后, CookieServlet1接着从请求消息中查找名称为 nickname 的 Cookie 信息,并根据返回结果打印出相应的问候语,CookieServlet1还打印出请求消息中的 Cookie 头字段的值。 CookieServlet2首先创建三个名称分别为 email、 phone、 sign 的 Cookie 信息,并将 phone 这个 Cookie 保持有效的时间设置为了 0秒,然后打印出请求消息中的 Cookie 头字段的值和每个 Cookie 的名称。 CookieServlet2 中的 email 和 phone 这两个 Cookie曾在 CookieServlet1程序中设置过,在 CookieServlet2程序再次进行设置,是为了便于查看设置同名 Cookie 的效果和了解如何删除 Cookie 。

Page 12: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Cookie 的综合实例实践 Cookie ckName = new Cookie("name",name);Cookie ckNickname = new Cookie("nickname",nickname);ckNickname.setMaxAge(365*24*3600);Cookie ckEmail = new Cookie("email","[email protected]");Cookie ckPhone = new Cookie("phone","1111111");response.addCookie(ckName);response.addCookie(ckNickname);response.addCookie(ckEmail);response.addCookie(ckPhone);

动手体验:了解 Cookie 的工作细节

String lastNickname = null;Cookie [] cks = request.getCookies();for(int i=0; cks!=null && i<cks.length; i++){

if("nickname".equals(cks[i].getName())) {

lastNickname = cks[i].getValue();break;

} } if(lastNickname != null){

out.println(" 欢迎您, " + lastNickname );}

Page 13: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Session 什么是 Session Session 的跟踪机制 Session 的超时管理 HttpSession 接口中的方法 HttpServletRequest 接口中的 Session方法 application 与 session域范围的属性比较 利用 Cookie 实现 Session跟踪 利用 URL重写实现 Session跟踪

Page 14: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

什么是 Session 使用 Cookie 和附加 URL参数都可以将上一次请求的状态信息传递到下一次请求中,但是如果传递的状态信息较多,将极大降低网络传输效率和增大服务器端程序处理的难度。 Session 技术是一种将会话状态保存在服务器端的技术 ,它可以比喻成是医院发放给病人的病历卡和医院为每个病人保留的病历档案的结合方式 。 客户端需要接收、记忆和回送 Session 的会话标识号, S

ession 可以且通常是借助 Cookie来传递会话标识号。

Page 15: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Session 的跟踪机制 Servlet API 规范中定义了一个 HttpSession接口, HttpSession接口定义了各种管理和操作会话状态的方法。 HttpSession 对象是保持会话状态信息的存储结构,一个客户端在 WEB 服务器端对应一个各自的 HttpSession 对象。 WEB 服务器并不会在客户端开始访问它时就创建 HttpSession 对象,只有客户端访问某个能与客户端开启会话的 Servlet程序时, WEB 应用程序才会创建一个与该客户端对应的 HttpSession 对象。 WEB 服务器为 HttpSession 对象分配一个独一无二的会话标识号,然后在响应消息中将这个会话标识号传递给客户端。客户端需要记住会话标识号,并在后续的每次访问请求中都把这个会话标识号传送给 WEB 服务器, WEB 服务器端程序依据回传的会话标识号就知道这次请求是哪个客户端发出的,从而选择与之对应的 HttpSession 对象。 WEB 应用程序创建了与某个客户端对应的 HttpSession 对象后,只要没有超出一个限定的空闲时间段, HttpSession 对象就驻留在 WEB 服务器内存之中,该客户端此后访问任意的Servlet程序时,它们都使用与客户端对应的那个已存在的 HttpSession 对象。 HttpSession接口中专门定义了一个 setAttribute 方法来将对象存储到 HttpSession 对象中,还定义了一个 getAttribute 方法来检索存储在 HttpSession 对象中的对象,存储进 HttpSession 对象中的对象可以被属于同一个会话的各个请求的处理程序共享。 Session 是实现网上商城的购物车的最佳方案,存储在某个客户 Session 中的一个集合对象就可充当该客户的一个购物车。

Page 16: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Session 的超时管理 WEB 服务器无法判断当前的客户端浏览器是否还会继续访问,也无法检测客户端浏览器是否关闭,所以,即使客户已经离开或关闭了浏览器, WEB 服务器还要保留与之对应的 HttpSession 对象。 随着时间的推移而不断增加新的访问客户端, WEB 服务器内存中将会因此积累起大量的不再被使用的 HttpSession 对象,并将最终导致服务器内存耗尽。 WEB 服务器采用“超时限制”的办法来判断客户端是否还在继续访问,如果某个客户端在一定的时间之内没有发出后续请求, WEB 服务器则认为客户端已经停止了活动,结束与该客户端的会话并将与之对应的 HttpSession 对象变成垃圾。 如果客户端浏览器超时后再次发出访问请求, WEB 服务器则认为这是一个新的会话的开始,将为之创建新的 HttpSession 对象和分配新的会话标识号。 会话的超时间隔可以在web.xml 文件中设置,其默认值由 Servlet 容器定义。 <session-config><session-timeout>30</session-timeout></session-config>

Page 17: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

HttpSession 接口中的方法 getId方法 getCreationTime方法 getLastAccessedTime方法 setMaxInactiveInterval方法 getMaxInactiveInterval方法 isNew方法

* 如果客户端请求消息中返回了一个与 Servlet程序当前获得的 HttpSession 对象的会话标识号相同的会话标识号,则认为这个 HttpSession 对象不是新建的。 invalidate方法 getServletContext方法 setAttribute方法 getAttribute方法 removeAttribute方法 getAttributeNames方法

Page 18: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

HttpServletRequest接口中的 Session方法 getSession方法

public HttpSession getSession(boolean create)public HttpSession getSession()

isRequestedSessionIdValid方法 isRequestedSessionIdFromCookie方法 isRequestedSessionIdFromURL方法

多想一想:什么情况下该调用 request.getSession(false)方法

Page 19: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

application域范围的属性 application.setAttribute(x,obj)

浏览器(a)

浏览器(b)

浏览器(c)浏览器(d)

Servlet(1)

Servlet(2)浏览器(a)

浏览器(b)

浏览器(c)

浏览器(d)

application对象

x = obj;

application.getAttribute(x)

所有客户端共享同一个application对象

Page 20: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Session域范围的属性 session.setAttribute(x,obj)

x = ” aaa” ;

session对象(d)session对象(c)

x = ” aaa” ;

session对象(b)

x = ” aaa” ;

session对象(a)

x = obj;

浏览器(a)

浏览器(b)

浏览器(c)浏览器(d)

session.getAttribute(x)

Servlet(1)

Servlet(2)

各个客户端所对应的session对象

各个客户端所对应的session对象

浏览器(a)

浏览器(b)

浏览器(c)

浏览器(d)

Page 21: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Application与 session域范围的属性比较实践 HttpSession session = request.getSession();Integer sessionCount = (Integer)session.getAttribute("count");int count = 0;if(sessionCount != null){ count = sessionCount.intValue();}out.println(" 当前会话中发生了 " + (++count) + "次访问 <br>");session.setAttribute("count",new Integer(count));count = 0;ServletContext application = getServletContext();Integer applicationCount = (Integer)application.getAttribute("count");if(applicationCount != null){ count = applicationCount.intValue();}out.println("WEB 应用程序中发生了 " + (++count) + "次访问 <br>");application.setAttribute("count",new Integer(count));

动手体验:了解 application 和 session域范围的属性的差异

Page 22: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

利用 Cookie 实现 Session跟踪 如果WEB 服务器处理某个访问请求时创建了新的 HttpSession 对象,它将把会话标识号作为一个 Cookie项加入到响应消息中,通常情况下,浏览器在随后发出的访问请求中又将会话标识号以 Cookie 的形式回传给 WEB 服务器。WEB 服务器端程序依据回传的会话标识号就知道以前已经为该客户端创建了 HttpSession 对象,不必再为该客户端创建新的 HttpSessio

n 对象,而是直接使用与该会话标识号匹配的 HttpSession 对象,通过这种方式就实现了对同一个客户端的会话状态的跟踪。

动手体验:了解如何利用 Cookie 实现 Session跟踪

Page 23: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

利用 URL重写实现 Session跟踪 Servlet 规范中引入了一种补充的会话管理机制,它允许不支持 Cookie 的浏览器也可以与 WEB 服务器保持连续的会话。这种补充机制要求在响应消息的实体内容中必须包含下一次请求的超链接,并将会话标识号作为超链接的 URL地址的一个特殊参数。 将会话标识号以参数形式附加在超链接的 URL地址后面的技术称为 URL重写。如果在浏览器不支持 Cookie 或者关闭了 Cookie 功能的情况下, WEB 服务器还要能够与浏览器实现有状态的会话,就必须对所有可能被客户端访问的请求路径(包括超链接、 form表单的 action 属性设置和重定向的 URL )进行 URL重写。 HttpServletResponse接口中定义了两个用于完成 URL重写方法:

encodeURL 方法 encodeRedirectURL 方法

动手体验:利用 URL重写实现 Session跟踪

Page 24: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Session 的典型案例 使用 Session 实现购物车 利用 Session防止表单重复提交 利用 Session 实现一次性验证码 跟踪用户上次访问站点的时间及 Cookie 中文问题

Page 25: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

使用 Session 实现购物车功能说明 程序包含一个 HTML 文件和两个 Servlet 组件: logon.html、 LogonServlet.java 和 CoursesServlet.java 。 logon.html 提供用户登录的界面; LogonServlet.java 是一个负责处理用户登录的 Servlet程序。 CoursesServlet.java完成了三项功能:显示所有可选课程的列表、将用户选择的课程放入购物车、显示购物车中的课程。 LogonServlet.java 的登录验证方式非常简单,只要登录的用户名不为空白字符串即可; LogonServlet.java 先将成功登录的用户名保存到 Session 中,然后将请求转发给 CoursesServlet.java显示所有可选课程的列表;如果登录失败, LogonServlet.java 则再次显示登录界面。 CoursesServlet.java需要完成如下任务:

首先判断访问请求是否来自一个已登录用户,如果不是,则将请求重定向到 logon.html页面。 接着判断当前访问请求是否是用户选择课程时发出的,如果是,则将用户选择的课程加入购物车。 最后显示出所有供选择的课程列表和已放入购物车中的课程列表。

Page 26: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

使用 Session 实现购物车实践String courseSelect = request.getParameter("course");if(courseSelect != null){ Vector vCourses = (Vector)session.getAttribute("courses");if(vCourses == null) {vCourses = new Vector();vCourses.add(courseSelect);session.setAttribute("courses",vCourses);}else {if(vCourses.contains(courseSelect)) {out.println(sessionName + ",你以前选择过了 " + courseSelect + "<hr>");}else {vCourses.add(courseSelect);}}} 动手体验:使用 Session 实现购物车功能

Page 27: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

利用 Session防止表单重复提交原理 包含有 FORM表单的页面必须通过一个服务器程序动态产生,服务器程序为每次产生的页面中的 FORM表单都分配一个唯一的随机标识号,并在 FORM表单的一个隐藏字段中设置这个标识号,同时在当前用户的 Session域中保存这个标识号。 当用户提交 FORM表单时,负责接收这一请求的服务器程序比较 FORM表单隐藏字段中的标识号与存储在当前用户的 Session域中的标识号是否相同,如果相同则处理表单数据,处理完后清除当前用户的 Session域中存储的标识号。在下列情况下,服务器程序将忽略提交的表单请求:

当前用户的 Session 中不存在表单标识号用户提交的表单数据中没有标识号字段存储在当前用户的 Session域中的表单标识号与表单数据中的标识号不同

浏览器只有重新向 WEB 服务器请求包含 FORM表单的页面时,服务器程序才又产生另外一个随机标识号,并将这个标识号保存在 Session域中和作为新返回的 FORM表单中的隐藏字段值。

Page 28: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

利用 Session防止表单重复提交实践

动手体验:利用 Session防止表单重复提交

程序包含三个 Java 源程序: TokenProcessor.java、 FormGenerateServlet.java 和 FormDealServlet.java 。 TokenProcessor.java 是用于管理表单标识号的工具类,它主要用于产生、比较和清除存储在当前用户 Session 中的表单标识号。为了保证表单标识号的唯一性,每次将当前 SessionID 和系统时间的组合值按 MD5算法计算的结果作为表单标识号,并且将 TokenProcessor 类设计为单件类。 FormGenerateServlet.java 是用于产生 FORM表单的 Servlet程序, FormDealServlet 是负责处理 FORM表单请求的 Servlet程序。

多学两招: MD5算法及其应用

Page 29: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

利用 Session防止表单重复提交问题 问题:

同一个用户打开同一个浏览器进程的多个窗口来并发访问同一个 WEB站点的多个 FORM表单页面时,将会出现表单无法正常提交的情况。 解决方案:

将 FORM表单的标识号作为表单隐藏字段的名称,如下所示:<input type='hidden' name='4b15c6b2f573831b4b5107d849fcafb8' value=''>

将所有的表单标识号存储进一个 Vector集合对象中,并将 Vector集合对象存储进 Session域中。当表单提交时,先从 Session域中取出 Vector集合对象,然后再从 Vector集合对象中逐一取出每个表单标识号作为参数调用 HttpServletRequest.getParameter 方法,如果其中有一次调用的返回值不为 null ,则接受并处理该表单数据,处理完后将该表单标识号从 Vector集合对象中删除。

Page 30: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

利用 Session 实现一次性验证码图例

Page 31: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

利用 Session 实现一次性验证码原理 一次性验证码的主要目的就是为了限制人们利用工具软件来暴力猜测密码,其原理与利用 Session防止表单重复提交的原理基本一样,只是将表单标识号变成了验证码的形式,并且要求用户将提示的验证码手工填写进一个表单字段中,而不是通过表单的隐藏字段自动回传给服务器。 服务器程序接收到表单数据后,首先判断用户是否填写了正确的验证码,只有该验证码与服务器端保存的验证码匹配时,服务器程序才开始正常的表单处理流程。 密码猜测工具要逐一尝试每个密码的前题条件是先输入正确的验证码,而验证码是一次性有效的,这样基本上就阻断了密码猜测工具的自动地处理过程。

Page 32: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

利用 Session 实现一次性验证码实践

动手体验:利用 Session 实现一次性验证码

整个程序包含三个组件: check_code.html、 CheckCodeServlet.java和 LogonFormServlet.java 。 check_code.html 是引用验证码图片的 FORM表单页面, CheckCodeServlet.java 是用于产生带有随机验证码图片的 Servlet程序, LogonFormServlet.java 则是负责处理 FORM表单请求的 Servlet程序。

多学两招:用时间间隔限制用户连续发帖

Page 33: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

跟踪用户上次访问站点的时间及 Cookie 中文问题 功能:帮助网站实现提示客户端计算机上次访问网站的时间

实现原理:将每一个会话作为一次访问过程,将每次会话的开始时间作为每次访问网站的时间,然后将这个时间以 Cookie 的形式存储到客户端的计算机中,客户端进行下次访问时通过该 Cookie 回传上次访问站点的时间值。 为了让 Cookie 信息在客户端浏览器或计算机关闭后仍然保持存在,Cookie 的保存时间被设置为了一年。Cookie 值中包含有中文字符,如果直接将它们传递给浏览器,其中的中文字符将丢失,,因此需要采用 BASE64 编码方式将 Cookie 值编码成了可打印的 ASCII 字符后再进行传递。

Page 34: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

跟踪用户上次访问站点的时间及 Cookie 中文问题程序代码//获取记录用户上次访问站点时间的 CookieCookie [] cks = request.getCookies();String lastAccessTime = getCookie(cks,"access_time");if(lastAccessTime == null){ out.println("没有您上次的访问记录 ");}else{ BASE64Decoder decoder = new BASE64Decoder();String decodedAccessTime = new String(decoder.decodeBuffer(lastAccessTime),"GB2312");out.println(" 您上次的访问时间为 " + decodedAccessTime);}// 将用户开始本次访问的时间存储到客户端 Cookie 中HttpSession session = request.getSession();if(session.isNew()){ long createTime = session.getCreationTime();Date dateCreateTime = new Date(createTime);SimpleDateFormat sdf = new SimpleDateFormat("yyyy年 MM月 dd HH 点 mm 分 ss秒 ");String formatedCreateTime = sdf.format(dateCreateTime);BASE64Encoder encoder = new sun.misc.BASE64Encoder();String base64CreateTime = encoder.encode(formatedCreateTime.getBytes("GB2312"));......

Page 35: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Session 的持久化 为了提高服务器内存资源的利用率, WEB 服务器通常将那些暂时不活动但未超时的 HttpSession 对象转移到文件系统或数据库中保存,一旦服务器需要使用它们时,再将它们从文件系统或数据库中装载进内存,这种技术称为 Session 的持久化。 将 HttpSession 对象保存到文件系统或数据库中时,需要采用序列化的方式将 HttpSession 对象中的每个属性对象保存到文件系统或数据库中;将 HttpSession 对象从文件系统或数据库中装载进内存时,需要采用反序列化的方式恢复 HttpSession 对象中的每个属性对象。 存储在 HttpSession 对象中的每个属性对象必须是可序列化的,即必须是实现了 Serializable接口的对象。 Session 持久化的作用:

提高服务器内存资源的利用率 在集群系统中同步 Session 对象 保障重启服务器和应用程序时,一些客户端的会话活动仍可继续

Page 36: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Tomcat 中的 Session 持久化管理 org.apache.catalina.session.StandardManager默认的存储文件为:<tomcat安装目录 >\work\Catalina\<主机名 >\<应用程序名 >\SESSIONS.ser

org.apache.catalina.session.PersistentManager要求设备提供实现 org.apache.catalina.Store接口的驱动类

配置<Context path= "/it315" docBase="it315">

<Manager className="org.apache.catalina.session.PersistentManager" …><Store className="…" …></Manager>

</Context>

Page 37: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

Tomcat 中的Session 持久化管理实践 程序包含三个组件: Student1.java、 Student2.java 和 PersistentServlet.java 。 Student1.java 和 Student2.java 是两个普通的 Java 类, Student2 实现了 Serializable接口, Student1 没有实现 Serializable接口,除此之外, Student1 和 Student2 中的其他代码完全一样。 PersistentServlet.java 是一个 Servlet程序,它在第一次被访问时将 Student1 和 Student2 的实例对象保存到 Session域中,在以后被访问时又从 Session域中读取先前保存的 Student1 和 Student2 的实例对象。

多学两招 :了解 Tomcat 的 Session 持久化

Page 38: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

思考与实践( 1 )1.在默认情况下,同一个浏览器访问 Tomcat 中的两个 WEB 应用程序时,两个 WEB 应用程序中的 Session 数据是不能共享的。 Tomcat 提供了让同一 WEB 站点上的所有应用程序之间能共享会话状态的设置选项,进入 Tomcat自带的关于 Tomcat 配置( Tomcat Configuration )的帮助文档,查看 Http连接器( HTTP Connector )的属性设置说明,可以看到 Http连接器中有一个 emptySessionPath 属性,将该属性设置为 true 时,同一 WEB 站点上的所有应用程序将共享会话信息, WEB 服务器返回的会话标识号的 Cookie项的 path 属性将被设置为“ /” ,即整个站点的根目录。请参照本书编写实验步骤的方法设计一个详细的实验步骤对此进行验证,并将完成的结果提交给 www.it315.org 站点评审,表现优异者将获得www.it315.org 站点的奖励和专家的指点。提示:首先在应用程序 appA 中设置某个 Session域属性,然后在应用程序 appB 的 Session域中访问那个属性,如果不能无法访问到该属性,则说明两个 WEB 应用程序中的 Session 数据是不能共享的;接着修改 Tomcat 的 Http连接器的配置,让同一 WEB 站点上的所有应用程序之间能共享会话状态,重复上面的操作和查看访问结果。

Page 39: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

思考与实践( 2 )2.假设浏览器显示出了服务器返回的一个页面后,客户机发生了网络瞬间断线,且重新接通网络后客户端的 IP地址发生了改变,如果用户继续接着在浏览器原来得到的页面中执行操作,其操作结果有可能受到网络断线的影响吗?例如,服务器端程序使用 Session 技术防止该表单被重复提交,当浏览器得到包含 FORM表单的页面内容后,客户机发生了网络瞬间断线,这时候用户还能够继续使用原来获得的 FORM表单提交数据吗? 3.本课的购物车例子程序缺少一个用户注销登录的功能,注销登录的程序代码虽然非常简单,但却非常有利于 WEB 服务器及时清理离开用户的HttpSession 对象。另外,该购物车例子程序没有考虑客户端不支持 Cookie 的情况,即没有增加 URL重写的方式来完成 Session会话的跟踪。为了节省WEB 服务器端的内存资源,不要创建一些无价值的 HttpSession 对象, WEB 服务器与浏览器的会话过程最好是从用户成功登录后才正式建立,即WEB 服务器只在用户成功登录后才真正创建 HttpSession 对象,而对于其他任何情况都不应创建 HttpSession 对象,本课的购物车例子程序没有按照这种思想设计。请在本课的购物车例子程序的基础上增加和完善上述功能。并将完成的结果提交给 www.it315.org 站点评审,表现优异者将获得www.it315.org 站点的奖励和专家的指点。

Page 40: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

思考与实践( 3 )4.当一个 Servlet程序使用 RequestDispatcher.forward方法调用另外一个 Servlet程序时,调用者程序可以使用 application、 session、request 这三个域范围中的属性来向被调用者程序传递对象数据,你觉得采用其中的哪个才是最佳方案?请说明不采用其他两个域范围的理由。5.请参照本课的防止表单重复提交的例子程序设计如下一个应用程序并写出详细的实验步骤:WEB 站点需要按使用 Session防止表单重复提交,但也要支持在同一会话中可并行打开多个 FORM表单页面的功能,例如,主窗口访问一个 FORM表单页面后,接着又调用 javascript 的window.open 方法打开了另外一个 FORM表单页面,这两个 FORM表单都可以向 WEB 服务器提交一次数据。 6.一些网站通常采用在 Session 中记录用户发帖的时间,然后通过一个时间间隔来限制用户连续发帖的数量,请编写一个限定用户连续两次提交表单的最小时间间隔的程序来模拟这种应用。

Page 41: 张孝祥 IT 课堂 - 深入体验 Java Web 开发内幕

IT WWW.IT315.ORG资讯交流网

结束语欢迎大家参与多媒体 IT课堂其他课程欢迎加入 IT315把宝贵经验分享给大家

相聚的地方,就在……HTTP://WWW.IT315.ORG