您的位置:首页 > 其它

不同浏览器Session使用和常见问题分析

2014-05-15 16:12 363 查看

 session跟踪机制

HTTP协议为无状态协议,对于每一个web请求,服务器是无法知道是否为同一个请求者。那么是怎么样跟踪请求的呢?



目前有两种方式。

第一种,使用cookie记录标志。浏览器是可以保存cookie信息的,在请求响应的时候,创建一个对应的cookie,记录一个编号,下次再发送请求的时候,将cookie记录的信息发送到服务器上,服务器取得这个值,就可以判断是否为同一个用户发送的请求了。



 第二种,使用URL重写。每次URL后面跟随一个参数,服务器取得这个参数,也可以判断是否为同一个用户的请求。

index.html; jsessionid=1234

 

对应用服务器来说,会先检查浏览器是否支持cookie,如果支持就采用cookie,如果不支持则自动采用URL重写,这个过程是由Servlet规范规定的,所有的Servlet容器都需要实现这样的功能,不需要人为干预。

session超时机制

当然,如果服务器一直保存session信息,用户关闭了浏览器,或者离开了网站,session信息就没有必要保存在服务器上了。怎么清理呢?

Session的超时机制就是来处理这种情况的,如果在规定的时间内,第一次请求时,服务器创建新的session,并且会记录时间,如果很长时间没有信息相同的session id信息过来,服务器会人为用户没有使用了,就自动清理掉这个对应的这个session了。

参考web.xml的配置sessiontimeout项。

JSP作用域

1、page

这个作用域是最严格的,此对象只对于它所在JSP页面是可访问的。

2、request

这个作用域的对象是在相应请求的生命周期内有效。也就是说,对象在创建它的页面内有效,以及请求被转发(forward方法)或者被包含(include方法)的页面内有效。

3、session

会话域的对象,对于参与某个客户端会话周期的所有请求,数据都是一致的。如果有多个请求操作session,可能会有多线程的问题。

比如先发送A请求,立即发送B请求:

A请求访问session,设置某一个属性的值为a。

B请求读取session,读取A设置的属性值。

如果在A响应之前B请求已经发出去了,B读取的时候A还没有设置,B读取到的值就不是a了。

4、application

这是最宽泛的作用域,application里的变量可以被所有用户共享,类似全局变量。这类对象不是线程安全的,如果多个请求试图同时修改某一个对象,那么必须对这些访问进行同步处理。  

如果用户甲的操作修改了application中的变量,用户乙访问时得到的是修改后的值。这在其他 scope中都是不会发生的,page, request, session都是完全隔离的,无论如何修改都不会影响其他人的数据。

HttpSession接口

Servlet API只是定义了一组接口和一些实现类,HttpSession就是一个接口,具体的实现类不同的servlet容器有不同的实现。

比如weblogic8里面使用的是HashTable来保存session的属性和值,而tomcat6里面则是使用ConcurrentHashMap来保存。

HttpSession常用方法:

 

getAttribute(java.lang.String name)

返回session中绑定的变量名的值,如果没有则返回null

getId()

返回jsessionId的值

invalidate()

取消当前会话,系统退出之前调用

removeAttribute(java.lang.String name)

删掉session某绑定的变量

setAttribute(java.lang.String name, java.lang.Object value)

添加对于的名称和值到session中

 

什么情况下使用session

1.  保存用户特定数据,比如用户角色,操作集合等

2.  多个不同请求之间的共享数据

什么情况下不能使用session

1.  对所有用户都可以共享的数据,比如机构列表缓存,系统某功能的配置基表等

2.  数据提交前的临时存放,可能存在数据覆盖的情况,使用request转发或使用隐藏表单

针对同一域中的操作的比较

新窗口打开方式
IE6
IE8
CTRL+N
共享session
共享session
winodw.open
共享session
共享session
链接
共享session
共享session
打开IE
新建session
共享session
创建标签页

共享session
 

对于同一用户从同一系统中同时打开多个相同的页面,此时浏览器会共享session,如果这个页面操作,服务器上有更新session对象的信息,可能会导致session信息会被覆盖。

 


举例:

       打开页面page.jsp后,输入信息,然后提交,提交时从session取key的值。

       假设某页面page.jsp每次打开之后,都会根据数据设置session。

    第一次的数据值为value1:

    session.setAttribute("key","value1");

    第二次的数据值为value2:

    session.setAttribute("key","value2");

     同时打开两个page.jsp,第一次打开之后未提交,第二次打开之后也未提交。

    此时,如果回到第一个页面,并提交,取到的key值是value2,数据有异常。

    回到第二个页面,并提交,取到的key值是value2,数据正常。

   

规避措施:

a. 禁止同一页面同时打开多次

b. a条件不满足的情况下,不使用session保存数据,考虑使用页面表单的hidden域传值,或者使用request请求转发

c. 对于GET请求,可以使用URL重写,加入参数,敏感信息需要加密不能使用

如果需要保存临时数据,该怎么办

有时候为了增加客户体验,需要在后面的页面中保留上一个页面输入的内容,例如分页显示列表,这个时候有两种做法可以选择。

A. 使用页面表单隐藏数据。将计算得到总条数,总页数,每页的数量,当前页数,开始的索引等数据放到页面表单中,当选择下一页或者上一页时,每次都将这些数据传到后台进行处理。

 B. 使用session缓存。将计算得到总条数,总页数,每页的数量,当前页数,开始的索引等数据组装成分页对象放到session中,当选择下一页或者上一页时,后台从session中获取数据,再进行处理。 

对于同一客户不同产品进行的受理,存在session数据覆盖的情况,此时就要特别注意了。如果改造成页面隐藏字段的方式确实很困难,在使用session的时候,可以对不同的产品进行拆分,使用跟产品相关的session key值,比如,可以使用保单号作为session的key,而不是使用保单对象。

代码示例:

PolicyDTO policy=new  PolicyDTO ();

session.setAttribute(“policyDTO”,policy);//会产生数据覆盖问题

session.setAttribute(policyDTO.getPolicyNo,policy);//不会产生数据覆盖问题

 

在服务退出或者受理提交之后,需要清理掉session中的数据,否则会造成垃圾数据过多,服务器内存泄露。

在IE6中,不同方式会有不同的行为,在IE8中,不同窗口共享一个会话。如果要使IE8和IE6在打开IE时,表现一致,在IE8启动参数中加入-nomerge。

对于多个不同请求之间共享的数据,如果放在session中,可能存在并发的问题。

请求响应的时间,由于网络,服务器等因素可能慢,也可能快,如果先后发送两个请求到服务器,可能后发送的请求会先响应,这时取到的值就不是期望的了。

示意图如下,和图三是有区别的,2A表示先于写之前取值,2B表示正常的情况。

 


对于这样的情况,可以使用顺序操作,设置session之后,跳转到一个新的页面,在新的页面上在去读session里面的数据。见示意图五。

模态窗口session丢失问题

在IE中使用showModalDialog方法打开一个新的窗口的时候,会创建一个新的窗口实例。如果这个实例是在新的进程中打开的,所有的cookies和session id都不能使用了,这个实例和winodw.open方法打开的实例是不一样的,也就是说showModalDialog在新进程中打开的窗口,和父窗口不共享session,这里使用的时候需要特别注意。

关于showModalDialog方法的详细描述,请参考链接文档:

在msdn上搜索 showModalDialog method

此处无法提供链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  L-LJ