httpSession的正确理解

关于HttpSession的误解实在是太多了,本来是一个很简单的问题,怎会搞的如此的复杂呢?下面说说我的理解吧:

一个session就是一系列某用户和服务器间的通讯。服务器有能力分辨出不同的用户。一个session的建立是从一个用户向服务器发第一个请求开始,而以用户显式结束或session超时为结束。
其工作原理是这样的:
1.当一个用户向服务器发送第一个请求时,服务器为其建立一个session,并为此session创建一个标识号;
2.这个用户随后的所有请求都应包括这个标识号。服务器会校对这个标识号以判断请求属于哪个session。
这种机制不使用IP作为标识,是因为很多机器是通过代理服务器方式上网,没法区分每一台机器。
对于session标识号(sessionID),有两种方式实现:cookies和URL重写。

HttpSession的使用
我们来看看在API中对session是如何定义和操作的。
当需要为用户端建立一个session时,servlet容器就创建了一个HttpSession对象。其中存储了和本session相关的信息。所以,在一个servlet中有多少个不同用户连接,就会有多少个HttpSession对象。
使用的机理是:
1.从请求中提取HttpSession对象;
2.增加或删除HttpSession中的属性;
3.根据需要关闭HttpSession或使其失效。

在请求中有两个重载的方法用来获取HttpSession对象。
HttpSession getSession(boolean create)/getSession();作用是提取HttpSession对象,如果没有自动创建。

获取到HttpSession对象后,我们就需要使用HttpSession的某些方法去设置和更改某些参数了。如:
void setAttribute(String name, Object value);
Object getAttribute(String name);
void removeAttribute(String name);

在javax.servlet.http包里一共定义了四个session监听器接口和与之关联的两个session事件。分别是:
HttpSessionAttributeListener and HttpSessionBindingEvent;
HttpSessionBindingListener and HttpSessionBindingEvent;
HttpSessionListener and HttpSessionEvent;
HttpSessionActivationListener and HttpSessionEvent.

他们的继承关系是:
所有四个接口的父类是java.util.EventListener;
HttpSessionEvent扩展java.util.EventObject;
而HttpSessionBindingEvent又扩展了HttpSessionEvent。

以下分别详述:
HttpSessionAttributeListener
当session中的属性被添加,更改,删除时得到通知。这个接口上节讲过,主要看其它三个。

HttpSessionBindingListener
当一个实现了HttpSessionBindingListener的类被加入到HttpSession中(或从中移出)时,会产生HttpBindingEvent事件,而这些事件会被它本身接收到。
本接口定义了两个方法:
void valueBound(HttpSessionBindingEvent e);
void valueUnbound(HttpSessionBindingEvent e);
当多个实现了HttpSessionBindingListener的类被加入到HttpSession中时,各类的方法只对本类感兴趣,不会去理会其它类的加入。
即使是同一类的不同实例间,也是互不关心的(各扫门前雪)。

我们可以看到前两个接口都对HttpSessionBindingEvent事件做出反应,但机理不同。
HttpSessionAttributeListener是在web.xml中登记的,servlet容器仅创建一个实例,来为任何在session中增加属性的servlet服务。触发事件的对象是所有可以转换为Object的实例。
HttpSessionBindingListener不用在web.xml中登记,在每个servlet中用new创建实例,且仅对本实例向session中的加入(或移出)感兴趣。触发事件的对象仅仅是自己。

HttpSessionListener
对于session的创建和取消感兴趣。需要在web.xml中登记。
共有两个方法:
void sessionCreated(HttpSessionEvent se);
void sessionDestroyed(HttpSessionEvent se);
使用它我们可以容易的创建一个类来对session计数。
也许我们会简单的考虑使用sessionDestroyed方法来在session结束后做一些清理工作。但是,请注意,当这个方法被调用的时候,session已经结束了,你不能从中提取到任何信息了。因此,我们要另辟蹊径。
一种通常采用的方法是使用HttpSessionBindingListener接口。在session创建时增加一个属性,而在session结束前最后一件事将这个属性删除,这样就会触发valueUnbound方法,所有对session的清理工作可以在这个方法中实现。

