js--Ajax的小知識(二):處理ajax的session過期的請求


問題的產生:  

  現如今Ajax在Web項目中應用廣泛,幾乎可以說無處不在。

  有時會碰到這樣個問題:當Ajax請求遇到Session超時,應該怎么辦?

  顯而易見,傳統的頁面跳轉在此已經不適用,因為Ajax請求是XMLHTTPRequest對象發起的而不是瀏覽器,在驗證失敗后的頁面跳轉無法反應到瀏覽器中,因為服務器返回(或輸出)的信息被JavaScript(XMLHTTPRequest對象)接到了。

  那么應該怎么處理這種情況呢?

問題的解決之法:

  既然服務器返回的消息被XMLHTTPRequest對象接收,而XMLHTTPRequest對象又是在JavaScript的掌控之中,那么我們是否可以利用JavaScript來完成頁面跳轉呢?

  當然可以,而且很容易實現!但有一點,我們需要判斷一下HTTP請求是否為Ajax請求(因為AJAX請求和普通的請求需要分開處理),這又如何判斷呢?其實Ajax請求和普通的HTTP請求是不同的,這體現在HTTP請求的頭信息中,如下所示:

上面兩張圖片是用火狐的Firebug截取的,前者為Ajax請求的請求頭信息;后者是普通的HTTP請求頭信息。注意第一圖片被紅框圈起來的部分,這就是Ajax請求與普通請求不同的地方,AJAX請求頭中帶有X-Requested-With信息,其值為XMLHttpRequest,這正是我們可以利用的地方。

Javascript代碼

$.ajaxSetup方法是來設置AJAX請求默認選項的,我們可以認為是全局的選項設置,因此可以將這段代碼提到外部JS文件中,在需要的頁面引用。

/**
 * 設置未來(全局)的AJAX請求默認選項
 * 主要設置了AJAX請求遇到Session過期的情況
 */
$.ajaxSetup({
    type: 'POST',
    complete: function(xhr,status) {
        var sessionStatus = xhr.getResponseHeader('sessionstatus');
        if(sessionStatus == 'timeout') {
            var top = getTopWinow();
            var yes = confirm('由於您長時間沒有操作, session已過期, 請重新登錄.');
            if (yes) {
                top.location.href = '/skynk/index.html';            
            }
        }
    }
});

/**
 * 在頁面中任何嵌套層次的窗口中獲取頂層窗口
 * @return 當前頁面的頂層窗口對象
 */
function getTopWinow(){
    var p = window;
    while(p != p.parent){
        p = p.parent;
    }
    return p;
}

攔截器的部分代碼:

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
 * 登錄過濾器
 *  擁有Session是否失效和用戶是否登錄2個條件判斷
 *  如果是ajax請求則設置session超時
 * @author Merlin.Ma
 *
 */
public class LoginFilter implements Filter{
  private String redirectUrl = "/login.html";
  private String sessionKey = "userName";
  @Override
  public void destroy() {
  }
  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse rep = (HttpServletResponse) response;
    HttpSession session = req.getSession();
    if( session == null || session.getAttribute(sessionKey) == null){
      //如果判斷是 AJAX 請求,直接設置為session超時
      if( req.getHeader("x-requested-with") != null && req.getHeader("x-requested-with").equals("XMLHttpRequest") ) {
        rep.setHeader("sessionstatus", "timeout"); 
      } else {
        rep.sendRedirect( req.getContextPath() + redirectUrl);
      }
    }else {
      chain.doFilter(request, response);
    }   
  }
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    String url = filterConfig.getInitParameter("redirectUrl");
    String key = filterConfig.getInitParameter("sessionKey");
    redirectUrl = url == null? redirectUrl:url;
    sessionKey = key == null ? sessionKey : key ;
  }
}

由上面代碼可以看出,當Session驗證失敗(即Session超時)后,我們通過HttpServletRequest取得請求頭信息X-Requested-With的值,如果不為空且等於XMLHttpRequest,那么就說明此次請求是Ajax請求,我們作出的反應就是向響應中添加一條頭信息(自定義)並且使響應對象HttpServletResponse返回服務器錯誤信息(518狀態是自己隨便定義的);這些信息都會被JavaScript接收,那么下面的工作就要將由JavaScript代碼了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM