Ajax应用中Session超时的一种解决方案

场景:一个基于Ajax技术的Web应用,采用的是多页面方式 ,每个页面内部使用Ajax实现复杂业务逻辑之间的无刷新切换,使用了Struts来实现MVC。

问题:对于Ajax请求,只有在通过用户验证无误之后才能对请求作出响应。如果用户长时间不做操作导致Session过时之后才发出请求,则此时应该跳转到出错页面,提示用户重新登录。对于非Ajax请求,可以自定义异常并针对此异常设置相应的出错页面。在用户信息验证失败的时候直接抛出此异常即可,web容器会自动捕捉到此异常并且显示出错页面;但是,对于Ajax请求,则不会如期待的那样自动跳转到出错页面。若不错特殊处理,Ajax请求的回调函数会得到意想不到的数据而导致程序出错。

分析:对于一个Ajax的应用,每一次客户端和服务器的数据交互,可以看成是在一个由客户端的XMLHttpRequest和服务器端的Servlet(这里假设用Servlet响应Ajax请求)组成的闭合管道(如图1)中进行的:

[img]https://p-blog.csdn.net/images/p_blog_csdn_net/rikuseiha/1.bmp[/img]


图1

所有从服务器端得到的数据流都会被XMLHttpRqeuest对象获得,然后由回调函数做出相应处理。
一般而言,用户登录之后,将用户信息是存放在Session中。做用户验证,其实就是检查此时Session中用户信息是否存在或者是否正确。如果在每次逻辑处理之前都去做这样的重复检查,并且检查的方法会发生改变,这样的程序既不精简还缺少可维护性。相信很少有人这么做。
比较好的做法是使用Filter(Servlet2.3之后才行)来做这样的通用检查,简单而且修改规则也很容易。Filter在应用中的作用之处如图2所示:
[img]https://p-blog.csdn.net/images/p_blog_csdn_net/rikuseiha/2.bmp[/img]

图2

另外,还可以添加具有不同功能的Filter,形成一个Filter链。
可以看到,在请求还没有到达Servlet之前,可以对请求作一些处理之后再提交给Servlet;在Servlet发出响应但还没有到达客户端之前,还可以对响应作处理。因此,作用户检查之类的工作由Filter来完成是比较合理的。
并不是说经过Filter的请求最终一定会到达Servlet。因为Filter有权操作Request和Response,所以Filter完全可以自己向客户端直接返回响应,从而中止此次交互:
[img]https://p-blog.csdn.net/images/p_blog_csdn_net/rikuseiha/3.bmp[/img]

图3

如图3所示,若是检查用户信息失败,Filter可以直接返回响应。
到这里,应该比较清楚了,在用户信息验证出错情况下,若要使得客户端能自动显示出错提示页面,应该让Ajax请求所对应的回调函数去做。
如果只是很简单的少数请求,则可以在Filter中返回出错标志,然后在回调函数中作判断进行相应的页面跳转处理。但是,对于一个复杂的应用,如果每个回调函数中都要添加这样的判断,或者服务器端定义的出错标志发生改变,则会大大降低程序的可维护性。
对于稍稍复杂的Ajax应用,一般都会使用一个共通的模块来操作Ajax的请求(比如创建跨浏览器的XMLHttpRequest对象等等)。如果能在这样的通用模块中具有可以在回调函数被调用之前获得服务器返回数据的能力,则可以做通用的出错判断,而不必修改每一个回调函数。
比如下面的这个通用模块:
function sendRequest(callback,data,method,url,async,sload,user,password)
...{
//创建XMLHttpRequest对象
var oj = createHttpRequest();
if( oj == null ) return null;
...
if(typeof callback=='object')...{
var callback_onload = callback.onload;
var callback_onbeforsetheader = callback.onbeforsetheader;
} else ...{
var callback_onload = callback;
var callback_onbeforsetheader = null;
}

oj.onload = function () ...{
callback_onload(oj);
}
...
oj.open(method, url, async, user, password);
...
oj.send(data);
}可以在callback_onload(oj); 之前添加对出错标志的判断。到此处,问题已经得到解决。
如果以后要更改出错标志或者是出错页面,则此处也要做相应的更改才行。如何能更“智能”一点呢?
既然Filter可以返回出错标志,那当然也可以返回javascript代码了!如果能在此处动态地执行一段代码,不就解决问题了吗?想到javascript的eval函数了吧!对,就是它!代码很简单:
oj.onload = function () ...{
try ...{
eval(oj.responseText);
} catch (e) ...{}

callback_onload(oj);
}如果是正常情况下返回的数据,eval函数执行后不会引起程序异常;如果是一段javascript代码,则会得到执行,客户端的Ajax调用也不要做任何修改。

返回到Filter,若是用户验证失败,并且是Ajax请求可以返回一段让页面自动跳转的javascript代码;若是普通的非Ajax请求,则可以放心地抛出异常。经过验证,在Ajax请求和非Ajax请求的情况下,二者的客户体验是相同的。对于页面跳转,其实方法很多,这里就省略代码了。
同理,如果继续添加用户权限检查等等的Filter,则可以地向客户端发出各种不同的javascript代码,很轻松实现相应的功能而客户端无需作修改。

总结:对于Ajax的请求,其数据流是封闭的,服务器发送给在客户端的数据都被XMLHttpRequest对象所获得。本文通过从Filter中发出javascript代码让其在客户端得到执行,从而可以在session过时验证用户信息失败之后,让客户端自动显示出错页面,与非Ajax请求时的客户体验相一致。对于Ajax请求,此方法进一步推广,可以直接在服务器端发出javascript让其在客户端得到执行。

PS:ajax请求在header里会多出这样的参数值对name:X-Requested-With value:XMLHttpRequest

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/owen4751076/archive/2008/07/23/2700501.aspx
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值