client:
向server發送一個請求,要求獲取一個資源java
server:
接收到這個請求後,發現請求的這個資源實際存放在另外一個位置
因而server在返回的response header的Location字段中寫入那個請求資源的正確的URL,並設置reponse的狀態碼爲30x
client:
接收到這個response後,發現狀態碼爲重定向的狀態嗎,就會去解析到新的URL,根據新的URL從新發起請求git
重定向最經常使用爲301,也有303,github
臨時重定向用302,307瀏覽器
請求轉發服務器
服務器在處理request的過程當中將request前後委託多個servlet或jsp接替進行處理的過程,request和reponse始終在期間傳遞網絡
重定向時,客戶端發起兩次請求,而請求轉發時,客戶端只發起一次請求jsp
重定向後,瀏覽器地址欄url變成第二個url,而請求轉發沒有變(請求轉發對於客戶端是透明的)ide
流程ui
重定向:
用戶請求-----》服務器入口-------》組件------>服務器出口-------》用戶----(重定向)---》新的請求url
請求轉發
用戶請求-----》服務器入口-------》組件1---(轉發)----》組件2------->服務器出口-------》用戶
重定向
response.sendRedirect()
請求轉發
在Servlet裏,實現dispatch是經過RequestDispatchers來實現的,這個類有兩個方法:forward,include
JSP裏實現dispatch的標籤也有兩個:jsp:forward和jsp:include
讀取到響應狀態碼爲30x時,拿到重定向的url,用這個url置換掉request中的原url
對request的一些header,body分狀況進行處理
從新執行這個request,發出請求
在RetryAndFollowUpInterceptor的intercept方法中構建了while (true)循環,循環內部:
int responseCode = userResponse.code();
而後switch (responseCode)進行判斷:
將前一步獲得的followUp 賦值給request,從新進入循環,
@Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); ... while (true) { if (canceled) { streamAllocation.release(); throw new IOException("Canceled"); } Response response = null; boolean releaseConnection = true; try { response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);//執行網絡請求 releaseConnection = false; ... Request followUp = followUpRequest(response);//拿到重定向的request if (followUp == null) { if (!forWebSocket) { streamAllocation.release(); } return response;//若是不是重定向,就返回response } ... if (++followUpCount > MAX_FOLLOW_UPS) {//有最大次數限制20次 streamAllocation.release(); throw new ProtocolException("Too many follow-up requests: " + followUpCount); } request = followUp;//把重定向的請求賦值給request,以便再次進入循環執行 priorResponse = response; } }
重定向功能默認是開啓的,能夠選擇關閉,而後去實現本身的重定向功能:
new OkHttpClient().newBuilder() .followRedirects(false) //禁制OkHttp的重定向操做,咱們本身處理重定向 .followSslRedirects(false)//https的重定向也本身處理