最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java通過httpclient比較重定向和請求轉(zhuǎn)發(fā)

 更新時間:2023年04月14日 09:41:13   作者:CrazyDragon_King  
這篇文章主要介紹了Java通過httpclient比較重定向和請求轉(zhuǎn)發(fā),HttpClient?4.x?版本,get請求方法會自動進行重定向,而post請求方法不會自動進行重定向,需要的朋友可以參考下

前言:

剛開始學(xué)習(xí)Java的web編程時,都會碰到重定向請求轉(zhuǎn)發(fā)這兩個概念,而且一般也會特別強調(diào)二者的區(qū)別。當(dāng)時,因為是剛接觸,所以也就似懂非懂的接受了,然后記得編程的時候要注意二者的區(qū)別。學(xué)習(xí)完計算機網(wǎng)絡(luò)后,對這兩個概念的理解也更加深刻了,主要是具有了網(wǎng)絡(luò)的層次概念,以及應(yīng)用層的基本知識。最近使用 httpclient,發(fā)生了一個錯誤,我請求一個網(wǎng)站地址,發(fā)現(xiàn)并沒有收到正確的響應(yīng),最后發(fā)現(xiàn)是因為發(fā)生了重定向,但是 httpclient 并沒有幫我自動重定向。發(fā)現(xiàn)這個問題還挺有趣的,所以就來再深入了解一下。

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

請求轉(zhuǎn)發(fā)和重定向的區(qū)別

1、重定向是兩次請求,轉(zhuǎn)發(fā)是一次請求,因此轉(zhuǎn)發(fā)的速度要快于重定向。

2、重定向之后地址欄上的地址會發(fā)生變化,變化成第二次請求的地址,轉(zhuǎn)發(fā)之后地址欄上的地址不會變化,還是第一次請求的地址。

3、轉(zhuǎn)發(fā)是服務(wù)器行為,重定向是客戶端行為。重定向時瀏覽器上的網(wǎng)址改變 ,轉(zhuǎn)發(fā)是瀏覽器上的網(wǎng)址不變。

4、重定向是兩次request,轉(zhuǎn)發(fā)只有一次請求。

5、重定向時的網(wǎng)址可以是任何網(wǎng)址,轉(zhuǎn)發(fā)的網(wǎng)址必須是本站點的網(wǎng)址。

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

