我使用$.post()使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery用登录页面的内容替换div元素,迫使用户的眼睛看到一个罕见的场景。

如何使用jQuery1.2.6管理Ajax调用的重定向指令?


当前回答

Try

    $(document).ready(function () {
        if ($("#site").length > 0) {
            window.location = "<%= Url.Content("~") %>" + "Login/LogOn";
        }
    });

把它放在登录页面上。如果它被加载到主页上的一个div中,它将重定向到登录页面。“#site”是位于除登录页面之外的所有页面上的div的id。

其他回答

这对我有用:

success: function(data, textStatus, xhr) {

        console.log(xhr.status);
}

一旦成功,ajax将获得浏览器从服务器获得的相同状态代码并执行它。

使用低级$.ajax()调用:

$.ajax({
  url: "/yourservlet",
  data: { },
  complete: function(xmlHttp) {
    // xmlHttp is a XMLHttpRquest object
    alert(xmlHttp.status);
  }
});

尝试此操作进行重定向:

if (xmlHttp.code != 200) {
  top.location.href = '/some/other/page';
}

让我再次引用@Steg描述的问题

我有一个和你类似的问题。我执行一个ajax请求可能的响应:将浏览器重定向到新页面将当前页面上的现有HTML表单替换为新的一

IMHO这是一个真正的挑战,必须正式扩展到当前的HTTP标准。

我相信新的Http标准将使用新的状态代码。意思:目前301/302告诉浏览器去把这个请求的内容取到一个新的位置。

在扩展标准中,它会说如果响应状态为:308(只是一个示例),那么浏览器应该将主页重定向到提供的位置。

话虽如此;我倾向于模仿这种未来的行为,因此当需要document.redirect时,我让服务器响应如下:

status: 204 No Content
x-status: 308 Document Redirect
x-location: /login.html

当JS获得“status:204”时,它检查x-status:308标头的存在,并将document.redirect指向位置标头中提供的页面。

这对你有意义吗?

您还可以钩住XMLHttpRequest发送原型。这将使用一个处理程序处理所有发送(jQuery/dojo/etc)。

我编写这段代码是为了处理一个500页的过期错误,但它应该可以捕获200个重定向。准备好有关readyState含义的XMLHttpRequest onreadystatechange上的维基百科条目。

// Hook XMLHttpRequest
var oldXMLHttpRequestSend = XMLHttpRequest.prototype.send;

XMLHttpRequest.prototype.send = function() {
  //console.dir( this );

  this.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 500 && this.responseText.indexOf("Expired") != -1) {
      try {
        document.documentElement.innerHTML = this.responseText;
      } catch(error) {
        // IE makes document.documentElement read only
        document.body.innerHTML = this.responseText;
      }
    }
  };

  oldXMLHttpRequestSend.apply(this, arguments);
}

后端弹簧@ExceptionHandler。

400和业务相关异常的错误字符串(将在弹出窗口中显示)302和用于浏览器请求的应用程序异常的错误/登录页面的位置标头(由浏览器自动重定向)500/400和错误/登录页面的位置头,用于通过ajax回调重定向ajax请求

通过用户会话将异常详细信息传递到错误页

@Order(HIGHEST_PRECEDENCE)
public class ExceptionHandlerAdvise {

    private static Logger logger = LoggerFactory.getLogger(ExceptionHandlerAdvise.class);

    @Autowired
    private UserInfo userInfo;

    @ExceptionHandler(value = Exception.class)
    protected ResponseEntity<Object> handleException(Exception ex, WebRequest request) {
        HttpHeaders headers = new HttpHeaders();
        if (isBusinessException(ex)) {
            logger.warn(getRequestURL(request), ex);
            return new ResponseEntity<>(getUserFriendlyErrorMessage(ex), headers, BAD_REQUEST);
        } else {
            logger.error(getRequestURL(request), ex);
            userInfo.setLastError(ex);
            headers.add("Location", "/euc-portal/fault");
            return new ResponseEntity<>(null, headers, isAjaxRequest(request) ? INTERNAL_SERVER_ERROR : FOUND);
        }
    }
}

private boolean isAjaxRequest(WebRequest request) {
    return request.getHeader("x-requested-with") != null;
}

private String getRequestURL(WebRequest request) {
    if (request instanceof ServletWebRequest) {
        HttpServletRequest servletRequest = ((ServletWebRequest) request).getRequest();
        StringBuilder uri = new StringBuilder(servletRequest.getRequestURI());
        if (servletRequest.getQueryString() != null) {
            uri.append("?");
            uri.append(servletRequest.getQueryString());
        }
        return uri.toString();
    }
    return request.getContextPath();
}

登录手柄接口

@Service
public class LoginHandlerInterceptor implements HandlerInterceptor {

    @Autowired
    private UserInfo userInfo;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (userInfo.getPrincipal() == null && !(request.getRequestURI().contains(LOGIN_URL) || request.getRequestURI().contains(FAULT_URL) || request.getRequestURI().startsWith("/app/css"))) {
            response.addHeader("Location", LOGIN_URL);
            response.setStatus(isAjaxRequest(request) ? BAD_REQUEST.value() : FOUND.value());
            return false;
        }
        return true;
    }
}

客户端代码

$.post('/app/request', params).done(function(response) {
    ...
}).fail(function(response) {
    if (response.getResponseHeader('Location')) {
        window.top.location.href = response.getResponseHeader('Location');
        return;
    }
    alert(response);
});