HttpSessionActivationListener
当session在分布式环境中跨JVM时,实现该接口的对象得到通知。共两个方法:
void sessionDidActivate(HttpSessionEvent se);
void sessionWillPassivate(HttpSessionEvent se);


1、HTTP协议本身是“连接-请求-应答-关闭连接”模式的,是一种无状态协议(HTTP只是一个传输协议);
2、Cookie规范是为了给HTTP增加状态跟踪用的(如果要精确把握,建议仔细阅读一下相关的RFC),但不是唯一的手段;
3、所谓Session,指的是客户端和服务端之间的一段交互过程的状态信息(数据);这个状态如何界定,生命期有多长,这是应用本身的事情;
4、由于B/S计算模型中计算是在服务器端完成的,客户端只有简单的显示逻辑,所以,Session数据对客户端应该是透明的不可理解的并且应该受控于服务端;Session数据要么保存到服务端(HttpSession),要么在客户端和服务端之间传递(Cookie或url rewritting或Hidden input);
5、由于HTTP本身的无状态性,服务端无法知道客户端相继发来的请求是来自一个客户的,所以,当使用服务端HttpSession存储会话数据的时候客户端的每个请求都应该包含一个session的标识(sid, jsessionid 等等)来告诉服务端;
6、会话数据保存在服务端(如HttpSession)的好处是减少了HTTP请求的长度,提高了网络传输效率;客户端session信息存储则相反;
7、客户端Session存储只有一个办法:cookie(url rewritting和hidden input因为无法做到持久化,不算,只能作为交换session id的方式,即a method of session tracking),而服务端做法大致也是一个道理:容器有个session管理器(如tomcat的org.apache.catalina.session包里面的类),提供session的生命周期和持久化管理并提供访问session数据的api;
8、使用服务端还是客户端session存储要看应用的实际情况的。一般来说不要求用户注册登录的公共服务系统(如google)采用cookie做客户端session存储(如google的用户偏好设置),而有用户管理的系统则使用服务端存储。原因很显然:无需用户登录的系统唯一能够标识用户的就是用户的电脑,换一台机器就不知道谁是谁了,服务端session存储根本不管用;而有用户管理的系统则可以通过用户id来管理用户个人数据,从而提供任意复杂的个性化服务;
9、客户端和服务端的session存储在性能、安全性、跨站能力、编程方便性等方面都有一定的区别,而且优劣并非绝对(譬如TheServerSide号称不使用HttpSession,所以性能好,这很显然:一个具有上亿的访问用户的系统,要在服务端数据库中检索出用户的偏好信息显然是低效的,Session管理器不管用什么数据结构和算法都要耗费大量内存和CPU时间;而用cookie,则根本不用检索和维护session数据,服务器可以做成无状态的,当然高效);
10、所谓的“会话cookie”简单的说就是没有明确指明有效期的cookie,仅在浏览器当前进程生命期内有效,可以被后继的Set-Cookie操作清除掉。
当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为 session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个 session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个 session id将被在本次响应中返回给客户端保存。
保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于SEEESIONID.
1、session在何时被创建
一个常见的误解是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用 HttpServletRequest.getSession(true)这样的语句时才被创建,注意如果JSP没有显示的使用 <% @page session="false"%> 关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句 HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的 session对象的来历。由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它。
2、存放在session中的对象必须是可序列化的吗
不是必需的。要求对象可序列化只是为了session能够在集群中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内存。
3、如何才能正确的应付客户端禁止cookie的可能性
对所有的URL使用URL重写,包括超链接,form的action,和重定向的URL,具体做法参见:
http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770
Instead, use the HttpServletResponse.encodeURL() method, for example:
out.println("<a href=/""     + response.encodeURL("myshop/catalog.jsp")      + "/">catalog</a>");
Calling the encodeURL() method determines if the URL needs to be rewritten, and if so, it rewrites it by including the session ID in the URL. The session ID is appended to the URL and begins with a semicolon.

