ajax访问遇到Session失效问题
2015-06-11 13:14
423 查看
最近由于一个项目,模块切换为ajax请求数据,当Session失效后,ajax请求后没有返回值,只有响应的html:<html><scripttype='text/javascript'>window.open('http://192.168.0.118:8080/welcomeAction/loginUI.do','_top');</script></html>
现在Ajax在Web项目中应用广泛,几乎可以说无处不在,这就带来另外一个问题:当Ajax请求遇到Session超时,应该怎么办?
显而易见,传统的页面跳转在此已经不适用,因为Ajax请求是XMLHTTPRequest对象发起的而不是浏览器,在验证失败后的页面跳转无法反应到浏览器中,因为服务器返回(或输出)的信息被JavaScript(XMLHTTPRequest对象)接到了。
那么应该怎么处理这种情况呢?
当然可以,而且很容易实现!但有一点,我们需要判断一下HTTP请求是否为Ajax请求(因为AJAX请求和普通的请求需要分开处理),这又如何判断呢?其实Ajax请求和普通的HTTP请求是不同的,这体现在HTTP请求的头信息中,如下所示:
上面两张图片是用火狐的Firebug截取的,前者是普通的HTTP请求头信息;后者为Ajax请求的请求头信息。注意第一图片被红框圈起来的部分,这就是Ajax请求与普通请求不同的地方,AJAX请求头中带有X-Requested-With信息,其值为XMLHttpRequest,这正是我们可以利用的地方。
下面看一下代码如何实现。
Interceptor过滤器
在使用Struts2时,我们一般使用Interceptor(拦截器)来拦截权限问题。
拦截器部分代码:
ViewCode
由上面代码可以看出,当Session验证失败(即Session超时)后,我们通过HttpServletRequest取得请求头信息X-Requested-With的值,如果不为空且等于XMLHttpRequest,那么就说明此次请求是Ajax请求,我们作出的反应就是向响应中添加一条头信息(自定义)并且使响应对象HttpServletResponse返回服务器错误信息(518状态是自己随便定义的);这些信息都会被JavaScript接收,那么下面的工作就要将由JavaScript代码了。
ViewCode
注册一个典型使用
以下的情况下:
当自定义选项,需要提前处理,预过滤器(Prefilters)是一个完美的选择。给定下面的代码,例如,如果自定义
handler
类型:Function(Eventevent,jqXHRjqXHR,PlainObjectajaxOptions
)
被调用的函数。
每当一个Ajax请求完成,jQuery就会触发
百流积聚,江河是也;文若化风,可以砾石。
现在Ajax在Web项目中应用广泛,几乎可以说无处不在,这就带来另外一个问题:当Ajax请求遇到Session超时,应该怎么办?
显而易见,传统的页面跳转在此已经不适用,因为Ajax请求是XMLHTTPRequest对象发起的而不是浏览器,在验证失败后的页面跳转无法反应到浏览器中,因为服务器返回(或输出)的信息被JavaScript(XMLHTTPRequest对象)接到了。
那么应该怎么处理这种情况呢?
方法
既然服务器返回的消息被XMLHTTPRequest对象接收,而XMLHTTPRequest对象又是在JavaScript的掌控之中,那么我们是否可以利用JavaScript来完成页面跳转呢?当然可以,而且很容易实现!但有一点,我们需要判断一下HTTP请求是否为Ajax请求(因为AJAX请求和普通的请求需要分开处理),这又如何判断呢?其实Ajax请求和普通的HTTP请求是不同的,这体现在HTTP请求的头信息中,如下所示:
上面两张图片是用火狐的Firebug截取的,前者是普通的HTTP请求头信息;后者为Ajax请求的请求头信息。注意第一图片被红框圈起来的部分,这就是Ajax请求与普通请求不同的地方,AJAX请求头中带有X-Requested-With信息,其值为XMLHttpRequest,这正是我们可以利用的地方。
下面看一下代码如何实现。
Interceptor过滤器
在使用Struts2时,我们一般使用Interceptor(拦截器)来拦截权限问题。
拦截器部分代码:
1publicStringintercept(ActionInvocationinvocation)throwsException{ 2//TODOAuto-generatedmethodstub 3ActionContextac=invocation.getInvocationContext(); 4HttpServletRequestrequest=(HttpServletRequest)ac.get(StrutsStatics.HTTP_REQUEST); 5StringrequestType=request.getHeader("X-Requested-With"); 6System.out.println("+++++++++++++++++++++++reqestType:"+requestType); 7HttpServletResponseresponse=(HttpServletResponse)ac.get(StrutsStatics.HTTP_RESPONSE); 8//StringbasePath=request.getContextPath(); 9Stringpath=request.getContextPath(); 10StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path; 11//获取session 12Mapsession=ac.getSession(); 13//判断session是否存在及session中的user信息是否存在,如果存在不用拦截 14if(session!=null&&session.get(Constants.FE_SESSION_BG_USER)!=null&&session.get(Constants.FE_SESSION_BG_AUTH)!=null){ 15System.out.println(invocation.getProxy().getActionName()+"++++++++++++++++++++++++"); 16System.out.println("namespace:"+invocation.getProxy().getNamespace()); 17//访问路径 18StringvisitURL=invocation.getProxy().getNamespace()+"/"+invocation.getProxy().getActionName()+Constants.FE_STRUTS_ACTION_EXTENSION; 19visitURL=visitURL.substring(1); 20Map<String,Object>authMap=(Map<String,Object>)session.get(Constants.FE_SESSION_BG_AUTH); 21Map<Integer,String>actionMap=(Map<Integer,String>)authMap.get(Constants.FE_BG_ACTIONMAP); 22if(actionMap!=null&&!actionMap.isEmpty()&&visitURL!=null){ 23if(actionMap.containsValue(visitURL)){ 24System.out.println(visitURL+"-----------------------"); 25returninvocation.invoke(); 26}else{ 27Stringforbidden=basePath+Constants.FE_BG_FORBIDDEN; 28response.sendRedirect(forbidden); 29returnnull; 30} 31} 32returninvocation.invoke(); 33}else{ 34if(StringUtils.isNotBlank(requestType)&&requestType.equalsIgnoreCase("XMLHttpRequest")){ 35response.setHeader("sessionstatus","timeout"); 36response.sendError(518,"sessiontimeout."); 37returnnull; 38}else{ 39 40StringactionName=invocation.getProxy().getActionName(); 41System.out.println(actionName); 42//如果拦截的actionName是loginUI或login,则不做处理,否则重定向到登录页面 43if(StringUtils.isNotBlank(actionName)&&actionName.equals(Constants.FE_BG_LOGINUI)){ 44returninvocation.invoke(); 45}elseif(StringUtils.isNotBlank(actionName)&&actionName.equals(Constants.FE_BG_LOGIN)){ 46returninvocation.invoke(); 47}else{ 48Stringlogin=basePath+"/"+Constants.FE_BG_LOGIN_NAMESPACE+"/"+Constants.FE_BG_LOGINUI+Constants.FE_STRUTS_ACTION_EXTENSION; 49//System.out.println("+++++++++++++++++++++++++++basePath:"+basePath); 50//response.sendRedirect(login); 51PrintWriterout=response.getWriter(); 52//out.println("<html>"); 53//out.println("<script>"); 54//out.println("window.open('"+login+"','_top');"); 55//out.println("</script>"); 56//out.println("</html>"); 57out.write("<html><scripttype='text/javascript'>window.open('"+login+"','_top');</script></html>"); 58returnnull; 59} 60} 61} 62 63}
ViewCode
由上面代码可以看出,当Session验证失败(即Session超时)后,我们通过HttpServletRequest取得请求头信息X-Requested-With的值,如果不为空且等于XMLHttpRequest,那么就说明此次请求是Ajax请求,我们作出的反应就是向响应中添加一条头信息(自定义)并且使响应对象HttpServletResponse返回服务器错误信息(518状态是自己随便定义的);这些信息都会被JavaScript接收,那么下面的工作就要将由JavaScript代码了。
Javascript代码
$.ajaxSetup方法是来设置AJAX请求默认选项的,我们可以认为是全局的选项设置,因此可以将这段代码提到外部JS文件中,在需要的页面引用。1/** 2*设置未来(全局)的AJAX请求默认选项 3*主要设置了AJAX请求遇到Session过期的情况 4*/ 5$.ajaxSetup({ 6type:'POST', 7complete:function(xhr,status){ 8varsessionStatus=xhr.getResponseHeader('sessionstatus'); 9if(sessionStatus=='timeout'){ 10vartop=getTopWinow(); 11varyes=confirm('由于您长时间没有操作,session已过期,请重新登录.'); 12if(yes){ 13top.location.href='/skynk/index.html'; 14} 15} 16} 17}); 18 19/** 20*在页面中任何嵌套层次的窗口中获取顶层窗口 21*@return当前页面的顶层窗口对象 22*/ 23functiongetTopWinow(){ 24varp=window; 25while(p!=p.parent){ 26p=p.parent; 27} 28returnp; 29}
ViewCode
注册一个典型使用
$.ajaxPrefilter()的预过滤器,看起来像这样:
1 2 3 | $.ajaxPrefilter(function(options,originalOptions,jqXHR){ //Modifyoptions,controloriginalOptions,storejqXHR,etc }); |
options是请求的选项
originalOptions值作为提供给Ajax方法未经修改的选项,因此,没有
ajaxSettings设置中的默认值
jqXHR是请求的jqXHR对象
当自定义选项,需要提前处理,预过滤器(Prefilters)是一个完美的选择。给定下面的代码,例如,如果自定义
abortOnRetry选项被设置为
true,那么调用
$.ajax()会自动中止请求相同的URL:
1 2 3 4 5 6 7 8 9 10 | varcurrentRequests={}; $.ajaxPrefilter(function(options,originalOptions,jqXHR){ if(options.abortOnRetry){ if(currentRequests[options.url]){ currentRequests[options.url].abort(); } currentRequests[options.url]=jqXHR; } }); |
.ajaxComplete(handler)
handler类型:
)
被调用的函数。
每当一个Ajax请求完成,jQuery就会触发
ajaxComplete事件,在这个时间点所有处理函数会使用
.ajaxComplete()方法注册并执行。
百流积聚,江河是也;文若化风,可以砾石。
相关文章推荐
- android performClick使用
- kickstart
- 遍历二叉树,利用栈和只用固定存储空间,递归和非递归。
- SAT数学:基本词汇小结(代数)
- Java编程思想_笔记(一)
- tokumx经营报表
- 使用线程安全的单例模式HttpClient,及HttpClient和Application的融合
- STL 容器的选择总结
- iOS多线程开发(一)
- MR WordCount类基本解析
- 启动虚拟机网卡
- Windows简单窗口的创建
- IntelliJ IDEA使用技巧一览表
- SQLSERVER2008 连接 MYSQL
- 常用vimrc脚本
- 40 Key Computer Science Concepts Explained In Layman’s Terms
- ExtJs自学教程(1):从一切API开始
- android service详解
- ASCII对照表
- Android Studio 快捷键