关于session失效时springmvc拦截器拦截ajax请求失败的问题

本文介绍了在session失效时,如何使用Spring MVC拦截器正确处理Ajax请求,避免出现success函数捕获到登录页源码的情况。关键在于拦截器中设置响应头标记,并在Ajax的complete事件中检查该标记,实现session失效时的页面跳转。同时,文章提醒了对于某些jQuery插件,需要在特定事件中加入正常的ajax请求来处理session失效问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前两天做项目在处理session失效时使用springMVC拦截器拦截ajax请求,结果发现正常请求拦截没问题,ajax请求拦截到了,可是ajax success函数捕获数据是登录页的源码,查了一下资料 ,
https://my.oschina.net/zhk/blog/323452
明白了怎么回事 具体来说ajax是用XMLHttpRequest 对象用于和服务器交换数据。它的请求头区别于正常请求头,利用它的这个特点我们在它请求时将它与正常请求区别开来,既然在拦截器中重定向会被ajax中的success函数捕获登录页源码无法跳转登录页,那么我们可以采取在拦截器中设置响应头添加session失效标记的方法,并用jquery ajax中的complete事件得到响应头中的标记,在js中添加session失效时跳转页面的处理
关于complete事件【
complete(XHR, TS)
类型:Function
请求完成后回调函数 (请求成功或失败之后均调用)。
参数: XMLHttpRequest 对象和一个描述请求类型的字符串。
这是一个 Ajax 事件。

以下是我自己测试的代码
Spring-mvc.xml配置

<mvc:interceptors>
 <mvc:interceptor>
<!--需要过滤的路径映射  -->
<mvc:mapping path="/**" />
<!—不过滤的路径映射-->
 <mvc:exclude-mapping path="/css/**"/>
 <mvc:exclude-mapping path="/fonts/**"/>
 <mvc:exclude-mapping path="/images/**"/>
 <mvc:exclude-mapping path="/js/**"/>
 <mvc:exclude-mapping path="/ueditor/**"/>
 <mvc:exclude-mapping path="/upload/**"/>
<!—自定义的拦截器注册-->
<bean class="com.rescam.interceptor.AuthInterceptor"></bean>
 </mvc:interceptor>
 </mvc:interceptors>

自定义拦截器代码

package com.rescam.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
//继承HandlerInterceptorAdapter类
public class AuthInterceptor extends HandlerInterceptorAdapter {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
String ctxPath = request.getContextPath();//获取项目名
String uri = request.getRequestURI();//获取请求资源名
String qs = request.getQueryString();//获取请求参数
String ctrlName = uri.replace(ctxPath + "/", "");//去掉请求资源名中的项目名
Object user = session.getAttribute("manager");
/* 
 此处逻辑是先判断session是否失效
 然后排除登录页
 接着根据请求头判断是正常请求还是ajax请求
*/
if (user == null) {
//注:此处排除登录页的逻辑处理针对我测试的项目,不是固定的(根据项目实际情况灵活处理)
   if((qs==null&& !ctrlName.equalsIgnoreCase("manger/login")) ||
     (qs != null &&!qs.equalsIgnoreCase("url=login"))) {
     if (request.getHeader("x-requested-with") != null &&
         request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
                    response.setHeader("sessionstatus", "timeout");//设置session失效时的响应头标记
                } else {
                    response.sendRedirect(ctxPath + "/page/show?url=login");
                }
                return false;
            }
        }
        return true;
    }
}

jquery ajax请求中需要加上

$.ajax({
    url : basePath+'/colorScheme/deletes',
    type : 'post',
    data : {
                'colorSchemeIds' : dels
                },
                dataType : 'json',
                success : function(data) {
                //此处在session失效时ajax请求被拦截器拦截到后 返回的是一个响应头
                //同时success回调函数依然会执行 只不过此时data是 null 因此我在此加上if 
                //防止session失效时执行下面程序时报错
                if(data && data != null){
                if (data.success) {
                    dt.ajax.reload(null, false);
                 }
            }
    },
complete : function (XMLHttpRequest, textStatus) {
 //使用XMLHttpRequest对象获取session失效响应头标记       
           var sessionstatus = XMLHttpRequest.getResponseHeader("sessionstatus");                                                                              if(sessionstatus=="timeout"){
          //跳转登录页   
        window.location.replace(basePath + "/page/show?url=login");
                                  }
                            },
                                error : function(){
                                    alertMsg("请求失败!");
                                }
                            });
                });

