ホームページ  >  記事  >  Java  >  Java で httpclient を使用してリダイレクトとリクエスト転送を比較する方法

Java で httpclient を使用してリダイレクトとリクエスト転送を比較する方法

PHPz
PHPz転載
2023-04-21 23:43:07997ブラウズ

ここで紹介します: HttpClient 4.x バージョンでは、get リクエスト メソッドは自動的にリダイレクトされますが、post リクエスト メソッドは自動的にリダイレクトされません。これは注意が必要です。最後にエラーが発生したのは、ログインするためのフォームを送信するために post を使用したときでしたが、その時は自動リダイレクトがありませんでした。

リクエスト転送とリダイレクトの違い

1. リダイレクトは 2 つのリクエスト、転送は 1 つのリクエストであるため、転送速度はリダイレクトよりも高速です。

2. リダイレクト後、アドレス バーのアドレスは 2 回目に要求されたアドレスに変更されますが、転送後もアドレス バーのアドレスは変更されず、最初に要求されたアドレスのままになります。

3. 転送はサーバーの動作であり、リダイレクトはクライアントの動作です。リダイレクトの場合、ブラウザ上の URL は変更されますが、転送の場合、ブラウザ上の URL は変更されません。

4. リダイレクトは 2 つのリクエストですが、転送は 1 つのリクエストだけです。

5. リダイレクト時の URL は任意の URL にすることができ、転送される URL はこのサイトの URL である必要があります。

ここでは 3 番目と 4 番目の項目に焦点を当てます。

HTTP メッセージには、応答コード、応答ヘッダー、および応答本文が含まれます。ここでは 200 と 302 のみが記載されています。応答コード: 2xx (通常は 200)。リクエストが成功し、応答データを受け入れることができることを示します。応答コード: 3xx (通常は 302)。 はリダイレクトを示します。サーバーはクライアントにリクエストの再送信を要求します。サーバーは、新しいリクエストの URL アドレスを指定する応答ヘッダー Location を送信します。 (これは非常に重要です! クライアントは、Location ヘッダーを通じてリダイレクトされたアドレスを取得する必要があります。 )

リクエストの転送はサーバーであるため、ここではリクエストの転送については言及されていません。 -side 操作はサーバー内で実行されるため、リクエストになります (クライアント上の通常のリクエストと変わりません)。リダイレクトは異なります。これはクライアント操作です。サーバーはクライアントにリクエストの再送信を要求するため、リダイレクトは 2 つのリクエストになります。これは、リクエストがまったくリクエストではないため、リダイレクト後にリクエスト パラメータが失われる理由も説明します。 ここではブラウザではなくクライアントについて話していますが、場合によっては必ずしもブラウザをクライアントとして使用するとは限らないためです。たとえば、クローラーもクライアントです。

しかし、学び始めたばかりの人や一般のユーザーにとっては、両者の違いが実感できないようで、せいぜいブラウザのアドレスが変わったかどうかがわかる程度です。 。リクエストを転送するブラウザのアドレスは変更されませんが、リダイレクトするブラウザのアドレスは新しいアドレスに変更されます。 (ただし、リダイレクトされた 2 つのリクエストはこのプロセスには反映されません。これは、ブラウザーが自動的にリダイレクトするためです。)

Java プログラミングを使用した 2 番目のリクエストを見てみましょう。の間:

上記の 3 番目と 4 番目の項目

Java Web パーツ

TestServlet クラス

単純なサーブレット クラス、その機能と単純さを提供します。パラメータが存在し、値が " の場合、キー パラメータを運びます。 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>

Start project test

ここでの主な目的は、リクエストの転送とリダイレクトの違いにアクセスすることです。 、それらの間の他の違いを比較していないため、例は非常に単純です。

テスト リクエスト アドレス: http://localhost:8080/study/TestServlet?key=1

注: リクエスト アドレスは変更されていません。

Java で httpclient を使用してリダイレクトとリクエスト転送を比較する方法

テスト リクエスト アドレス: http://localhost:8080/study/TestServlet?key=2 注: リクエスト アドレス何かが変わりました。

Java で httpclient を使用してリダイレクトとリクエスト転送を比較する方法

この場合、2 つのアクセスに違いは見られませんが、見えないからといって、違いがあるわけではありません。両者に違いはありませんので、以下のコードを使用して、両者のアクセス方法の違いを見てみましょう。

HttpClient の使用

  • 301 完全に移動されました

  • 302 見つかりました

  • 303その他を参照してください

  • 307 一時的なリダイレクト

HttpClient 4.x によるバージョンは自動的にリダイレクトされるため、追跡するには自動リダイレクトをオフにする必要があります。リダイレクトプロセス。

RequestConfig に設定し、タイムアウト (3 回) を設定します。

//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 了。

测试结果:

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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。