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

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


当前回答

后端弹簧@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);
});

其他回答

如果您还想传递值,那么还可以设置会话变量和访问如:在jsp中,您可以编写

<% HttpSession ses = request.getSession(true);
   String temp=request.getAttribute("what_you_defined"); %>

然后,您可以将这个temp值存储在javascript变量中,并四处游玩

    <script>
    function showValues() {
        var str = $("form").serialize();
        $.post('loginUser.html', 
        str,
        function(responseText, responseStatus, responseXML){
            if(responseStatus=="success"){
                window.location= "adminIndex.html";
            }
        });     
    }
</script>

使用低级$.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';
}

我这样解决了这个问题:

添加一个中间件来处理响应,如果是对ajax请求的重定向,则使用重定向url将响应更改为正常响应。

class AjaxRedirect(object):
  def process_response(self, request, response):
    if request.is_ajax():
      if type(response) == HttpResponseRedirect:
        r = HttpResponse(json.dumps({'redirect': response['Location']}))
        return r
    return response

然后在ajaxComplete中,如果响应包含重定向,则它必须是重定向,因此请更改浏览器的位置。

$('body').ajaxComplete(function (e, xhr, settings) {
   if (xhr.status == 200) {
       var redirect = null;
       try {
           redirect = $.parseJSON(xhr.responseText).redirect;
           if (redirect) {
               window.location.href = redirect.replace(/\?.*$/, "?next=" + window.location.pathname);
           }
       } catch (e) {
           return;
       }
   }
}

使用statusCode选项,如下所示,重定向通常是301、302状态代码。

$.ajax({
    type: <HTTP_METHOD>,
    url:  {server.url},
    data: {someData: true},
    statusCode: {
        301: function(responseObject, textStatus, errorThrown) {
            //yor code goes here
        },
        302: function(responseObject, textStatus, errorThrown) {
            //yor code goes here
        }           
    }
})
.done(function(data){
    alert(data);
})
.fail(function(jqXHR, textStatus){
    alert('Something went wrong: ' + textStatus);
})
.always(function(jqXHR, textStatus) {
   alert('Ajax request was finished')
});