Http請求狀態碼302,已得到html頁面但未跳轉?HttpServletRequest轉發/HttpServletResponse重定向後,前端頁面未跳轉?Ajax怎麼處理頁面跳轉?
- 2021 年 4 月 6 日
- 筆記
- 呦~又再寫bug呢?
論斷
出現此類錯誤,伺服器端出現問題的可能性不大,大概率是前端問題。
問題概述
事情是這樣的,我在用Java開發後端。前端頁面使用jQuery庫的 $.getJSON()
方法發送了一個Ajax請求。
添加過濾器跳轉之前前端效果正常。
但是當我在後端加上了一個判斷用戶是否已經登錄的Filter過濾器時,出現了問題!
過濾器功能很簡單:
- 用戶已經登錄:請求順利通過過濾器;
- 用戶還沒有登錄:過濾器通過請求或響應響應的對象進行跳轉。
增加過濾器後的結果:
- 登錄狀態:前端頁面依然正常顯示數據。
- 非登錄狀態:頁面既沒有顯示數據也沒有跳轉!
- 此時打開瀏覽器後台查看:
- 請求的狀態碼為302
- 瀏覽器後台已獲取到需要跳轉的頁面,但是前端當前頁面卻沒有改變
- 此時打開瀏覽器後台查看:
出錯圖(1)👇
出錯圖(2)👇
問題分析
排除問題
- 非後端的問題:
- 以前實多次使用過濾器跳轉並沒有出現問題
- 前端確實收到了跳轉頁面,只不過沒有顯示
- 通過測試排除一些其他問題:
- 具體排除了什麼不記得了
逼近真相
- 排除了後端問題後,我開始在網上搜索前端問題的解決方案(我對前端不熟悉)。
- 逐漸的我將問題鎖定在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() {}
還沒解決?評論區見~