经过测试 ,在session失效时 jquery ajax请求成功跳转登录页


注:对于 .post() . p o s t ( ) 、 .get()需要特别处理一下
以下摘自
http://www.css88.com/jqapi-1.9/jQuery.post/
从 jQuery 1.5开始,success回调函数还传递一个“jqXHR”对象 ( 在 jQuery 1.4中 ,它传递的是XMLHttpRequest对象)。用 POST 获取的页面是从来不会被缓存, 所以这些请求中的 cache 和 ifModified 选项在 jQuery.ajaxSetup() 是无效的。
The jqXHR Object(jqXHR 对象)

从jQuery 1.5开始,所有jQuery的Ajax方法都返回一个XMLHTTPRequest对象的超集。这个通过 .post()jQueryXHRjqXHRPromise使PromiseDeferredjqXHR.done()(),jqXHR.fail()(),jqXHR.always()(,jQuery1.6)jqXHRObject . p o s t ( ) 方 法 返 回 的 j Q u e r y X H R 对 象 , 或 “ j q X H R ” , 实 现 了 P r o m i s e 接 口 , 使 它 拥 有 P r o m i s e 的 所 有 属 性 , 方 法 和 行 为 ( 见 D e f e r r e d 对 象 获 取 更 多 信 息 ) 。 j q X H R . d o n e ( ) ( 表 示 成 功 ) , j q X H R . f a i l ( ) ( 表 示 错 误 ) , 和 j q X H R . a l w a y s ( ) ( 表 示 完 成 , 无 论 是 成 功 或 错 误 ; 在 j Q u e r y 1.6 中 添 加 ) 方 法 接 受 一 个 函 数 参 数 , 用 来 请 求 终 止 时 被 调 用 。 关 于 这 个 函 数 接 收 参 数 的 详 细 信 息 , 请 参 阅 j q X H R O b j e c t 文 档 中 的 .ajax() 章节。
Promise 接口也允许jQuery的Ajax方法, 包括 $.get(), 在一个单独的请求中关联到 .done(), .fail(), 和 .always() 回调函数, 甚至允许你在请求已经结束后,指派回调函数。如果该请求已经完成,则回调函数会被立刻调用。

var jqxhr = $.post("example.php", function() {
      alert("success");
    })
    .success(function() { alert("second success"); })
    .error(function() { alert("error"); })
    .complete(function() { alert("complete"); });

    // perform other work here ...

    // Set another completion function for the request above
    jqxhr.complete(function(){ alert("second complete"); });

jqXHR.success(), jqXHR.error(), 和 jqXHR.complete() 回调方法 在jQuery 1.5中引进, 在jQuery 1.8中不赞成使用,已经过时。他们最终将被取消(移除),你的代码应该为此做好准备, 从jQuery 3.0开始被删除,你可以使用 jqXHR.done(), jqXHR.fail(), 和 jqXHR.always() 代替.


对了 还有使用关于jquery插件,例如 jquery.Form 、 jquery.fileupload…….时session失效时发送的ajax请求不会被拦截器拦截到,这是因为这些插件已经将ajax请求封装了起来,同时进行了一些加工,已于原本的ajax请求大不相同,不过不用担心,这些插件都有一个共同特点,即都有一个在请求提交之前的事件,例如jquery.FileUpload中的add事件、jquery.Form中的beforeSubmit事件,因此只需在这些事件中加入一个正常的ajax请求即可(例如:空请求 没有任何逻辑处理 只需在此ajax请求中的complete事件中加入session 是否失效的逻辑即可 返回 true or false)


这可能只是解决这个问题的一种方法,希望大家多多分享解决各种技术问题的经验办法,不仅帮助别人,也是帮助自己加深对于这个问题的理解和提高解决问题的能力。只有付出你才能拥有更多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值