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的重定向也本身处理