In addition to URLs that are returned as a response to WebLogic Server, also encode URLs that send redirects. For example:
if (session.isNew()) response.sendRedirect (response.encodeRedirectUrl(welcomeURL));
4、开两个浏览器窗口访问应用程序会使用同一个session还是不同的session
参见第三小节对cookie的讨论,对session来说是只认id不认人,因此不同的浏览器,不同的窗口打开方式以及不同的cookie存储方式都会对这个问题的答案有影响。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/549434.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RequestDispatcher提供两个方法:forward,include有什么区别

都表示要跳转到其他资源&#xff0c;不同的是&#xff0c;如果使用forward跳转则后面的response输出则不会执行&#xff0c;而用include来跳转&#xff0c;则include的servlet执行完后&#xff0c;再返回到原来的servlet执行response的输出&#xff08;如果有&#xff09;。如&…

JDBC通过连接池链接数据库总是失败的解决办法

应用服务器&#xff1a;glassfish JDBC通过连接池链接数据库总是失败,通过查看日志&#xff0c;发现是APACHE报DHCP 错误&#xff0c; 只需要通过访问4848端口的管理程序&#xff0c;重新PING下JDBC当前连接池即可。

JSP--(使用请求转发的动作标识jsp:forward)

版权声明&#xff1a;To be or not to be, thats a question. https://blog.csdn.net/qq_32823673/article/details/79542554 </div><link rel"stylesheet" href"https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d7e2a68c7…

SQL搜索精华语句

一、 简单查询 9HW M C3k X"o hy X153092  简单的Transact-SQL查询只包括选择列表、FROM子句和WHERE子句。它们分别说明所查询列、查询的表或视图、以及搜索条件等。T%f r8\ Q"w153092  例如&#xff0c;下面的语句查询testtable表中姓名为"张三"的nic…

北大青鸟组建与维护企业网络高级技术PPT课件

北大青鸟组建与维护企业网络高级技术PPT课件主要是思科技术和一些协议又OSPF STP VTP NAT ACL PPP 三层交换等记住一定要一起解压转载于:https://blog.51cto.com/854090/171284

DB2中admin_cmd执行load

CREATE PROCEDURE ADMINISTRATOR.load_test() LANGUAGE SQLBEGINdeclare sql1 varchar(200);declare sql2 varchar(200);set sql1select * from yh.t;set sql2yh.t1;call sysproc.admin_cmd(load from (||sql1||) of cursor insert into ||sql2);END;本文来自: IXPUB技术社区(w…

计组学习笔记(一):浮点数的表示和运算

最近学习计算机组成原理&#xff0c;遇到许多疑难问题&#xff0c;接下来写一写我在学习浮点数方面知识的理解&#xff0c;在巩固的同时也方便日后的复习。一、浮点数的表示1、浮点数的表示格式浮点数&#xff0c;顾名思义&#xff0c;就是小数点不固定的数。计算机中&#xff…

映世便携音箱我对你一见钟情啦~

映世便携音箱我对你一见钟情啦~我这个人平时不眼馋别人的东西&#xff0c;是你的就是你的&#xff0c;眼馋也没有用&#xff01;但是……我第一次眼馋别人的东西居然是映世便携音箱&#xff01;大姐&#xff0c;你那个东西给我好不啦~映世便携音箱&#xff0c;我爱死你啦~那天我…

Uniform String

版权声明&#xff1a;来自星空计算机团队(QQ群&#xff1a;134826825)——申屠志刚 https://blog.csdn.net/weixin_43272781/article/details/85105113 </div><link rel"stylesheet" href"https://csdnimg.cn/release/phoenix/template/css/ck_…

李天平:职场智慧之如何提升自己在公司的价值

一个人要想在公司立足&#xff0c;成为公司不可或缺的人才&#xff0c;并得到公司的重用和青睐&#xff0c;只有让自己对公司具有更大的价值&#xff0c;那么如何提升自己在公司的价值呢&#xff1f;1&#xff0e;任务分配&#xff0c;不怕累&#xff0c;多干活任何公司、老总都…

如何得到自增id值

如何得到自增id值 如何得到SqlServer的自增ID: SqlServer中的自增的ID的最后的值: SELECT SCOPE_IDENTITY() --返回插入到同一作用域中的 IDENTITY 列内的最后一个 IDENTITY 值。SELECT IDENTITY --返回插入到当前会话中任何作用域内的最后一个 IDENTITY 列值SELECT IDENT_CU…

Python 3 语法小记(一)入门 (print 函数用法总结)

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/jcjc918/article/details/9354815 </div><link rel"stylesheet" href"https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views…

如何查看linux的版本

虽然用过些版本的LINUX系统&#xff0c;但是没有查看过具体的版本是多少来着&#xff0c;下午心血来潮&#xff0c;想查看下自己的版本&#xff0c;到网上收索了下&#xff0c;看到有一大堆命令出来&#xff0c;呵呵&#xff0c;1 最简单的一个uname -a2 cat /etc/issue …

JDBC批量Insert深度优化(有事务)

JDBC批量Insert深度优化&#xff08;有事务&#xff09;环境&#xff1a;MySQL 5.1RedHat Linux AS 5JavaSE 1.5DbConnectionBroker 微型数据库连接池测试的方案&#xff1a;执行10万次Insert语句&#xff0c;使用不同方式。A组&#xff1a;静态SQL&#xff0c;自动提交&#x…

计算机专业面试中会问到的问题

今年是2015年&#xff0c;在过去几年中&#xff0c;电面&#xff08;电话面试&#xff09;是筛选程序员职位候选人的最流行的方式。它让雇佣双方很容易互相了解对方&#xff0c;候选人不需要去未来雇主的所在地&#xff0c;面试官也不用做额外的安排。这是我介绍程序员面试问题…

ActiveBpel部署运行BPEL流程实例

本文接收使用ActiveBpel开发&#xff0c;部署和运行BPEL流程实例。本文的例子工程和服务工程请见附件。1. 安装ActiveBpel5.0.2要安装ActiveBpel5.0.2&#xff0c;需要先安装JDK1.5&#xff0c;Tomcat。注意这里是JDK1.5版本的&#xff0c;ActiveBpel5.0.2不支持JDK1.5以上的版…

如何用c语言从txt文件中读取数据

用C语言从txt文件中读取数据&#xff0c;可以使用C标准库文件自带的文件接口函数进行操作。 一、打开文件&#xff1a; FILE *fopen(const char *filename, const char *mode); 因为txt文件为文本文件&#xff0c; 所以打开时选择的mode应为"r"或者"rt"。 …

活动目录实战系列五(更改域名)

在单域环境下且没有什么服务的情况的改域名还行&#xff0c;如果网络环境比较复杂或者有其他服务&#xff0c;不建议更改。以免发生错误。在实验中由于虚拟机坏掉在这里使用了两个&#xff0c;有部分图片对不上&#xff0c;请谅解。 WIN2000域不支持域重命名域重命名并不是在域…

关于C语言中的Bool类型变量的一点看法

C语言中并没有bool类型变量。这是C中新增的系统类型。 要在C语言中使用bool类型&#xff0c;可以使用自定义的方式。 使用整型做bool类型。 typedef int bool; 或 typedef unsigned char bool; 只要是整型&#xff0c;都可以当做bool使用。 使用枚举类型做bool类型。 typedef…

Lotus Notes Domino 监控

SUM服务器监控软件对Lotus可以进行全面监控. 监控方法主要采用SNMP(lnSNMP), 它是Lotus的标准监控方法. SUM用户不需要了任何Lotus MIB的信息, 只要启用lnSNMP服务即可实现对Lotus邮件, 文档, ,数据库,Demino, 线程等的监控. 主要监控内容:邮件: 总数,错误,正在传送等,邮件大小…