欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

针对ajax请求时拦截器不跳转问题

程序员文章站 2024-02-29 18:40:40
...

前言(下面有博主符合自身案例的解决方法)


在有一次开发中,原本用的是js控制页面跳转,控制器来接收并对此请求进行拦截。

之后js模块需要增加逻辑代码,特殊要求,所以改成了ajax进行异步请求。

最后发现用ajax请求的地址在处理后拦截器并不拦截此请求,也不会进行跳转(ps:当然不会跳转了),这让我一直感觉我的拦截器地址配置写错了,进行一番查阅后,这里对这个问题进行了一些梳理

解释


ajax为异步请求,前台的逻辑最后都走ajax的回调函数,也仅走回调函数,也就是success。

只会接收后台传送过来的数据,不会对页面跳转拦截这样的请求进行处理。

解决办法


以下是经过搜索后整理的办法

使用$.ajaxSetup(),也可以理解为对ajax的增强,它会在每个ajax请求后得到执行。

// 解决Ajax异步请求 springMvc 不跳转页面的问题
$.ajaxSetup( {
	//设置ajax请求结束后的执行动作
    complete :
        function(XMLHttpRequest, textStatus) {
			// 通过XMLHttpRequest取得响应头,sessionstatus
            var sessionstatus = XMLHttpRequest.getResponseHeader("sessionstatus");
            if (sessionstatus == "TIMEOUT") {
                var win = window;
                while (win != win.top){
                    win = win.top;
                }
                win.location.href= XMLHttpRequest.getResponseHeader("CONTEXTPATH");
            }
        }
});

这段代码的含义,大抵就是,在 ajax请求完成以后,执行 complete 回调方法,里面进行一些逻辑的判断;

这里判断 session 的状态,如果是超时被销毁了,则进行页面的跳转,跳到 CONTEXTPATH 的值那 ;

session 的状态以及 CONTEXTPATH 的值,由我们后台同学定义;

如下:在拦截器的preHandle方法中,添加如下逻辑
 

HttpSession session = httpServletRequest.getSession();
        User user = (User) session.getAttribute("user");
        if (user == null) {
            // 获取到项目名,以便下面进行重定向
            String homeUrl = httpServletRequest.getContextPath();
         	// 如果是 ajax 请求,则设置 session 状态 、CONTEXTPATH 的路径值
         	// 如果是ajax请求响应头会有,x-requested-with
            if (httpServletRequest.getHeader("x-requested-with") != null && httpServletRequest.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")){
                httpServletResponse.setHeader("SESSIONSTATUS", "TIMEOUT");
                httpServletResponse.setHeader("CONTEXTPATH", homeUrl+"/index.html");
                // FORBIDDEN,forbidden。也就是禁止、403
                httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN); 
            }else{
                // 如果不是 ajax 请求,则直接跳转即可
                httpServletResponse.sendRedirect(homeUrl+"/index.html");
            }
            return false;
        }

以上的你看懂了吗,如果没有以下还有博主自己设计解决思路(情景:登录和未登录)


这是博主自己的构思,请仔细浏览,完全没有其他的技术只是解决问题的逻辑,只为实现功能,并且运行无误而设计

ajax请求没有被拦截,拦截的主要原因是因为没有登录。我们先搞明白问题卡在了哪里——首先当ajax请求时,它不会去管你需要跳转什么,它只会进入到回调函数里面,导致页面不能经过拦截器进行页面跳转。

明白了问题后,那么先妥协一下,我们先去回调函数里进行算法的逻辑运算

首先,我打印了两个json传过来的数据,发现未登录的情况下,json的数据为页面的html文本内容。而登录后,json则是正常的json数据格式返回的状态码等信息。那么如果将此数据用js的eval函数来进行转化,然后读取json里面的其中某条数据,未登录的情况下的json肯定是控制不了的,那么先从控制器的json返回数据下手。

当设置控制器的返回数据为自定义的东西的时候,我们在回调函数中调用代码每次进来的时候传的数据是否有这个自定义的数据data,有则判断是否相等,没有数据就意味着是没有登录的状态下,那么我们就可以用js调跳转页面的操作:window.location.href="";

理想很美好,现实很骨感

未登录状态下,贸然用eval进行转化成json是会出错的,因为未登录状态的json请求后的数据为html页面内容,然而页面内容并不是按照json格式来书写的,而且还有非法字符

然后,现在的新问题是,用eval函数来进行转化可能会导致js代码走到这的时候就出错不继续往下走了,从而也不会执行js跳转location。然而出错的原因是eval转化字符串数据的时候只能按照规则来,那就代表未登录状态下的返回数据并不能转化json

既然两个数据一个能转化一个不能转化,那么换个思路,可以先判断这个字符串是否可以转化为json数据类型,可以转化成json那就代表是登录状态下的,反之亦然。

这样一来代码反而更简单了

下面是判断是否为json数据类型的代码:

//判断是否可以转json类型
function isJsonString(str) {
    try {
        if (typeof JSON.parse(str) == "object") {
            return true;
        }
    } catch(e) {
    }
    return false;
}

当用上面判断后,只需要在回调函数中,简单的if判断就完事了

//ajax回调函数
"success" : function(json){
    //调用判断函数方法
	if(!isJsonString(json)){
	//不可以转json 代表是未登录状态
		window.location.href="......html";
	}
    //如果你对是登录状态下还有什么操作直接else即可
}

这样就可以直接解决ajax提交拦截器无法进行跳转的问题了,在不考虑分工合作下完成的项目中,推卸责任问题,可以一试

如有不符的地方欢迎指正,如有雷同,纯属巧合

 

附:什么是回调函数


ajax提交了一个action或do的请求,这个时候ajax是向后台请求了数据,然后后台也给了对应的数据,后台做好了该怎么给前台,这时候就有了ajax的回调函数。

回调函数是在ajax里面定义的,当请求并完成了对数据的请求时,就调用了ajax的success回调函数,把数据给ajax,然后success通过回调函数来处理这些数据

本次只针对遇到的问题进行笔记共享,如有不对或者补充的,欢迎指正。