Http请求状态码302,已得到html页面但未跳转?HttpServletRequest转发/HttpServletResponse重定向后,前端页面未跳转?Ajax怎么处理页面跳转?

直接看【问题概述】,和最后的【真·最终解决】就可以了

问题概述

事情是这样的,我在用Java开发后端。前端页面使用jQuery库的 $.getJSON() 方法发送了一个Ajax请求

添加过滤器跳转之前前端效果正常。

但是当我在后端加上了一个判断用户是否已经登录的Filter过滤器时,出现了问题!

过滤器功能很简单:

  • 用户已经登录:请求顺利通过过滤器;
  • 用户还没有登录:过滤器通过请求或响应响应的对象进行跳转。

增加过滤器后的结果:

  • 登录状态:前端页面依然正常显示数据。
  • 非登录状态:页面既没有显示数据也没有跳转!
    • 此时打开浏览器后台查看:
      • 请求的状态码为302
      • 浏览器后台已获取到需要跳转的页面,但是前端当前页面却没有改变


出错图(1)👇


出错图(2)👇


问题分析

排除问题

  • 非后端的问题:
    1. 以前实多次使用过滤器跳转并没有出现问题
    2. 前端确实收到了跳转页面,只不过没有显示
  • 通过测试排除一些其他问题:
    1. 具体排除了什么不记得了

逼近真相

  • 排除了后端问题后,我开始在网上搜索前端问题的解决方案(我对前端不熟悉)。
  • 逐渐的我将问题锁定在Ajax请求和$.getJSON()方法上。
  • 看到网上说Ajax不适合做跳转,并提供的Ajax实现跳转的方法,然而并不适合我的代码。
  • 又看到了有人说,可以在请求方法后面加上window.location='/'实现跳转,我试了,这种跳转是无差别的跳转。也就是说在登录状态下成功返回JSON数据是也是会跳转的!这显然不是我想要的结果。

到这里,答案已经十分接近了。也就是在返回JSON的时候不跳转,返回html的时候跳转。

但是当我在查怎么知道Ajax返回结果的时候卡住,没有找到满意的答案。

正在愁呢,突然就想起一件事情:也许$.getJSON()方法是是有返回值的!于是我尝试接收了这个返回值,并用consle.log()在控制台记录这个对象。果然,出现了一个包含很多信息的对象!

最终解决(假)

我分别测试了,登录状态和未登录状态下$.getJSON()方法的返回对象。在仔细对比后发现了其中的不同!

我发现这个对象有一个属性statusText:

  • ajax请求得到了正确响应时:即得到了JSON对象,statusText属性的值为"success";

  • ajax请求得到了错误响应时:即没有得到JSON对象,而是得到一个html,statusText属性的值为"parsererror"

    parser error : 分析器错误

“神秘对象”截图👇


解决方案:很简单,只要获得“神秘对象”并判断statusText属性值区别处理!

代码:不过彩笔的我还是因为不熟悉JavaScript,被JavaScript的函数执行顺序、变量作用域折磨了半天,最终狼狈的解决了问题。

  • 前端页面Ajax请求部分代码
<script>
    $(function () {
        //定义一个执行Ajax请求并能获取Ajax函数返回值的函数
        let ajaxFunction = function () {
            //发起Ajax请求,并把返回值直接return出去
            return $.getJSON("/wx/expressList.do", null, function (data) {
                //如果没有返回JSON对象,就不会执行回调函数
                //回调函数具体代码,与问题无关
                //... ...
            });
        }
        //执行上面定义的函数,并判断Ajax响应是否为json
        if (ajaxFunction().statusText !== 'success'){
            //响应结果不是json,在本例中不是json那就只能时html了!
            window.location = '/';
            //或者使用下面的语句,效果完全相同
            //window.location = '/wx/expressList.do';
        }
    })
</script>
  • 后端过滤器代码(不重要)
@WebFilter({"/wx/expressList.do", "其他请求"})
public class UserAccessFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        //判断用户是否已经登录的实现代码
        boolean isLoggedIn = ... ;
        //到这儿是判断用户是否已经
        if (isLoggedIn) {
            //用户已登录,请求通过
            filterChain.doFilter(req, resp);
        } else {
            //跳转(重定向)至登录页面
            resp.sendRedirect("/login.html");//这里使用req跳转(转发)也可以
        }
    }

    @Override
    public void destroy() {}

真·最终解决

后来又经过测试,发现上面的方法有时候行,有时候不行。

上面方法不行的原因

  • Ajax异步。因为异步导致if条件取值早于return $.getJSON(),那么if条件获取的值是总是undefined!当然也有例外,这跟编译器和执行环境等因素有关。

最终方案:

  • 换一个Ajax请求方法,苦笑~

  • 使用error回调函数来解决跳转的问题。

    //ajax请求成功回调函数
    function success(json) {
        //具体实现
    }
    
    //ajax请求失败回调函数
    function error() {
        //如果返回的是html页面,打开此页面
        window.location = "/";
        /*	等效语句
         *	window.location = url;
         */
    }
    
    $.ajax({
        type: 'get',
        url: url,
        dataType: 'json',
        success: success,
        error: error
    });
    
  • success:当ajax请求成功返回JSON对象时才会执行

  • error:当ajax请求失败时才会执行

posted @ 2021-04-06 06:22  呆炜  阅读(4504)  评论(0编辑  收藏  举报