這裡介紹一下:HttpClient 4.x 版本,get請求方法會自動進行重定向,而post請求方法不會自動進行重定向,這是要注意的地方。我上次發生錯誤,就是使用post提交表單登錄,當時沒有自動重定向。
1、重定向是兩個請求,轉送是一次請求,因此轉送的速度要快於重定向。
2、重定向之後地址列上的地址會發生變化,變化成第二次請求的地址,轉送之後地址列上的地址不會變化,還是第一次請求的地址。
3、轉送是伺服器行為,重定向是客戶端行為。重定向時瀏覽器上的網址改變 ,轉發是瀏覽器上的網址不變。
4、重定向是兩次request,轉送只有一次請求。
5、重新導向時的網址可以是任何網址,轉送的網址必須是本網站的網址。
這裡重點看第三條和第四條。
HTTP封包包含回應碼、回應頭和回應體。這裡只說 200 和 302. 回應碼:2xx(一般是200)。表示請求成功,然後就可以接受回應的資料。回應碼:3xx(一般為302)。 表示重定向,伺服器會要求客戶端重新傳送一個請求,伺服器會傳送一個回應頭 Location,它指定了新請求的 URL 位址。 (這裡很重要!客戶端需要通過Location 頭,取得重定向的位址。)
這裡並沒有提及請求轉發,因為請求轉送是一種伺服器端的操作,它是在伺服器內部進行操作的,所以就是一次請求(在客戶端看和普通的請求沒有區別)。而重定向不同,它是客戶端的操作,因為伺服器要求客戶端重新發送一次請求,所以重定向是兩次請求。這也解釋了為什麼重定向後請求參數會遺失,因為根本不是一次請求。 我在這裡說客戶端,不說瀏覽器,因為我們有時不一定會使用瀏覽器作為客戶端,例如爬蟲也是是一個客戶端了。
但是,對於剛開始學習的時候,或者對於普通用戶來說,似乎感覺不出來二者的區別,最多是可以發現瀏覽器地址是否改變。請求轉送瀏覽器位址不變,而重定向瀏覽器位址會變更為新的位址。 (但是在這個過程中並未體現重定向的兩個請求,這是因為瀏覽器自動幫我們進行了重定向。)
下面以Java程式設計來看看二者的區別:上面的第三條和第四條。
提供一個簡單的Servlet 類,它的功能和簡單,它會攜帶一個key 參數,如果該參數存在且值為“1”,那麼就進行請求轉發到“/dispatcher.jsp” 頁面;否則,就重定向到“redirect.jsp” 頁面。
package com.study; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/TestServlet") public class TestServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String key = request.getParameter("key"); if((key != null && key.equals("1"))) { System.out.println("请求转发:key " + key); //请求转发 request.getRequestDispatcher("/dispatcher.jsp").forward(request,response); }else { //重定向 response.sendRedirect("redirect.jsp"); System.out.println("重定向:key " + key); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
dispacher.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>请求转发</title> </head> <body> <h2>请求转发</h2> </body> </html>
redirect.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>重定向</title> </head> <body> <h2>重定向</h2> </body> </html>
我這裡的目的主要是請求轉發和重定向的存取區別,並不是比較它們二者的其它區別,所以示例很簡單。
測試請求位址:http://localhost:8080/study/TestServlet?key=1
注意:請求位址無變更。
測試請求位址:http://localhost:8080/study/TestServlet?key=2 注意:請求位址發生了變化。
這樣的話,是看不出來二者在訪問上有什麼區別的,但是看不到,不代表它們沒有區別,下面通過代碼來查看二者在訪問方式上的差異。
301 Moved Permanently(永久移動)
302 Found(發現)
303 See Other(查看其他)
307 Temporary Redirect(暫時重定向)
由於HttpClient 4.x版本會自動重定向,所以我們必須關閉自動重定向,才能追蹤重定向的過程。
在 RequestConfig 裡面設置,並設定超時時間(三個)。
//HttpClient4.3中默认允许自动重定向,导致程序中不能跟踪跳转情况。 int timeout = 10*1000; RequestConfig config = RequestConfig.custom() .setSocketTimeout(timeout) .setConnectTimeout(timeout) .setConnectionRequestTimeout(timeout) .setRedirectsEnabled(false) //关闭自动重定向,默认值为true。 .build();
然後發送請求時,設定並允許自動重定向。
//创建get请求对象 HttpGet getMethod = new HttpGet(url); //设置请求方法关闭自动重定向 getMethod.setConfig(config); //配置信息
這樣當我們訪問路徑為:http://localhost:8080/study/TestServlet?key=1
伺服器會進行請求轉發,但是這是伺服器行為,與客戶端沒有關係,所以我們不用關心,在請求正確的情況下,回應碼為200。
測試結果:
当我们访问路径为:http://localhost:8080/study/TestServlet?key=2,服务器会要求客户端进行重定向(即要求客户端请求另一个地址),这时会先收到状态码 302,当再次访问成功时状态码为 200(当然了,也许重定向不止一次,但是浏览器会对重定向次数有限制)。
如果发生了重定向,我们需要获取响应头中的 Location 字段,这里面是重定向的地址。
//读取新的 URL 地址 Header header = response.getFirstHeader("location"); String newUrl = header.getValue();
注意:重定向是可以访问服务器外的地址的,服务器内部的地址一般是相对地址,需要拼接 URL,服务器外就是绝对 URL 了。
测试结果:
package com.learn; import java.io.IOException; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpStatus; import org.apache.http.ParseException; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; public class TestRedirect { /** * 重定向是客户端操作,而请求转发是服务端操作 。 * 但是通常用户使用浏览器,并不注意二者的区别, * 这是因为浏览器自动帮我们重定向了。(当然了, * 编程还是需要注意的)。 * @throws IOException * @throws ParseException * */ public static void main(String[] args) throws ParseException, IOException { String root = "http://localhost:8080/study/"; //网站的根路径,因为重定向得到的是相对路径(服务器内部的路径) //HttpClient4.3中默认允许自动重定向,导致程序中不能跟踪跳转情况。 int timeout = 10*1000; RequestConfig config = RequestConfig.custom() .setSocketTimeout(timeout) .setConnectTimeout(timeout) .setConnectionRequestTimeout(timeout) .setRedirectsEnabled(false) //关闭自动重定向,默认值为true。 .build(); String url = "http://localhost:8080/study/TestServlet?key=1"; //请求转发。 //创建 httpclient 对象 CloseableHttpClient httpClient = HttpClients.createDefault(); //创建get请求对象 HttpGet getMethod = new HttpGet(url); getMethod.setConfig(config); //配置信息 //执行请求,得到响应信息 try (CloseableHttpResponse response = httpClient.execute(getMethod)) { HttpEntity entity = null; int statusCode = response.getStatusLine().getStatusCode(); System.out.println("返回值状态码:" + statusCode); if (statusCode == HttpStatus.SC_OK) { //获取请求转发的实体信息 entity = response.getEntity(); if (entity != null) { System.out.println(EntityUtils.toString(entity, "UTF-8")); } } else if (statusCode == HttpStatus.SC_MOVED_TEMPORARILY) { //读取新的 URL 地址 Header header = response.getFirstHeader("location"); System.out.println(header); if (header != null) { String newUrl = header.getValue(); if (newUrl != null && !newUrl.equals("")) { //使用get方法转向。 HttpGet redirectGet = new HttpGet(root+newUrl); System.out.println("重定向到新的地址:" + redirectGet.getURI()); redirectGet.setConfig(config); //发送请求,做进一步处理。。。 try (CloseableHttpResponse redirectRes = httpClient.execute(redirectGet)) { statusCode = redirectRes.getStatusLine().getStatusCode(); System.out.println("返回值状态码:" + statusCode); if (statusCode == HttpStatus.SC_OK) { //获取请求转发的实体信息 entity = redirectRes.getEntity(); if (entity != null) { System.out.println(EntityUtils.toString(entity, "UTF-8")); } } } } } } } } }
以上是如何使用Java中的httpclient進行重定向和請求轉送的比較的詳細內容。更多資訊請關注PHP中文網其他相關文章!