下面我就为大家带来一篇完美解决ajax访问遇到session失效的问题。现在就分享给大家,也给大家做个参考。
最近由于一个项目,模块切换为ajax请求数据,当session失效后,ajax请求后没有返回值,只有响应的html:100db36a723c770d327fc0aef2ce13b1cbcabc09e924becb49144e0c3123329dwindow.open('http://192.168.0.118:8080/welcomeaction/loginui.do','_top');2cacc6d41bbb37262a98f745aa00fbf073a6ac4ed44ffec12cee46588e518a5e
现在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(拦截器)来拦截权限问题。
拦截器部分代码:
public string intercept(actioninvocation invocation) throws exception {
// todo auto-generated method stub
actioncontext ac = invocation.getinvocationcontext();
httpservletrequest request = (httpservletrequest) ac.get(strutsstatics.http_request);
string requesttype = request.getheader("x-requested-with");
system.out.println("+++++++++++++++++++++++reqesttype:"+requesttype);
httpservletresponse response = (httpservletresponse) ac.get(strutsstatics.http_response);
// string basepath = request.getcontextpath();
string path = request.getcontextpath();
string basepath = request.getscheme()+"://"+request.getservername()+":"+request.getserverport()+path;
//获取session
map session = ac.getsession();
//判断session是否存在及session中的user信息是否存在,如果存在不用拦截
if(session != null && session.get(constants.fe_session_bg_user) != null && session.get(constants.fe_session_bg_auth) != null){
system.out.println(invocation.getproxy().getactionname()+"++++++++++++++++++++++++");
system.out.println("namespace:"+invocation.getproxy().getnamespace());
//访问路径
string visiturl = invocation.getproxy().getnamespace() + "/" + invocation.getproxy().getactionname() + constants.fe_struts_action_extension;
visiturl = visiturl.substring(1);
map<string , object> authmap = (map<string, object>) session.get(constants.fe_session_bg_auth);
map<integer, string> actionmap = (map<integer, string>) authmap.get(constants.fe_bg_actionmap);
if(actionmap != null && !actionmap.isempty() && visiturl != null){
if (actionmap.containsvalue(visiturl)) {
system.out.println(visiturl+"-----------------------");
return invocation.invoke();
} else{
string forbidden = basepath + constants.fe_bg_forbidden;
response.sendredirect(forbidden);
return null;
}
}
return invocation.invoke();
}else{
if(stringutils.isnotblank(requesttype) && requesttype.equalsignorecase("xmlhttprequest")){
response.setheader("sessionstatus", "timeout");
response.senderror(518, "session timeout.");
return null;
}else {
string actionname = invocation.getproxy().getactionname();
system.out.println(actionname);
//如果拦截的actionname是loginui或login,则不做处理,否则重定向到登录页面
if (stringutils.isnotblank(actionname) && actionname.equals(constants.fe_bg_loginui)) {
return invocation.invoke();
}else if(stringutils.isnotblank(actionname) && actionname.equals(constants.fe_bg_login)){
return invocation.invoke();
}else{
string login = basepath + "/" + constants.fe_bg_login_namespace + "/" + constants.fe_bg_loginui + constants.fe_struts_action_extension;
// system.out.println("+++++++++++++++++++++++++++basepath:"+basepath);
// response.sendredirect(login);
printwriter out = response.getwriter();
// out.println("<html>");
// out.println("<script>");
// out.println("window.open ('"+login+"','_top');");
// out.println("</script>");
// out.println("</html>");
out.write("<html><script type='text/javascript'>window.open('"+login+"','_top');</script></html>");
return null;
}
}
}
}
由上面代码可以看出,当session验证失败(即session超时)后,我们通过httpservletrequest取得请求头信息x-requested-with的值,如果不为空且等于xmlhttprequest,那么就说明此次请求是ajax请求,我们作出的反应就是向响应中添加一条头信息(自定义)并且使响应对象httpservletresponse返回服务器错误信息(518状态是自己随便定义的);这些信息都会被javascript接收,那么下面的工作就要将由javascript代码了。
javascript代码
$.ajaxsetup方法是来设置ajax请求默认选项的,我们可以认为是全局的选项设置,因此可以将这段代码提到外部js文件中,在需要的页面引用。
/**
* 设置未来(全局)的ajax请求默认选项
* 主要设置了ajax请求遇到session过期的情况
*/
$.ajaxsetup({
type: 'post',
complete: function(xhr,status) {
var sessionstatus = xhr.getresponseheader('sessionstatus');
if(sessionstatus == 'timeout') {
var top = gettopwinow();
var yes = confirm('由于您长时间没有操作, session已过期, 请重新登录.');
if (yes) {
top.location.href = '/skynk/index.html';
}
}
}
});
/**
* 在页面中任何嵌套层次的窗口中获取顶层窗口
* @return 当前页面的顶层窗口对象
*/
function gettopwinow(){
var p = window;
while(p != p.parent){
p = p.parent;
}
return p;
}
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
ajax内部值外部调用不了的原因及解决方法
使用nginx 反向代理来避免 ajax 跨域请求的方法
全面解析ajax综合应用
以上就是完美解决ajax访问遇到session失效的问题的详细内容。