HTTP報文包含響應(yīng)碼、響應(yīng)頭和響應(yīng)體。 這里只說 200 和 302. 響應(yīng)碼:2xx(一般是200)。表示請求成功,然后就可以接受響應(yīng)的數(shù)據(jù)。 響應(yīng)碼:3xx(一般為302)。表示重定向,服務(wù)器會要求客戶端重新發(fā)送一個請求,服務(wù)器會發(fā)送一個響應(yīng)頭 Location,它指定了新請求的 URL 地址。(這里很重要!客戶端需要通過 Location 頭,獲取重定向的地址。

這里并沒有提及請求轉(zhuǎn)發(fā),因為請求轉(zhuǎn)發(fā)是一種服務(wù)器端的操作,它是在服務(wù)器內(nèi)部進行操作的,所以就是一次請求(在客戶端看和普通的請求沒有區(qū)別)。而重定向不同,它是客戶端的操作,因為服務(wù)器要求客戶端重新發(fā)送一次請求,所以重定向是兩次請求。這也解釋了為什么重定向后請求參數(shù)會丟失,因為根本不是一次請求。我這里說客戶端,并不說瀏覽器,因為我們有時不一定會使用瀏覽器作為客戶端,比如爬蟲也是是一個客戶端了。

但是,對于剛開始學(xué)習(xí)的時候,或者對于普通用戶來說,似乎感覺不出來二者的區(qū)別,最多是可以發(fā)現(xiàn)瀏覽器地址是否改變。請求轉(zhuǎn)發(fā)瀏覽器地址不變,而重定向瀏覽器地址會變化為新的地址。(但是在這個過程中并未體現(xiàn)重定向的兩次請求,這是因為瀏覽器自動幫我們進行了重定向。)

下面以Java編程來看看二者的區(qū)別:上面的第三條和第四條

Java web 部分

TestServlet 類

提供一個簡單的 Servlet 類,它的功能和簡單,它會攜帶一個 key 參數(shù),如果該參數(shù)存在且值為 “1”,那么就進行請求轉(zhuǎn)發(fā)到 “/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("請求轉(zhuǎn)發(fā):key " + key);
			//請求轉(zhuǎn)發(fā)
			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>請求轉(zhuǎn)發(fā)</title>
</head>
<body>
<h1>請求轉(zhuǎn)發(fā)</h1>
</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>
<h1>重定向</h1>
</body>
</html>

啟動項目測試

我這里的目的主要是請求轉(zhuǎn)發(fā)和重定向的訪問區(qū)別,并不是比較它們二者的其它區(qū)別,所以示例很簡單。

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

注意:請求地址無變化。

在這里插入圖片描述

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

在這里插入圖片描述

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

使用 HttpClient

  • 301 Moved Permanently(永久移動)
  • 302 Found(發(fā)現(xiàn))
  • 303 See Other(查看其他)
  • 307 Temporary Redirect(臨時重定向)

由于 HttpClient 4.x 版本會自動重定向,所以我們必須關(guān)閉自動重定向,才能跟蹤重定向的過程。

在 RequestConfig 里面設(shè)置,并設(shè)置超時時間(三個)。

//HttpClient4.3中默認允許自動重定向,導(dǎo)致程序中不能跟蹤跳轉(zhuǎn)情況。
int timeout = 10*1000;
RequestConfig config = RequestConfig.custom()
		.setSocketTimeout(timeout)
		.setConnectTimeout(timeout)
		.setConnectionRequestTimeout(timeout)
		.setRedirectsEnabled(false)   //關(guān)閉自動重定向,默認值為true。
		.build();

然后發(fā)送請求時,設(shè)置并允許自動重定向。

//創(chuàng)建get請求對象
HttpGet getMethod = new HttpGet(url);
//設(shè)置請求方法關(guān)閉自動重定向
getMethod.setConfig(config);  //配置信息

這樣當(dāng)我們訪問路徑為:http://localhost:8080/study/TestServlet?key=1

服務(wù)器會進行請求轉(zhuǎn)發(fā),但是這是服務(wù)器行為,與客戶端沒有關(guān)系,所以我們不用關(guān)心,在請求正確的情況下,響應(yīng)碼為 200。

測試結(jié)果:

在這里插入圖片描述

當(dāng)我們訪問路徑為:http://localhost:8080/study/TestServlet?key=2,服務(wù)器會要求客戶端進行重定向(即要求客戶端請求另一個地址),這時會先收到狀態(tài)碼 302,當(dāng)再次訪問成功時狀態(tài)碼為 200(當(dāng)然了,也許重定向不止一次,但是瀏覽器會對重定向次數(shù)有限制)。

如果發(fā)生了重定向,我們需要獲取響應(yīng)頭中的 Location 字段,這里面是重定向的地址。

//讀取新的 URL 地址
Header header = response.getFirstHeader("location");
String newUrl = header.getValue();

注意:重定向是可以訪問服務(wù)器外的地址的,服務(wù)器內(nèi)部的地址一般是相對地址,需要拼接 URL,服務(wù)器外就是絕對 URL 了。

測試結(jié)果:

在這里插入圖片描述

完整測試代碼

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 {
	
	/**
	 * 重定向是客戶端操作,而請求轉(zhuǎn)發(fā)是服務(wù)端操作 。
	 * 但是通常用戶使用瀏覽器,并不注意二者的區(qū)別,
	 * 這是因為瀏覽器自動幫我們重定向了。(當(dāng)然了,
	 * 編程還是需要注意的)。
	 * @throws IOException 
	 * @throws ParseException 
	 * */
	public static void main(String[] args) throws ParseException, IOException {
		String root = "http://localhost:8080/study/";  //網(wǎng)站的根路徑,因為重定向得到的是相對路徑(服務(wù)器內(nèi)部的路徑)
		
		//HttpClient4.3中默認允許自動重定向,導(dǎo)致程序中不能跟蹤跳轉(zhuǎn)情況。
		int timeout = 10*1000;
		RequestConfig config = RequestConfig.custom()
				.setSocketTimeout(timeout)
				.setConnectTimeout(timeout)
				.setConnectionRequestTimeout(timeout)
				.setRedirectsEnabled(false)   //關(guān)閉自動重定向,默認值為true。
				.build();
		
		
		String url = "http://localhost:8080/study/TestServlet?key=1";  //請求轉(zhuǎn)發(fā)。
		
		//創(chuàng)建 httpclient 對象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		//創(chuàng)建get請求對象
		HttpGet getMethod = new HttpGet(url);
		getMethod.setConfig(config);  //配置信息
	
		//執(zhí)行請求,得到響應(yīng)信息
		try (CloseableHttpResponse response = httpClient.execute(getMethod)) {
			HttpEntity entity = null;
			int statusCode = response.getStatusLine().getStatusCode();
			System.out.println("返回值狀態(tài)碼:" + statusCode);
			if (statusCode == HttpStatus.SC_OK) {  
				//獲取請求轉(zhuǎn)發(fā)的實體信息
				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方法轉(zhuǎn)向。
						HttpGet redirectGet = new HttpGet(root+newUrl);
						System.out.println("重定向到新的地址:" + redirectGet.getURI());
						redirectGet.setConfig(config);
						//發(fā)送請求,做進一步處理。。。
						try (CloseableHttpResponse redirectRes = httpClient.execute(redirectGet)) {
							statusCode = redirectRes.getStatusLine().getStatusCode();
							System.out.println("返回值狀態(tài)碼:" + statusCode);
							if (statusCode == HttpStatus.SC_OK) {  
								//獲取請求轉(zhuǎn)發(fā)的實體信息
								entity = redirectRes.getEntity();
								if (entity != null) {
									System.out.println(EntityUtils.toString(entity, "UTF-8"));
								}
							}
						}
					}
				}
			} 
		}
	}
}

