我使用$.post()使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery用登录页面的内容替换div元素,迫使用户的眼睛看到一个罕见的场景。
如何使用jQuery1.2.6管理Ajax调用的重定向指令?
我使用$.post()使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery用登录页面的内容替换div元素,迫使用户的眼睛看到一个罕见的场景。
如何使用jQuery1.2.6管理Ajax调用的重定向指令?
当前回答
<script>
function showValues() {
var str = $("form").serialize();
$.post('loginUser.html',
str,
function(responseText, responseStatus, responseXML){
if(responseStatus=="success"){
window.location= "adminIndex.html";
}
});
}
</script>
其他回答
后端弹簧@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);
});
使用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')
});
我有一个适合我的简单解决方案,无需更改服务器代码。。。只要加一茶匙肉豆蔻。。。
$(document).ready(function ()
{
$(document).ajaxSend(
function(event,request,settings)
{
var intercepted_success = settings.success;
settings.success = function( a, b, c )
{
if( request.responseText.indexOf( "<html>" ) > -1 )
window.location = window.location;
else
intercepted_success( a, b, c );
};
});
});
我检查了html标记的存在,但您可以更改indexOf以搜索登录页面中存在的任何唯一字符串。。。
这对我有用:
success: function(data, textStatus, xhr) {
console.log(xhr.status);
}
一旦成功,ajax将获得浏览器从服务器获得的相同状态代码并执行它。
我只是想分享我的方法,因为这可能会帮助某人:
我基本上包含了一个JavaScript模块,它处理身份验证,例如显示用户名,以及本例中处理重定向到登录页面。
我的场景:我们之间基本上有一个ISA服务器,它监听所有请求,并用302和位置标头响应登录页面。
在我的JavaScript模块中,我最初的方法是
$(document).ajaxComplete(function(e, xhr, settings){
if(xhr.status === 302){
//check for location header and redirect...
}
});
问题(这里已经提到了很多)是浏览器自己处理重定向,因此我的ajaxComplete回调从未被调用,但我得到了已经重定向的Login页面的响应,这显然是状态200。问题是:如何检测成功的200响应是您实际的登录页面还是其他任意页面??
解决方案
由于无法捕获302个重定向响应,我在登录页面上添加了LoginPage标头,其中包含登录页面本身的url。在模块中,我现在侦听标头并执行重定向:
if(xhr.status === 200){
var loginPageRedirectHeader = xhr.getResponseHeader("LoginPage");
if(loginPageRedirectHeader && loginPageRedirectHeader !== ""){
window.location.replace(loginPageRedirectHeader);
}
}
…这就像魅力一样:)。你可能想知道为什么我在LoginPage头中包含url。。。基本上是因为我找不到从xhr对象自动定位重定向得到的GET url的方法。。。