目錄
請求轉送和重定向的差異
Java web 部分
TestServlet 類別
请求转发
重定向
啟動專案測試
使用HttpClient
完整测试代码
首頁 Java java教程 如何使用Java中的httpclient進行重定向和請求轉送的比較

如何使用Java中的httpclient進行重定向和請求轉送的比較

Apr 21, 2023 pm 11:43 PM
java httpclient

這裡介紹一下:HttpClient 4.x 版本,get請求方法會自動進行重定向,而post請求方法不會自動進行重定向,這是要注意的地方。我上次發生錯誤,就是使用post提交表單登錄,當時沒有自動重定向。

請求轉送和重定向的差異

1、重定向是兩個請求,轉送是一次請求,因此轉送的速度要快於重定向。

2、重定向之後地址列上的地址會發生變化,變化成第二次請求的地址,轉送之後地址列上的地址不會變化,還是第一次請求的地址。

3、轉送是伺服器行為,重定向是客戶端行為。重定向時瀏覽器上的網址改變 ,轉發是瀏覽器上的網址不變。

4、重定向是兩次request,轉送只有一次請求。

5、重新導向時的網址可以是任何網址,轉送的網址必須是本網站的網址。

這裡重點看第三條和第四條。

HTTP封包包含回應碼、回應頭和回應體。這裡只說 200 和 302. 回應碼:2xx(一般是200)。表示請求成功,然後就可以接受回應的資料。回應碼:3xx(一般為302)。 表示重定向,伺服器會要求客戶端重新傳送一個請求,伺服器會傳送一個回應頭 Location,它指定了新請求的 URL 位址。 (這裡很重要!客戶端需要通過Location 頭,取得重定向的位址。

這裡並沒有提及請求轉發,因為請求轉送是一種伺服器端的操作,它是在伺服器內部進行操作的,所以就是一次請求(在客戶端看和普通的請求沒有區別)。而重定向不同,它是客戶端的操作,因為伺服器要求客戶端重新發送一次請求,所以重定向是兩次請求。這也解釋了為什麼重定向後請求參數會遺失,因為根本不是一次請求。 我在這裡說客戶端,不說瀏覽器,因為我們有時不一定會使用瀏覽器作為客戶端,例如爬蟲也是是一個客戶端了。

但是,對於剛開始學習的時候,或者對於普通用戶來說,似乎感覺不出來二者的區別,最多是可以發現瀏覽器地址是否改變。請求轉送瀏覽器位址不變,而重定向瀏覽器位址會變更為新的位址。 (但是在這個過程中並未體現重定向的兩個請求,這是因為瀏覽器自動幫我們進行了重定向。)

下面以Java程式設計來看看二者的區別:上面的第三條和第四條

Java web 部分

TestServlet 類別

提供一個簡單的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 id="请求转发">请求转发</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 id="重定向">重定向</h2>
</body>
</html>
登入後複製

啟動專案測試

我這裡的目的主要是請求轉發和重定向的存取區別,並不是比較它們二者的其它區別,所以示例很簡單。

測試請求位址:http://localhost:8080/study/TestServlet?key=1

注意:請求位址無變更。

如何使用Java中的httpclient進行重定向和請求轉送的比較

測試請求位址:http://localhost:8080/study/TestServlet?key=2 注意:請求位址發生了變化。

如何使用Java中的httpclient進行重定向和請求轉送的比較

這樣的話,是看不出來二者在訪問上有什麼區別的,但是看不到,不代表它們沒有區別,下面通過代碼來查看二者在訪問方式上的差異。

使用HttpClient

  • 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。

測試結果:

如何使用Java中的httpclient進行重定向和請求轉送的比較

当我们访问路径为:http://localhost:8080/study/TestServlet?key=2,服务器会要求客户端进行重定向(即要求客户端请求另一个地址),这时会先收到状态码 302,当再次访问成功时状态码为 200(当然了,也许重定向不止一次,但是浏览器会对重定向次数有限制)。

如果发生了重定向,我们需要获取响应头中的 Location 字段,这里面是重定向的地址。

//读取新的 URL 地址
Header header = response.getFirstHeader("location");
String newUrl = header.getValue();
登入後複製

注意:重定向是可以访问服务器外的地址的,服务器内部的地址一般是相对地址,需要拼接 URL,服务器外就是绝对 URL 了。

测试结果:

如何使用Java中的httpclient進行重定向和請求轉送的比較

完整测试代码

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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

突破或從Java 8流返回? 突破或從Java 8流返回? Feb 07, 2025 pm 12:09 PM

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP與Python:了解差異 PHP與Python:了解差異 Apr 11, 2025 am 12:15 AM

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

PHP與其他語言:比較 PHP與其他語言:比較 Apr 13, 2025 am 12:19 AM

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

Java程序查找膠囊的體積 Java程序查找膠囊的體積 Feb 07, 2025 am 11:37 AM

膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4

PHP與Python:核心功能 PHP與Python:核心功能 Apr 13, 2025 am 12:16 AM

PHP和Python各有優勢,適合不同場景。 1.PHP適用於web開發,提供內置web服務器和豐富函數庫。 2.Python適合數據科學和機器學習,語法簡潔且有強大標準庫。選擇時應根據項目需求決定。

創造未來:零基礎的 Java 編程 創造未來:零基礎的 Java 編程 Oct 13, 2024 pm 01:32 PM

Java是熱門程式語言,適合初學者和經驗豐富的開發者學習。本教學從基礎概念出發,逐步深入解說進階主題。安裝Java開發工具包後,可透過建立簡單的「Hello,World!」程式來實踐程式設計。理解程式碼後,使用命令提示字元編譯並執行程序,控制台上將輸出「Hello,World!」。學習Java開啟了程式設計之旅,隨著掌握程度加深,可創建更複雜的應用程式。

PHP:許多網站的基礎 PHP:許多網站的基礎 Apr 13, 2025 am 12:07 AM

PHP成為許多網站首選技術棧的原因包括其易用性、強大社區支持和廣泛應用。 1)易於學習和使用,適合初學者。 2)擁有龐大的開發者社區,資源豐富。 3)廣泛應用於WordPress、Drupal等平台。 4)與Web服務器緊密集成,簡化開發部署。

See all articles