總結(jié)

剛開始學(xué)習(xí)的時候,對于知識總是一知半解,然后就開始用起來了。但是,隨著學(xué)習(xí)的深入,就會發(fā)現(xiàn)自己對與知識的理解加深了,當(dāng)然了,不斷地動手嘗試,犯錯誤才行。因為動手嘗試才會熟練,犯錯誤才會明白為什么?這樣是一個比較好地學(xué)習(xí)方式。我也是某次使用 httpclient 地時候,發(fā)現(xiàn)自己沒有考慮重定向這個問題,而且 httpclient 也沒有幫我自動重定向(POST請求方法不會自動重定向),所以這個問題,就卡住了我很長時間,因為我不知道問題到底出在哪里?最后也是在網(wǎng)上查資料解決的問題,所以就想著試著用 httpclient 加深一下自己對于重定向和請求轉(zhuǎn)發(fā)地理解。

到此這篇關(guān)于Java通過httpclient比較重定向和請求轉(zhuǎn)發(fā)的文章就介紹到這了,更多相關(guān)httpclient比較重定向和請求轉(zhuǎn)發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Java實現(xiàn)Redis多級緩存方案

    基于Java實現(xiàn)Redis多級緩存方案

    這篇文章主要介紹了Redis多級緩存方案分享,傳統(tǒng)緩存方案、多級緩存方案、JVM本地緩存,舉例說明這些方案,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-03-03
  • Java并發(fā)之Condition案例詳解

    Java并發(fā)之Condition案例詳解

    這篇文章主要介紹了Java并發(fā)之Condition案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • spring動態(tài)注冊bean?AOP失效原理解析

    spring動態(tài)注冊bean?AOP失效原理解析

    這篇文章主要為大家介紹了spring動態(tài)注冊bean使AOP失效原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • JAVA截取字符串的幾種常用方法

    JAVA截取字符串的幾種常用方法

    這篇文章主要給大家介紹了關(guān)于JAVA截取字符串的幾種常用方法, 在處理字符串的過程中有很多情況下會遇到需要截取字符串的情況,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2023-09-09
  • Java定時任務(wù):利用java Timer類實現(xiàn)定時執(zhí)行任務(wù)的功能

    Java定時任務(wù):利用java Timer類實現(xiàn)定時執(zhí)行任務(wù)的功能

    本篇文章主要介紹了利用java Timer類實現(xiàn)定時執(zhí)行任務(wù)的功能,具有一定的參考價值,有需要的可以了解一下。
    2016-11-11
  • Java使用RedisTemplate如何根據(jù)前綴獲取key列表

    Java使用RedisTemplate如何根據(jù)前綴獲取key列表

    這篇文章主要介紹了Java使用RedisTemplate如何根據(jù)前綴獲取key列表,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java final static abstract關(guān)鍵字概述

    Java final static abstract關(guān)鍵字概述

    這篇文章主要介紹了Java final static abstract關(guān)鍵字的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • java定義數(shù)組的三種類型總結(jié)

    java定義數(shù)組的三種類型總結(jié)

    下面小編就為大家?guī)硪黄猨ava定義數(shù)組的三種類型總結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • Java堆排序算法詳解

    Java堆排序算法詳解

    這篇文章主要為大家詳細介紹了Java堆排序算法的相關(guān)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • Java super關(guān)鍵字用法實戰(zhàn)案例分析

    Java super關(guān)鍵字用法實戰(zhàn)案例分析

    這篇文章主要介紹了Java super關(guān)鍵字用法,結(jié)合具體案例形式分析了java super關(guān)鍵字調(diào)用父類構(gòu)造方法、屬性及方法等相關(guān)操作技巧與注意事項,需要的朋友可以參考下
    2019-09-09

最新評論

长沙市| 翁牛特旗| 新安县| 金坛市| 牡丹江市| 阳信县| 陈巴尔虎旗| 江北区| 辉县市| 宁乡县| 汶川县| 林口县| 双柏县| 崇州市| 岗巴县| 新宾| 宜宾县| 桦南县| 涿州市| 广汉市| 香港 | 靖州| 黔江区| 井研县| 会同县| 错那县| 乌恰县| 都江堰市| 芦山县| 辉南县| 静安区| 高雄市| 司法| 威宁| 广西| 永昌县| 阆中市| 九龙坡区| 大同县| 兰州市| 宜阳县|