Apache HttpClient - 快速指南
Apache HttpClient - 概述
超文本传输协议 (HTTP) 是一种用于分布式、协作式超媒体信息系统的应用层协议。自1990年以来,它是万维网(即互联网)数据通信的基础。HTTP 是一种通用且无状态的协议,也可以使用其请求方法、错误代码和标头的扩展用于其他目的。
基本上,HTTP 是一种基于 TCP/IP 的通信协议,用于在万维网上传递数据(HTML 文件、图像文件、查询结果等)。默认端口是 TCP 80,但也可以使用其他端口。它为计算机之间以标准化方式进行通信提供了一种方法。HTTP 规范定义了客户端如何构建和发送请求数据到服务器,以及服务器如何响应这些请求。
什么是 HTTP 客户端
HTTP 客户端是一个传输库,它驻留在客户端,发送和接收 HTTP 消息。它提供最新的、功能丰富的和高效的实现,满足最新的 HTTP 标准。
此外,使用客户端库,可以构建基于 HTTP 的应用程序,例如 Web 浏览器、Web 服务客户端等。
HTTP 客户端的功能
以下是 HTTP 客户端的主要功能:
HttpClient 库实现了所有可用的 HTTP 方法。
HttpClient 库提供 API 以使用安全套接字层协议保护请求。
使用 HttpClient,您可以使用代理建立连接。
您可以使用基本、摘要、NTLMv1、NTLMv2、NTLM2 会话等身份验证方案对连接进行身份验证。
HttpClient 库支持通过多线程发送请求。它使用 **ClientConnectionPoolManager** 管理从各种线程建立的多个连接。
使用 Apache HttpClient 库,您可以设置连接超时。
Apache HttpClient - 环境设置
本章将解释如何在 Eclipse IDE 中为 HttpClient 设置环境。在继续安装之前,请确保您的系统中已安装 Eclipse。如果没有,请下载并安装 Eclipse。
有关 Eclipse 的更多信息,请参阅我们的 Eclipse 教程。
步骤 1 - 下载依赖 JAR 文件
打开 HttpClient (组件) 网站的官方 主页 并转到下载页面
然后,下载最新稳定版本的 **HttpClient**。在本教程中,我们使用的是 4.5.6 版本,因此请下载文件 **4.5.6.zip**。
在下载的文件夹中,您会找到一个名为 **lib** 的文件夹,其中包含需要添加到项目类路径中的必需 Jar 文件,以便使用 HttpClient。
步骤 2 - 创建项目并设置构建路径
打开 Eclipse 并创建一个示例项目。右键单击项目,选择 **构建路径 → 配置构建路径** 选项,如下所示。
在 **Java 构建路径** 框架的 **库** 选项卡中,单击 **添加外部 JARs**。
然后选择 lib 文件夹中的所有 jar 文件,然后单击 **应用并关闭**。
您已准备好使用 Eclipse 中的 HttpClient 库。
Apache HttpClient - HTTP GET 请求
GET 方法用于使用给定的 URI 从给定的服务器检索信息。使用 GET 的请求应该只检索数据,并且不应该对数据产生其他影响。
HttpClient API 提供了一个名为 **HttpGet** 的类,它表示 GET 请求方法。
请按照以下步骤使用 HttpClient 库发送 GET 请求
步骤 1 - 创建 HttpClient 对象
**HttpClients** 类的 **createDefault()** 方法返回一个 **CloseableHttpClient** 对象,它是 **HttpClient** 接口的基本实现。
使用此方法,创建一个 HttpClient 对象,如下所示:
CloseableHttpClient httpclient = HttpClients.createDefault();
步骤 2 - 创建 HttpGet 对象
**HttpGet** 类表示 HTTP GET 请求,它使用 URI 检索给定服务器的信息。
通过实例化此类来创建一个 HTTP GET 请求。此类的构造函数接受一个表示 URI 的字符串值。
HttpGet httpget = new HttpGet("https://tutorialspoint.com/");
步骤 3 - 执行 GET 请求
**CloseableHttpClient** 类的 **execute()** 方法接受一个 HttpUriRequest(接口)对象(即 HttpGet、HttpPost、HttpPut、HttpHead 等)并返回一个响应对象。
使用此方法执行请求,如下所示:
HttpResponse httpresponse = httpclient.execute(httpget);
示例
以下示例演示了使用 HttpClient 库执行 HTTP GET 请求。
import java.util.Scanner; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; public class HttpGetExample { public static void main(String args[]) throws Exception{ //Creating a HttpClient object CloseableHttpClient httpclient = HttpClients.createDefault(); //Creating a HttpGet object HttpGet httpget = new HttpGet("https://tutorialspoint.com/ "); //Printing the method used System.out.println("Request Type: "+httpget.getMethod()); //Executing the Get request HttpResponse httpresponse = httpclient.execute(httpget); Scanner sc = new Scanner(httpresponse.getEntity().getContent()); //Printing the status line System.out.println(httpresponse.getStatusLine()); while(sc.hasNext()) { System.out.println(sc.nextLine()); } } }
输出
以上程序生成以下输出:
Request Type: GET <!DOCTYPE html> <!--[if IE 8]><html class = "ie ie8"> <![endif]--> <!--[if IE 9]><html class = "ie ie9"> <![endif]--> <!--[if gt IE 9]><!--> <html lang = "en-US"> <!--<![endif]--> <head> <!-- Basic --> <meta charset = "utf-8"> <title>Parallax Scrolling, Java Cryptography, YAML, Python Data Science, Java i18n, GitLab, TestRail, VersionOne, DBUtils, Common CLI, Seaborn, Ansible, LOLCODE, Current Affairs 2018, Apache Commons Collections</title> <meta name = "Description" content = "Parallax Scrolling, Java Cryptography, YAML, Python Data Science, Java i18n, GitLab, TestRail, VersionOne, DBUtils, Common CLI, Seaborn, Ansible, LOLCODE, Current Affairs 2018, Intellij Idea, Apache Commons Collections, Java 9, GSON, TestLink, Inter Process Communication (IPC), Logo, PySpark, Google Tag Manager, Free IFSC Code, SAP Workflow"/> <meta name = "Keywords" content = "Python Data Science, Java i18n, GitLab, TestRail, VersionOne, DBUtils, Common CLI, Seaborn, Ansible, LOLCODE, Gson, TestLink, Inter Process Communication (IPC), Logo"/> <meta http-equiv = "X-UA-Compatible" content = "IE = edge"> <meta name = "viewport" content = "width = device-width,initial-scale = 1.0,userscalable = yes"> <link href = "https://cdn.muicss.com/mui-0.9.39/extra/mui-rem.min.css" rel = "stylesheet" type = "text/css" /> <link rel = "stylesheet" href="/questions/css/home.css?v = 3" /> <script src = "/questions/js/jquery.min.js"></script> <script src = "/questions/js/fontawesome.js"></script> <script src = "https://cdn.muicss.com/mui-0.9.39/js/mui.min.js"></script> </head> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . </script> </body> </html>
Apache HttpClient - HTTP POST 请求
POST 请求用于将数据发送到服务器;例如,使用 HTML 表单发送客户信息、文件上传等。
HttpClient API 提供了一个名为 **HttpPost** 的类,它表示 POST 请求。
请按照以下步骤使用 HttpClient 库发送 HTTP POST 请求。
步骤 1 - 创建 HttpClient 对象
**HttpClients** 类的 **createDefault()** 方法返回 **CloseableHttpClient** 类的对象,它是 **HttpClient** 接口的基本实现。
使用此方法,创建一个 HttpClient 对象。
CloseableHttpClient httpClient = HttpClients.createDefault();
步骤 2 - 创建 HttpPost 对象
**HttpPost** 类表示 **HTTP POST** 请求。这会发送所需的数据并使用 URI 检索给定服务器的信息。
通过实例化 **HttpPost** 类并将其构造函数的参数设置为表示 URI 的字符串值来创建此请求。
HttpGet httpGet = new HttpGet("https://tutorialspoint.com/");
步骤 3 - 执行 GET 请求
**CloseableHttpClient** 对象的 **execute()** 方法接受一个 HttpUriRequest(接口)对象(即 HttpGet、HttpPost、HttpPut、HttpHead 等)并返回一个响应对象。
HttpResponse httpResponse = httpclient.execute(httpget);
示例
以下示例演示了使用 HttpClient 库执行 HTTP POST 请求。
import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; public class HttpPostExample { public static void main(String args[]) throws Exception{ //Creating a HttpClient object CloseableHttpClient httpclient = HttpClients.createDefault(); //Creating a HttpGet object HttpPost httppost = new HttpPost("https://tutorialspoint.com/"); //Printing the method used System.out.println("Request Type: "+httppost.getMethod()); //Executing the Get request HttpResponse httpresponse = httpclient.execute(httppost); Scanner sc = new Scanner(httpresponse.getEntity().getContent()); //Printing the status line System.out.println(httpresponse.getStatusLine()); while(sc.hasNext()) { System.out.println(sc.nextLine()); } } }
输出
以上程序生成以下输出。
Request Type: POST <!DOCTYPE html> <!--[if IE 8]><html class = "ie ie8"> <![endif]--> <!--[if IE 9]><html class = "ie ie9"> <![endif]--> <!--[if gt IE 9]><!--> <html lang = "en-US"> <!--<![endif]--> <head> <!-- Basic --> <meta charset = "utf-8"> <title>Parallax Scrolling, Java Cryptography, YAML, Python Data Science, Java i18n, GitLab, TestRail, VersionOne, DBUtils, Common CLI, Seaborn, Ansible, LOLCODE, Current Affairs 2018, Apache Commons Collections</title> <meta name = "Description" content = "Parallax Scrolling, Java Cryptography, YAML, Python Data Science, Java i18n, GitLab, TestRail, VersionOne, DBUtils, Common CLI, Seaborn, Ansible, LOLCODE, Current Affairs 2018, Intellij Idea, Apache Commons Collections, Java 9, GSON, TestLink, Inter Process Communication (IPC), Logo, PySpark, Google Tag Manager, Free IFSC Code, SAP Workflow"/> <meta name = "Keywords" content="Python Data Science, Java i18n, GitLab, TestRail, VersionOne, DBUtils, Common CLI, Seaborn, Ansible, LOLCODE, Gson, TestLink, Inter Process Communication (IPC), Logo"/> <meta http-equiv = "X-UA-Compatible" content = "IE = edge"> <meta name = "viewport" conten t= "width = device-width,initial-scale = 1.0,userscalable = yes"> <link href = "https://cdn.muicss.com/mui-0.9.39/extra/mui-rem.min.css" rel = "stylesheet" type = "text/css" /> <link rel = "stylesheet" href = "/questions/css/home.css?v = 3" /> <script src = "/questions/js/jquery.min.js"></script> <script src = "/questions/js/fontawesome.js"></script> <script src = "https://cdn.muicss.com/mui-0.9.39/js/mui.min.js"></script> </head> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . </script> </body> </html>
Apache HttpClient - 响应处理器
建议使用响应处理器处理 HTTP 响应。本章将讨论如何创建响应处理器以及如何使用它们来处理响应。
如果使用响应处理器,所有 HTTP 连接都将自动释放。
创建响应处理器
HttpClient API 提供了一个名为 **ResponseHandler** 的接口,位于 **org.apache.http.client.** 包中。为了创建一个响应处理器,请实现此接口并覆盖其 **handleResponse()** 方法。
每个响应都有一个状态代码,如果状态代码介于 200 和 300 之间,则表示操作已成功接收、理解和接受。因此,在我们的示例中,我们将处理具有此类状态代码的响应实体。
使用响应处理器执行请求
请按照以下步骤使用响应处理器执行请求。
步骤 1 - 创建 HttpClient 对象
**HttpClients** 类的 **createDefault()** 方法返回 **CloseableHttpClient** 类的对象,它是 **HttpClient** 接口的基本实现。使用此方法创建 HttpClient 对象
CloseableHttpClient httpclient = HttpClients.createDefault();
步骤 2 - 实例化响应处理器
使用以下代码行实例化上面创建的响应处理器对象:
ResponseHandler<String> responseHandler = new MyResponseHandler();
步骤 3 - 创建 HttpGet 对象
**HttpGet** 类表示 HTTP GET 请求,它使用 URI 检索给定服务器的信息。
通过实例化 HttpGet 类并将其构造函数的参数设置为表示 URI 的字符串来创建 HttpGet 请求。
ResponseHandler<String> responseHandler = new MyResponseHandler();
步骤 4 - 使用响应处理器执行 GET 请求
**CloseableHttpClient** 类有一个 **execute()** 方法的变体,它接受两个对象 **ResponseHandler** 和 HttpUriRequest,并返回一个响应对象。
String httpResponse = httpclient.execute(httpget, responseHandler);
示例
以下示例演示了响应处理器的用法。
import java.io.IOException; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ResponseHandler; 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; class MyResponseHandler implements ResponseHandler<String>{ public String handleResponse(final HttpResponse response) throws IOException{ //Get the status of the response int status = response.getStatusLine().getStatusCode(); if (status >= 200 && status < 300) { HttpEntity entity = response.getEntity(); if(entity == null) { return ""; } else { return EntityUtils.toString(entity); } } else { return ""+status; } } } public class ResponseHandlerExample { public static void main(String args[]) throws Exception{ //Create an HttpClient object CloseableHttpClient httpclient = HttpClients.createDefault(); //instantiate the response handler ResponseHandler<String> responseHandler = new MyResponseHandler(); //Create an HttpGet object HttpGet httpget = new HttpGet("https://tutorialspoint.com/"); //Execute the Get request by passing the response handler object and HttpGet object String httpresponse = httpclient.execute(httpget, responseHandler); System.out.println(httpresponse); } }
输出
以上程序生成以下输出:
<!DOCTYPE html> <!--[if IE 8]><html class = "ie ie8"> <![endif]--> <!--[if IE 9]><html class = "ie ie9"> <![endif]--> <!--[if gt IE 9]><!--> <html lang = "en-US"> <!--<![endif]--> <head> <!-- Basic --> <meta charset = "utf-8"> <meta http-equiv = "X-UA-Compatible" content = "IE = edge"> <meta name = "viewport" content = "width = device-width,initial-scale = 1.0,userscalable = yes"> <link href = "https://cdn.muicss.com/mui-0.9.39/extra/mui-rem.min.css" rel = "stylesheet" type = "text/css" /> <link rel = "stylesheet" href = "/questions/css/home.css?v = 3" /> <script src = "/questions/js/jquery.min.js"></script> <script src = "/questions/js/fontawesome.js"></script> <script src = "https://cdn.muicss.com/mui-0.9.39/js/mui.min.js"></script> </head> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . <script> window.dataLayer = window.dataLayer || []; function gtag() {dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-232293-17'); </script> </body>
Apache HttpClient - 关闭连接
如果您是手动处理 HTTP 响应而不是使用响应处理器,则需要自己关闭所有 HTTP 连接。本章解释如何手动关闭连接。
手动关闭 HTTP 连接时,请按照以下步骤操作:
步骤 1 - 创建 HttpClient 对象
**HttpClients** 类的 **createDefault()** 方法返回 **CloseableHttpClient** 类的对象,它是 HttpClient 接口的基本实现。
使用此方法,创建一个 **HttpClient** 对象,如下所示:
CloseableHttpClient httpClient = HttpClients.createDefault();
步骤 2 - 开始一个 try-finally 块
开始一个 try-finally 块,在 try 块中编写程序中的其余代码,并在 finally 块中关闭 CloseableHttpClient 对象。
CloseableHttpClient httpClient = HttpClients.createDefault(); try{ //Remaining code . . . . . . . . . . . . . . . }finally{ httpClient.close(); }
步骤 3 - 创建 HttpGetobject
**HttpGet** 类表示 HTTP GET 请求,它使用 URI 检索给定服务器的信息。
通过传递表示 URI 的字符串来实例化 HttpGet 类创建一个 HTTP GET 请求。
HttpGet httpGet = new HttpGet("https://tutorialspoint.com/");
步骤 4 - 执行 GET 请求
**CloseableHttpClient** 对象的 **execute()** 方法接受一个 **HttpUriRequest**(接口)对象(即 HttpGet、HttpPost、HttpPut、HttpHead 等)并返回一个响应对象。
使用给定方法执行请求:
HttpResponse httpResponse = httpclient.execute(httpGet);
步骤 5 - 开始另一个(嵌套的)try-finally 块
开始另一个 try-finally 块(嵌套在之前的 try-finally 块中),在 try 块中编写程序中的其余代码,并在 finally 块中关闭 HttpResponse 对象。
CloseableHttpClient httpclient = HttpClients.createDefault(); try{ . . . . . . . . . . . . . . CloseableHttpResponse httpresponse = httpclient.execute(httpget); try{ . . . . . . . . . . . . . . }finally{ httpresponse.close(); } }finally{ httpclient.close(); }
示例
无论何时创建/获取诸如请求、响应流等对象,请在下一行开始一个 try finally 块,在 try 块中编写其余代码,并在 finally 块中关闭相应对象,如下面的程序所示:
import java.util.Scanner; 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; public class CloseConnectionExample { public static void main(String args[])throws Exception{ //Create an HttpClient object CloseableHttpClient httpclient = HttpClients.createDefault(); try{ //Create an HttpGet object HttpGet httpget = new HttpGet("https://tutorialspoint.com/"); //Execute the Get request CloseableHttpResponse httpresponse = httpclient.execute(httpget); try{ Scanner sc = new Scanner(httpresponse.getEntity().getContent()); while(sc.hasNext()) { System.out.println(sc.nextLine()); } }finally{ httpresponse.close(); } }finally{ httpclient.close(); } } }
输出
执行上述程序后,将生成以下输出:
<!DOCTYPE html> <!--[if IE 8]><html class = "ie ie8"> <![endif]--> <!--[if IE 9]><html class = "ie ie9"> <![endif]--> <!--[if gt IE 9]><!--> <html lang = "en-US"> <!--<![endif]--> <head> <!-- Basic --> <meta charset = "utf-8"> <meta http-equiv = "X-UA-Compatible" content = "IE = edge"> <meta name = "viewport" content = "width = device-width,initial-scale = 1.0,userscalable = yes"> <link href = "https://cdn.muicss.com/mui-0.9.39/extra/mui-rem.min.css" rel = "stylesheet" type = "text/css" /> <link rel = "stylesheet" href = "/questions/css/home.css?v = 3" /> <script src = "/questions/js/jquery.min.js"></script> <script src = "/questions/js/fontawesome.js"></script> <script src = "https://cdn.muicss.com/mui-0.9.39/js/mui.min.js"></script> </head> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . <script> window.dataLayer = window.dataLayer || []; function gtag() {dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-232293-17'); </script> </body> </html>
Apache HttpClient - 中止请求
您可以使用`abort()`方法中止当前HTTP请求,即在特定请求上调用此方法后,将中止其执行。
如果在一次执行后调用此方法,则该执行的响应不会受到影响,后续执行将被中止。
示例
如果您观察下面的示例,我们创建了一个HttpGet请求,并使用`getMethod()`打印了使用的请求格式。
然后,我们使用相同的请求进行了另一次执行。再次打印了第一次执行的状体行。最后,打印了第二次执行的状体行。
正如所讨论的,第一次执行(abort方法之前的执行)的响应被打印(包括abort方法之后写入的第二个状态行),并且abort方法之后当前请求的所有后续执行都因引发异常而失败。
import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; public class HttpGetExample { public static void main(String args[]) throws Exception{ //Creating an HttpClient object CloseableHttpClient httpclient = HttpClients.createDefault(); //Creating an HttpGet object HttpGet httpget = new HttpGet("https://tutorialspoint.com/"); //Printing the method used System.out.println(httpget.getMethod()); //Executing the Get request HttpResponse httpresponse = httpclient.execute(httpget); //Printing the status line System.out.println(httpresponse.getStatusLine()); httpget.abort(); System.out.println(httpresponse.getEntity().getContentLength()); //Executing the Get request HttpResponse httpresponse2 = httpclient.execute(httpget); System.out.println(httpresponse2.getStatusLine()); } }
输出
执行上述程序后,将生成以下输出:
On executing, the above program generates the following output. GET HTTP/1.1 200 OK -1 Exception in thread "main" org.apache.http.impl.execchain.RequestAbortedException: Request aborted at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:180) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108) at HttpGetExample.main(HttpGetExample.java:32)
Apache HttpClient - 拦截器
拦截器可以阻止或更改请求或响应。协议拦截器通常作用于特定的标头或一组相关的标头。HttpClient库提供对拦截器的支持。
请求拦截器
`HttpRequestInterceptor`接口表示请求拦截器。此接口包含一个名为process的方法,您需要在其中编写拦截请求的代码块。
在客户端,此方法在将请求发送到服务器之前验证/处理请求;在服务器端,此方法在评估请求主体之前执行。
创建请求拦截器
您可以按照以下步骤创建请求拦截器。
步骤1 - 创建HttpRequestInterceptor对象
通过实现其抽象方法process来创建HttpRequestInterceptor接口的对象。
HttpRequestInterceptor requestInterceptor = new HttpRequestInterceptor() {
@Override public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { //Method implementation . . . . . };
步骤2 - 实例化CloseableHttpClient对象
如下所示,通过将上面创建的拦截器添加到其中来构建自定义`CloseableHttpClient`对象:
//Creating a CloseableHttpClient object CloseableHttpClient httpclient = HttpClients.custom().addInterceptorFirst(requestInterceptor).build();
使用此对象,您可以照常执行请求。
示例
以下示例演示了请求拦截器的用法。在这个例子中,我们创建了一个HTTP GET请求对象,并向其中添加了三个标头:sample-header、demoheader和test-header。
在拦截器的`processor()`方法中,我们正在验证发送的请求的标头;如果任何标头是`sample-header`,我们将尝试将其删除并显示该特定请求的标头列表。
import java.io.IOException; import org.apache.http.Header; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponse; 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.message.BasicHeader; import org.apache.http.protocol.HttpContext; public class InterceptorsExample { public static void main(String args[]) throws Exception{ //Creating an HttpRequestInterceptor HttpRequestInterceptor requestInterceptor = new HttpRequestInterceptor() { @Override public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { if(request.containsHeader("sample-header")) { System.out.println("Contains header sample-header, removing it.."); request.removeHeaders("sample-header"); } //Printing remaining list of headers Header[] headers= request.getAllHeaders(); for (int i = 0; i<headers.length;i++) { System.out.println(headers[i].getName()); } } }; //Creating a CloseableHttpClient object CloseableHttpClient httpclient = HttpClients.custom().addInterceptorFirst(requestInterceptor).build(); //Creating a request object HttpGet httpget1 = new HttpGet("https://tutorialspoint.com/"); //Setting the header to it httpget1.setHeader(new BasicHeader("sample-header","My first header")); httpget1.setHeader(new BasicHeader("demo-header","My second header")); httpget1.setHeader(new BasicHeader("test-header","My third header")); //Executing the request HttpResponse httpresponse = httpclient.execute(httpget1); //Printing the status line System.out.println(httpresponse.getStatusLine()); } }
输出
执行上述程序后,将生成以下输出:
Contains header sample-header, removing it.. demo-header test-header HTTP/1.1 200 OK
响应拦截器
`HttpResponseInterceptor`接口表示响应拦截器。此接口包含一个名为`process()`的方法。在此方法中,您需要编写拦截响应的代码块。
在服务器端,此方法在将响应发送到客户端之前验证/处理响应;在客户端,此方法在评估响应主体之前执行。
创建响应拦截器
您可以按照以下步骤创建响应拦截器:
步骤1 - 创建HttpResponseInterceptor对象
通过实现其抽象方法`process`来创建`HttpResponseInterceptor`接口的对象。
HttpResponseInterceptor responseInterceptor = new HttpResponseInterceptor() { @Override public void process(HttpResponse response, HttpContext context) throws HttpException, IOException { //Method implementation . . . . . . . . } };
步骤2:实例化CloseableHttpClient对象
如下所示,通过将上面创建的拦截器添加到其中来构建自定义`CloseableHttpClient`对象:
//Creating a CloseableHttpClient object CloseableHttpClient httpclient = HttpClients.custom().addInterceptorFirst(responseInterceptor).build();
使用此对象,您可以照常执行请求。
示例
以下示例演示了响应拦截器的用法。在这个例子中,我们在处理器中向响应添加了三个标头:sample-header、demo-header和test-header。
执行请求并获得响应后,我们使用`getAllHeaders()`方法打印了响应的所有标头的名称。
并且在输出中,您可以看到列表中三个标头的名称。
import java.io.IOException; import org.apache.http.Header; import org.apache.http.HttpException; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; 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.protocol.HttpContext; public class ResponseInterceptorsExample { public static void main(String args[]) throws Exception{ //Creating an HttpRequestInterceptor HttpResponseInterceptor responseInterceptor = new HttpResponseInterceptor() { @Override public void process(HttpResponse response, HttpContext context) throws HttpException, IOException { System.out.println("Adding header sample_header, demo-header, test_header to the response"); response.setHeader("sample-header", "My first header"); response.setHeader("demo-header", "My second header"); response.setHeader("test-header", "My third header"); } }; //Creating a CloseableHttpClient object CloseableHttpClient httpclient = HttpClients.custom().addInterceptorFirst(responseInterceptor).build(); //Creating a request object HttpGet httpget1 = new HttpGet("https://tutorialspoint.com/"); //Executing the request HttpResponse httpresponse = httpclient.execute(httpget1); //Printing remaining list of headers Header[] headers = httpresponse.getAllHeaders(); for (int i = 0; i<headers.length;i++) { System.out.println(headers[i].getName()); } } }
输出
执行上述程序后,将生成以下结果:
On executing the above program generates the following output. Adding header sample_header, demo-header, test_header to the response Accept-Ranges Access-Control-Allow-Headers Access-Control-Allow-Origin Cache-Control Content-Type Date Expires Last-Modified Server Vary X-Cache sample-header demo-header test-header
Apache HttpClient - 用户身份验证
使用HttpClient,您可以连接到需要用户名和密码的网站。本章解释了如何针对需要用户名和密码的站点执行客户端请求。
步骤1 - 创建CredentialsProvider对象
`CredentialsProvider`接口维护一个集合以保存用户登录凭据。您可以通过实例化`BasicCredentialsProvider`类(此接口的默认实现)来创建其对象。
CredentialsProvider credentialsPovider = new BasicCredentialsProvider();
步骤2 - 设置凭据
您可以使用`setCredentials()`方法将所需的凭据设置为CredentialsProvider对象。
此方法接受两个对象,如下所示:
`AuthScope`对象 - 身份验证范围,指定主机名、端口号和身份验证方案名称等详细信息。
`Credentials`对象 - 指定凭据(用户名、密码)。
如下所示,使用`setCredentials()`方法为主机和代理设置凭据:
credsProvider.setCredentials(new AuthScope("example.com", 80), new UsernamePasswordCredentials("user", "mypass")); credsProvider.setCredentials(new AuthScope("localhost", 8000), new UsernamePasswordCredentials("abc", "passwd"));
步骤3 - 创建HttpClientBuilder对象
使用`HttpClients`类的`custom()`方法创建一个`HttpClientBuilder`。
//Creating the HttpClientBuilder HttpClientBuilder clientbuilder = HttpClients.custom();
步骤4 - 设置credentialsPovider
您可以使用`setDefaultCredentialsProvider()`方法将上面创建的credentialsPovider对象设置为HttpClientBuilder。
将上一步中创建的CredentialProvider对象传递给`CredentialsProvider`对象()方法,将其设置为客户端构建器。
clientbuilder = clientbuilder.setDefaultCredentialsProvider(credsProvider);
步骤5 - 构建CloseableHttpClient
使用`HttpClientBuilder`类的`build()`方法构建`CloseableHttpClient`对象。
CloseableHttpClient httpclient = clientbuilder.build()
步骤6 - 创建HttpGet对象并执行它
通过实例化HttpGet类来创建一个HttpRequest对象。使用`execute()`方法执行此请求。
//Creating a HttpGet object HttpGet httpget = new HttpGet("https://tutorialspoint.com/ "); //Executing the Get request HttpResponse httpresponse = httpclient.execute(httpget);
示例
以下是一个示例程序,演示了针对需要用户身份验证的目标站点执行HTTP请求。
import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScope; import org.apache.http.auth.Credentials; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; public class UserAuthenticationExample { public static void main(String args[]) throws Exception{ //Create an object of credentialsProvider CredentialsProvider credentialsPovider = new BasicCredentialsProvider(); //Set the credentials AuthScope scope = new AuthScope("https://tutorialspoint.com/questions/", 80); Credentials credentials = new UsernamePasswordCredentials("USERNAME", "PASSWORD"); credentialsPovider.setCredentials(scope,credentials); //Creating the HttpClientBuilder HttpClientBuilder clientbuilder = HttpClients.custom(); //Setting the credentials clientbuilder = clientbuilder.setDefaultCredentialsProvider(credentialsPovider); //Building the CloseableHttpClient object CloseableHttpClient httpclient = clientbuilder.build(); //Creating a HttpGet object HttpGet httpget = new HttpGet("https://tutorialspoint.com/questions/index.php"); //Printing the method used System.out.println(httpget.getMethod()); //Executing the Get request HttpResponse httpresponse = httpclient.execute(httpget); //Printing the status line System.out.println(httpresponse.getStatusLine()); int statusCode = httpresponse.getStatusLine().getStatusCode(); System.out.println(statusCode); Header[] headers= httpresponse.getAllHeaders(); for (int i = 0; i<headers.length;i++) { System.out.println(headers[i].getName()); } } }
输出
执行上述程序后,将生成以下输出。
GET HTTP/1.1 200 OK 200
Apache HttpClient - 使用代理
代理服务器是客户端和互联网之间的中间服务器。代理服务器提供以下基本功能:
防火墙和网络数据过滤
网络连接共享
数据缓存
使用HttpClient库,您可以使用代理发送HTTP请求。请按照以下步骤操作:
步骤1 - 创建HttpHost对象
通过传递表示代理主机名称的字符串参数(您需要从中发送请求)到其构造函数中,实例化`org.apache.http`包的`HttpHost`类。
//Creating an HttpHost object for proxy HttpHost proxyHost = new HttpHost("localhost");
同样,创建另一个HttpHost对象来表示需要将请求发送到的目标主机。
//Creating an HttpHost object for target HttpHost targetHost = new HttpHost("google.com");
步骤2 - 创建HttpRoutePlanner对象
`HttpRoutePlanner`接口计算到指定主机的路由。通过实例化`DefaultProxyRoutePlanner`类(此接口的实现)来创建此接口的对象。将其构造函数的参数设置为上面创建的代理主机:
//creating a RoutePlanner object HttpRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyhost);
步骤3 - 将路由规划器设置为客户端构建器
使用`HttpClients`类的`custom()`方法创建一个`HttpClientBuilder`对象,并使用`setRoutePlanner()`方法将上面创建的路由规划器设置为该对象。
//Setting the route planner to the HttpClientBuilder object HttpClientBuilder clientBuilder = HttpClients.custom(); clientBuilder = clientBuilder.setRoutePlanner(routePlanner);
步骤4 - 构建CloseableHttpClient对象
通过调用`build()`方法构建`CloseableHttpClient`对象。
//Building a CloseableHttpClient CloseableHttpClient httpClient = clientBuilder.build();
步骤5 - 创建HttpGetobject
通过实例化`HttpGet`类来创建一个HTTP GET请求。
//Creating an HttpGet object HttpGet httpGet = new HttpGet("/");
步骤6 - 执行请求
`execute()`方法的变体之一接受`HttpHost`和`HttpRequest`对象并执行请求。使用此方法执行请求:
//Executing the Get request HttpResponse httpResponse = httpclient.execute(targetHost, httpGet);
示例
以下示例演示如何通过代理将HTTP请求发送到服务器。在此示例中,我们通过localhost将HTTP GET请求发送到google.com。我们打印了响应的标头和响应的主体。
import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.routing.HttpRoutePlanner; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.DefaultProxyRoutePlanner; import org.apache.http.util.EntityUtils; public class RequestViaProxyExample { public static void main(String args[]) throws Exception{ //Creating an HttpHost object for proxy HttpHost proxyhost = new HttpHost("localhost"); //Creating an HttpHost object for target HttpHost targethost = new HttpHost("google.com"); //creating a RoutePlanner object HttpRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyhost); //Setting the route planner to the HttpClientBuilder object HttpClientBuilder clientBuilder = HttpClients.custom(); clientBuilder = clientBuilder.setRoutePlanner(routePlanner); //Building a CloseableHttpClient CloseableHttpClient httpclient = clientBuilder.build(); //Creating an HttpGet object HttpGet httpget = new HttpGet("/"); //Executing the Get request HttpResponse httpresponse = httpclient.execute(targethost, httpget); //Printing the status line System.out.println(httpresponse.getStatusLine()); //Printing all the headers of the response Header[] headers = httpresponse.getAllHeaders(); for (int i = 0; i < headers.length; i++) { System.out.println(headers[i]); } //Printing the body of the response HttpEntity entity = httpresponse.getEntity(); if (entity != null) { System.out.println(EntityUtils.toString(entity)); } } }
输出
执行上述程序后,将生成以下输出:
HTTP/1.1 200 OK Date: Sun, 23 Dec 2018 10:21:47 GMT Server: Apache/2.4.9 (Win64) PHP/5.5.13 Last-Modified: Tue, 24 Jun 2014 10:46:24 GMT ETag: "2e-4fc92abc3c000" Accept-Ranges: bytes Content-Length: 46 Content-Type: text/html <html><body><h1>It works!</h1></body></html>
Apache HttpClient - 代理身份验证
本章将学习如何创建一个使用用户名和密码进行身份验证的HttpRequest,并通过代理将其隧道传输到目标主机,并通过示例进行说明。
步骤1 - 创建CredentialsProvider对象
`CredentialsProvider`接口维护一个集合以保存用户登录凭据。您可以通过实例化BasicCredentialsProvider类(此接口的默认实现)来创建其对象。
CredentialsProvider credentialsPovider = new BasicCredentialsProvider();
步骤2 - 设置凭据
您可以使用`setCredentials()`方法将所需的凭据设置为CredentialsProvider对象。此方法接受两个对象:
`AuthScope`对象 - 身份验证范围,指定主机名、端口号和身份验证方案名称等详细信息。
`Credentials`对象 - 指定凭据(用户名、密码)。如下所示,使用`setCredentials()`方法为主机和代理设置凭据。
credsProvider.setCredentials(new AuthScope("example.com", 80), new UsernamePasswordCredentials("user", "mypass")); credsProvider.setCredentials(new AuthScope("localhost", 8000), new UsernamePasswordCredentials("abc", "passwd"));
步骤3 - 创建HttpClientBuilder对象
如下所示,使用`HttpClients`类的`custom()`方法创建一个`HttpClientBuilder`:
//Creating the HttpClientBuilder HttpClientBuilder clientbuilder = HttpClients.custom();
步骤4 - 设置CredentialsProvider
您可以使用`setDefaultCredentialsProvider()`方法将CredentialsProvider对象设置为HttpClientBuilder对象。将先前创建的`CredentialsProvider`对象传递给此方法。
clientbuilder = clientbuilder.setDefaultCredentialsProvider(credsProvider);
步骤5 - 构建CloseableHttpClient
使用`build()`方法构建`CloseableHttpClient`对象。
CloseableHttpClient httpclient = clientbuilder.build();
步骤6 - 创建代理和目标主机
通过实例化`HttpHost`类来创建目标和代理主机。
//Creating the target and proxy hosts HttpHost target = new HttpHost("example.com", 80, "http"); HttpHost proxy = new HttpHost("localhost", 8000, "http");
步骤7 - 设置代理并构建RequestConfig对象
使用`custom()`方法创建一个`RequestConfig.Builder`对象。使用`setProxy()`方法将先前创建的proxyHost对象设置为`RequestConfig.Builder`。最后,使用`build()`方法构建`RequestConfig`对象。
RequestConfig.Builder reqconfigconbuilder= RequestConfig.custom(); reqconfigconbuilder = reqconfigconbuilder.setProxy(proxyHost); RequestConfig config = reqconfigconbuilder.build();
步骤8 - 创建HttpGet请求对象并将其配置对象设置为它。
通过实例化HttpGet类来创建一个`HttpGet`对象。使用`setConfig()`方法将上一步中创建的配置对象设置为此对象。
//Create the HttpGet request object HttpGet httpGet = new HttpGet("/"); //Setting the config to the request httpget.setConfig(config);
步骤9 - 执行请求
通过将HttpHost对象(目标)和请求(HttpGet)作为参数传递给`execute()`方法来执行请求。
HttpResponse httpResponse = httpclient.execute(targetHost, httpget);
示例
以下示例演示如何使用用户名和密码通过代理执行HTTP请求。
import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; public class ProxyAuthenticationExample { public static void main(String[] args) throws Exception { //Creating the CredentialsProvider object CredentialsProvider credsProvider = new BasicCredentialsProvider(); //Setting the credentials credsProvider.setCredentials(new AuthScope("example.com", 80), new UsernamePasswordCredentials("user", "mypass")); credsProvider.setCredentials(new AuthScope("localhost", 8000), new UsernamePasswordCredentials("abc", "passwd")); //Creating the HttpClientBuilder HttpClientBuilder clientbuilder = HttpClients.custom(); //Setting the credentials clientbuilder = clientbuilder.setDefaultCredentialsProvider(credsProvider); //Building the CloseableHttpClient object CloseableHttpClient httpclient = clientbuilder.build(); //Create the target and proxy hosts HttpHost targetHost = new HttpHost("example.com", 80, "http"); HttpHost proxyHost = new HttpHost("localhost", 8000, "http"); //Setting the proxy RequestConfig.Builder reqconfigconbuilder= RequestConfig.custom(); reqconfigconbuilder = reqconfigconbuilder.setProxy(proxyHost); RequestConfig config = reqconfigconbuilder.build(); //Create the HttpGet request object HttpGet httpget = new HttpGet("/"); //Setting the config to the request httpget.setConfig(config); //Printing the status line HttpResponse response = httpclient.execute(targetHost, httpget); System.out.println(response.getStatusLine()); } }
输出
执行上述程序后,将生成以下输出:
HTTP/1.1 200 OK
Apache HttpClient - 基于表单的登录
使用HttpClient库,您可以通过传递参数来发送请求或登录表单。
请按照以下步骤登录表单。
步骤 1 - 创建 HttpClient 对象
`HttpClients`类的`createDefault()`方法返回`CloseableHttpClient`类的对象,它是HttpClient接口的基本实现。使用此方法创建HttpClient对象:
CloseableHttpClient httpClient = HttpClients.createDefault();
步骤2 - 创建RequestBuilder对象
`RequestBuilder`类用于通过向其中添加参数来构建请求。如果请求类型是PUT或POST,它会将参数作为URL编码实体添加到请求中
使用post()方法创建一个(POST类型的)RequestBuilder对象。
//Building the post request object RequestBuilder reqbuilder = RequestBuilder.post();
步骤3 - 将Uri和参数设置为RequestBuilder。
使用RequestBuilder类的`setUri()`和`addParameter()`方法将URI和参数设置为RequestBuilder对象。
//Set URI and parameters RequestBuilder reqbuilder = reqbuilder.setUri("http://httpbin.org/post"); reqbuilder = reqbuilder1.addParameter("Name", "username").addParameter("password", "password");
步骤4 - 构建HttpUriRequest对象
设置所需参数后,使用`build()`方法构建`HttpUriRequest`对象。
//Building the HttpUriRequest object HttpUriRequest httppost = reqbuilder2.build();
步骤5 - 执行请求
`CloseableHttpClient`对象的execute方法接受一个HttpUriRequest(接口)对象(即HttpGet、HttpPost、HttpPut、HttpHead等)并返回一个响应对象。
将上一步中创建的HttpUriRequest传递给`execute()`方法来执行它。
//Execute the request HttpResponse httpresponse = httpclient.execute(httppost);
示例
以下示例演示如何通过发送登录凭据来登录表单。在这里,我们向表单发送了两个参数 - `username`和`password`,并尝试打印请求的消息实体和状态。
import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.IOException; import java.net.URISyntaxException; public class FormLoginExample { public static void main(String args[]) throws Exception { //Creating CloseableHttpClient object CloseableHttpClient httpclient = HttpClients.createDefault(); //Creating the RequestBuilder object RequestBuilder reqbuilder = RequestBuilder.post(); //Setting URI and parameters RequestBuilder reqbuilder1 = reqbuilder.setUri("http://httpbin.org/post"); RequestBuilder reqbuilder2 = reqbuilder1.addParameter("Name", "username").addParameter("password", "password"); //Building the HttpUriRequest object HttpUriRequest httppost = reqbuilder2.build(); //Executing the request HttpResponse httpresponse = httpclient.execute(httppost); //Printing the status and the contents of the response System.out.println(EntityUtils.toString(httpresponse.getEntity())); System.out.println(httpresponse.getStatusLine()); } }
输出
执行上述程序后,将生成以下输出:
{ "args": {}, "data": "", "files": {}, "form": { "Name": "username", "password": "password" }, "headers": { "Accept-Encoding": "gzip,deflate", "Connection": "close", "Content-Length": "31", "Content-Type": "application/x-www-form-urlencoded; charset = UTF-8", "Host": "httpbin.org", "User-Agent": "Apache-HttpClient/4.5.6 (Java/1.8.0_91)" }, "json": null, "origin": "117.216.245.180", "url": "http://httpbin.org/post" } HTTP/1.1 200 OK
使用Cookie的表单登录
如果您的表单存储Cookie,而不是创建默认的`CloseableHttpClient`对象。
通过实例化BasicCookieStore类来`创建一个CookieStore对象`。
//Creating a BasicCookieStore object BasicCookieStore cookieStore = new BasicCookieStore();
使用**HttpClients**类的**custom()**方法**创建一个HttpClientBuilder**。
//Creating an HttpClientBuilder object HttpClientBuilder clientbuilder = HttpClients.custom();
使用setDefaultCookieStore()方法**将Cookie存储区设置到客户端构建器**。
//Setting default cookie store to the client builder object Clientbuilder = clientbuilder.setDefaultCookieStore(cookieStore);
使用`build()`方法构建`CloseableHttpClient`对象。
//Building the CloseableHttpClient object CloseableHttpClient httpclient = clientbuilder1.build();
如上所述构建**HttpUriRequest**对象,通过执行请求。
如果页面存储Cookie,则您传递的参数将添加到Cookie存储区。
您可以打印**CookieStore**对象的内容,在那里您可以看到您的参数(以及页面可能已经存储的先前参数)。
要打印Cookie,请使用**getCookies()**方法从**CookieStore**对象获取所有Cookie。此方法返回一个**List**对象。使用迭代器,如下所示打印列表对象的内容:
//Printing the cookies List list = cookieStore.getCookies(); System.out.println("list of cookies"); Iterator it = list.iterator(); if(it.hasNext()) { System.out.println(it.next()); }
Apache HttpClient - Cookie管理
Cookie是存储在客户端计算机上的文本文件,它们用于各种信息跟踪目的。
HttpClient提供对Cookie的支持,您可以创建和管理Cookie。
创建Cookie
按照以下步骤使用HttpClient库创建Cookie。
步骤1 - 创建CookieStore对象
**CookieStore**接口表示Cookie对象的抽象存储区。您可以通过实例化**BasicCookieStore**类(此接口的默认实现)来创建一个Cookie存储区。
//Creating the CookieStore object CookieStore cookieStore = new BasicCookieStore();
步骤2 - 创建ClientCookie对象
除了Cookie的功能外,ClientCookie还可以获取服务器中的原始Cookie。您可以通过实例化**BasicClientCookie**类来创建一个客户端Cookie。对于此类的构造函数,您需要传递希望存储在该特定Cookie中的键值对。
//Creating client cookie BasicClientCookie clientCookie = new BasicClientCookie("name","Raju");
步骤3 - 设置Cookie的值
对于客户端Cookie,您可以使用相应的方法设置/删除路径、值、版本、过期日期、域、注释和属性。
Calendar myCal = new GregorianCalendar(2018, 9, 26); Date expiryDate = myCal.getTime(); clientcookie.setExpiryDate(expiryDate); clientcookie.setPath("/"); clientcookie.setSecure(true); clientcookie.setValue("25"); clientcookie.setVersion(5);
步骤4 - 将Cookie添加到Cookie存储区
您可以使用**BasicCookieStore**类的**addCookie()**方法将Cookie添加到Cookie存储区。
将所需的Cookie添加到**CookieStore**。
//Adding the created cookies to cookie store cookiestore.addCookie(clientcookie);
示例
以下示例演示如何创建Cookie并将它们添加到Cookie存储区。在这里,我们创建了一个Cookie存储区,通过设置域和路径值创建了一批Cookie,并将这些Cookie添加到Cookie存储区。
import org.apache.http.client.CookieStore; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.cookie.BasicClientCookie; public class CookieHandlingExample { public static void main(String args[]) throws Exception{ //Creating the CookieStore object CookieStore cookiestore = new BasicCookieStore(); //Creating client cookies BasicClientCookie clientcookie1 = new BasicClientCookie("name","Raju"); BasicClientCookie clientcookie2 = new BasicClientCookie("age","28"); BasicClientCookie clientcookie3 = new BasicClientCookie("place","Hyderabad"); //Setting domains and paths to the created cookies clientcookie1.setDomain(".sample.com"); clientcookie2.setDomain(".sample.com"); clientcookie3.setDomain(".sample.com"); clientcookie1.setPath("/"); clientcookie2.setPath("/"); clientcookie3.setPath("/"); //Adding the created cookies to cookie store cookiestore.addCookie(clientcookie1); cookiestore.addCookie(clientcookie2); cookiestore.addCookie(clientcookie3); } }
检索Cookie
您可以使用**BasicCookieStore**类的**getCookies()**方法获取添加到Cookie存储区的Cookie。此方法返回一个列表,其中包含Cookie存储区中的所有Cookie。
您可以使用迭代器如下所示打印Cookie存储区的内容:
//Retrieving the cookies List list = cookieStore.getCookies(); //Creating an iterator to the obtained list Iterator it = list.iterator(); while(it.hasNext()) { System.out.println(it.next()); }
示例
以下示例演示如何从Cookie存储区检索Cookie。在这里,我们将一堆Cookie添加到Cookie存储区并将其检索回来。
import org.apache.http.client.CookieStore; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.cookie.BasicClientCookie; public class CookieHandlingExample { public static void main(String args[]) throws Exception{ //Creating the CookieStore object CookieStore cookiestore = new BasicCookieStore(); //Creating client cookies BasicClientCookie clientcookie1 = new BasicClientCookie("name","Raju"); BasicClientCookie clientcookie2 = new BasicClientCookie("age","28"); BasicClientCookie clientcookie3 = new BasicClientCookie("place","Hyderabad"); //Setting domains and paths to the created cookies clientcookie1.setDomain(".sample.com"); clientcookie2.setDomain(".sample.com"); clientcookie3.setDomain(".sample.com"); clientcookie1.setPath("/"); clientcookie2.setPath("/"); clientcookie3.setPath("/"); //Adding the created cookies to cookie store cookiestore.addCookie(clientcookie1); cookiestore.addCookie(clientcookie2); cookiestore.addCookie(clientcookie3); } }
输出
执行此程序后,将生成以下输出:
[version: 0][name: age][value: 28][domain: .sample.com][path: /][expiry: null] [version: 0][name: name][value: Raju][domain: my.example.com][path: /][expiry: null] [version: 0][name: place][value: Hyderabad][domain: .sample.com][path: /][expiry: null]
Apache HttpClient - 多线程
多线程程序包含两个或多个可以同时运行的部分,每个部分可以同时处理不同的任务,从而最佳地利用可用资源。
您可以通过编写多线程HttpClient程序来执行来自多个线程的请求。
如果要从线程连续执行多个客户端请求,则需要创建一个**ClientConnectionPoolManager**。它维护一个**HttpClientConnections**池,并为来自线程的多个请求提供服务。
连接管理器根据路由对连接进行池化。如果管理器对特定路由有连接,则它通过从池中租赁现有连接来为这些路由中的新请求提供服务,而不是创建一个新的连接。
按照以下步骤从多个线程执行请求:
步骤1 - 创建客户端连接池管理器
通过实例化**PoolingHttpClientConnectionManager**类来创建客户端连接池管理器。
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
步骤2 - 设置最大连接数
使用**setMaxTotal()**方法设置池中的最大连接数。
//Set the maximum number of connections in the pool connManager.setMaxTotal(100);
步骤3 - 创建ClientBuilder对象
如下所示,通过使用**setConnectionManager()**方法设置连接管理器来创建一个**ClientBuilder**对象:
HttpClientBuilder clientbuilder = HttpClients.custom().setConnectionManager(connManager);
步骤4 - 创建HttpGet请求对象
通过将所需的URI作为参数传递给其构造函数来实例化HttpGet类。
HttpGet httpget1 = new HttpGet("URI1"); HttpGet httpget2 = new HttpGet("URI2"); . . . . . . . . . . . .
步骤5 - 实现run方法
确保您已创建一个类,使其成为线程(通过扩展线程类或实现Runnable接口),并实现了run方法。
public class ClientMultiThreaded extends Thread { public void run() { //Run method implementation . . . . . . . . . . } }
步骤6 - 创建线程对象
通过实例化上面创建的Thread类(ClientMultiThreaded)来创建线程对象。
将HttpClient对象、相应的HttpGet对象和表示ID的整数传递给这些线程。
ClientMultiThreaded thread1 = new ClientMultiThreaded(httpclient,httpget1, 1); ClientMultiThreaded thread2 = new ClientMultiThreaded(httpclient,httpget2, 2); . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
步骤7 - 启动和加入线程
使用**start()**方法启动所有线程,并使用join**method()**方法加入它们。
thread1.start(); thread2.start(); . . . . . . . . thread1.join(); thread2.join(); . . . . . . . . . . . .
步骤8 - run方法实现
在run方法中,执行请求,检索响应并打印结果。
示例
以下示例演示了同时从多个线程执行HTTP请求。在此示例中,我们尝试从多个线程执行各种请求,并尝试打印状态以及每个客户端读取的字节数。
import org.apache.http.HttpEntity; 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.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.util.EntityUtils; public class ClientMultiThreaded extends Thread { CloseableHttpClient httpClient; HttpGet httpget; int id; public ClientMultiThreaded(CloseableHttpClient httpClient, HttpGet httpget, int id) { this.httpClient = httpClient; this.httpget = httpget; this.id = id; } @Override public void run() { try{ //Executing the request CloseableHttpResponse httpresponse = httpClient.execute(httpget); //Displaying the status of the request. System.out.println("status of thread "+id+":"+httpresponse.getStatusLine()); //Retrieving the HttpEntity and displaying the no.of bytes read HttpEntity entity = httpresponse.getEntity(); if (entity != null) { System.out.println("Bytes read by thread thread "+id+": "+EntityUtils.toByteArray(entity).length); } }catch(Exception e) { System.out.println(e.getMessage()); } } public static void main(String[] args) throws Exception { //Creating the Client Connection Pool Manager by instantiating the PoolingHttpClientConnectionManager class. PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(); //Set the maximum number of connections in the pool connManager.setMaxTotal(100); //Create a ClientBuilder Object by setting the connection manager HttpClientBuilder clientbuilder = HttpClients.custom().setConnectionManager(connManager); //Build the CloseableHttpClient object using the build() method. CloseableHttpClient httpclient = clientbuilder.build(); //Creating the HttpGet requests HttpGet httpget1 = new HttpGet("https://tutorialspoint.com/"); HttpGet httpget2 = new HttpGet("http://www.google.com/"); HttpGet httpget3 = new HttpGet("https://www.qries.com/"); HttpGet httpget4 = new HttpGet("https://in.yahoo.com/"); //Creating the Thread objects ClientMultiThreaded thread1 = new ClientMultiThreaded(httpclient,httpget1, 1); ClientMultiThreaded thread2 = new ClientMultiThreaded(httpclient,httpget2, 2); ClientMultiThreaded thread3 = new ClientMultiThreaded(httpclient,httpget3, 3); ClientMultiThreaded thread4 = new ClientMultiThreaded(httpclient,httpget4, 4); //Starting all the threads thread1.start(); thread2.start(); thread3.start(); thread4.start(); //Joining all the threads thread1.join(); thread2.join(); thread3.join(); thread4.join(); } }
输出
执行上述程序后,将生成以下输出:
status of thread 1: HTTP/1.1 200 OK Bytes read by thread thread 1: 36907 status of thread 2: HTTP/1.1 200 OK Bytes read by thread thread 2: 13725 status of thread 3: HTTP/1.1 200 OK Bytes read by thread thread 3: 17319 status of thread 4: HTTP/1.1 200 OK Bytes read by thread thread 4: 127018
Apache HttpClient - 自定义SSL上下文
使用安全套接字层,您可以建立客户端和服务器之间的安全连接。它有助于保护敏感信息,例如信用卡号码、用户名、密码、PIN码等。
您可以使用**HttpClient**库创建自己的SSL上下文,使连接更安全。
按照以下步骤使用HttpClient库自定义SSLContext:
步骤1 - 创建SSLContextBuilder对象
**SSLContextBuilder**是SSLContext对象的构建器。使用**SSLContexts**类的**custom()**方法创建其对象。
//Creating SSLContextBuilder object SSLContextBuilder SSLBuilder = SSLContexts.custom();
步骤2 - 加载密钥库
在路径**Java_home_directory/jre/lib/security/**中,您可以找到一个名为cacerts的文件。将其保存为您的密钥库文件(扩展名为.jks)。使用**SSLContextBuilder**类的**loadTrustMaterial()**方法加载密钥库文件及其密码(默认为**changeit**)。
//Loading the Keystore file File file = new File("mykeystore.jks"); SSLBuilder = SSLBuilder.loadTrustMaterial(file, "changeit".toCharArray());
步骤3 - 构建SSLContext对象
SSLContext对象表示安全套接字协议实现。使用**build()**方法构建SSLContext。
//Building the SSLContext SSLContext sslContext = SSLBuilder.build();
步骤4 - 创建SSLConnectionSocketFactory对象
**SSLConnectionSocketFactory**是用于TSL和SSL连接的分层套接字工厂。使用它,您可以使用受信任证书列表验证Https服务器并验证给定的Https服务器。
您可以通过多种方式创建它。根据您创建**SSLConnectionSocketFactory**对象的方式,您可以允许所有主机、仅允许自签名证书、仅允许特定协议等。
**要仅允许特定协议**,请通过将SSLContext对象、表示需要支持的协议的字符串数组、表示需要支持的密码套件的字符串数组以及HostnameVerifier对象传递给其构造函数来创建**SSLConnectionSocketFactory**对象。
new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
**要允许所有主机**,请通过传递SSLContext对象和**NoopHostnameVerifier**对象来创建**SSLConnectionSocketFactory**对象。
//Creating SSLConnectionSocketFactory SSLConnectionSocketFactory object SSLConnectionSocketFactory sslConSocFactory = new SSLConnectionSocketFactory(sslcontext, new NoopHostnameVerifier());
步骤5 - 创建HttpClientBuilder对象
使用**HttpClients**类的**custom()**方法创建一个HttpClientBuilder对象。
//Creating HttpClientBuilder HttpClientBuilder clientbuilder = HttpClients.custom();
步骤6 - 设置SSLConnectionSocketFactory对象
使用**setSSLSocketFactory()**方法将SSLConnectionSocketFactory对象设置为**HttpClientBuilder**。
//Setting the SSLConnectionSocketFactory clientbuilder = clientbuilder.setSSLSocketFactory(sslConSocFactory);
步骤7 - 构建CloseableHttpClient对象
通过调用`build()`方法构建`CloseableHttpClient`对象。
//Building the CloseableHttpClient CloseableHttpClient httpclient = clientbuilder.build();
步骤8 - 创建HttpGet对象
**HttpGet** 类表示 HTTP GET 请求,它使用 URI 检索给定服务器的信息。
通过传递表示 URI 的字符串来实例化 HttpGet 类创建一个 HTTP GET 请求。
//Creating the HttpGet request HttpGet httpget = new HttpGet("https://example.com/");
步骤9 - 执行请求
使用**execute()**方法执行请求。
//Executing the request HttpResponse httpresponse = httpclient.execute(httpget);
示例
以下示例演示了SSLContrext的自定义:
import java.io.File; import javax.net.ssl.SSLContext; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.SSLContexts; import org.apache.http.util.EntityUtils; public class ClientCustomSSL { public final static void main(String[] args) throws Exception { //Creating SSLContextBuilder object SSLContextBuilder SSLBuilder = SSLContexts.custom(); //Loading the Keystore file File file = new File("mykeystore.jks"); SSLBuilder = SSLBuilder.loadTrustMaterial(file, "changeit".toCharArray()); //Building the SSLContext usiong the build() method SSLContext sslcontext = SSLBuilder.build(); //Creating SSLConnectionSocketFactory object SSLConnectionSocketFactory sslConSocFactory = new SSLConnectionSocketFactory(sslcontext, new NoopHostnameVerifier()); //Creating HttpClientBuilder HttpClientBuilder clientbuilder = HttpClients.custom(); //Setting the SSLConnectionSocketFactory clientbuilder = clientbuilder.setSSLSocketFactory(sslConSocFactory); //Building the CloseableHttpClient CloseableHttpClient httpclient = clientbuilder.build(); //Creating the HttpGet request HttpGet httpget = new HttpGet("https://example.com/"); //Executing the request HttpResponse httpresponse = httpclient.execute(httpget); //printing the status line System.out.println(httpresponse.getStatusLine()); //Retrieving the HttpEntity and displaying the no.of bytes read HttpEntity entity = httpresponse.getEntity(); if (entity != null) { System.out.println(EntityUtils.toByteArray(entity).length); } } }
输出
执行上述程序后,将生成以下输出。
HTTP/1.1 200 OK 1270
Apache HttpClient - 分块上传
使用HttpClient,我们可以执行分块上传,即我们可以将较大的对象分成较小的部分上传。在本章中,我们将通过上传一个简单的文本文件来演示HttpClient中的分块上传。
通常,任何分块上传都包含三个部分。
上传初始化
上传对象部分
完成分块上传
对于使用HttpClient的分块上传,我们需要遵循以下步骤:
创建一个多部分构建器。
向其中添加所需的部分。
完成构建并获得多部分HttpEntity。
通过设置上述多部分实体来构建请求。
执行请求。
以下是使用HttpClient库上传多部分实体的步骤。
步骤 1 - 创建 HttpClient 对象
`HttpClients`类的`createDefault()`方法返回`CloseableHttpClient`类的对象,它是HttpClient接口的基本实现。使用此方法创建HttpClient对象:
//Creating CloseableHttpClient object CloseableHttpClient httpclient = HttpClients.createDefault();
步骤2 - 创建FileBody对象
**FileBody**类表示由文件支持的二进制主体部分。通过传递一个**File**对象和一个表示内容类型的**ContentType**对象来实例化此类。
//Creating a File object File file = new File("sample.txt"); //Creating the FileBody object FileBody filebody = new FileBody(file, ContentType.DEFAULT_BINARY);
步骤3 - 创建MultipartEntityBuilder
**MultipartEntityBuilder**类用于构建多部分**HttpEntity**对象。使用**create()**方法(同一类)创建其对象。
//Creating the MultipartEntityBuilder MultipartEntityBuilder entitybuilder = MultipartEntityBuilder.create();
步骤4 - 设置模式
**MultipartEntityBuilder**有三种模式:STRICT、RFC6532和BROWSER_COMPATIBLE。使用**setMode()**方法将其设置为所需的模式。
//Setting the mode entitybuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
步骤5 - 添加各种所需的部分
使用**addTextBody()**、addPart()和**addBinaryBody()**方法,您可以将简单的文本、文件、流和其他对象添加到**MultipartBuilder**。使用这些方法添加所需的内容。
//Adding text entitybuilder.addTextBody("sample_text", "This is the text part of our file"); //Adding a file entitybuilder.addBinaryBody("image", new File("logo.png"));
步骤6 - 构建单个实体
您可以使用**MultipartEntityBuilder**类的**build()**方法将所有这些部分构建到单个实体中。使用此方法,将所有部分构建到单个**HttpEntity**中。
//Building a single entity using the parts HttpEntity mutiPartHttpEntity = entityBuilder.build();
步骤7 - 创建RequestBuilder对象
**RequestBuilder**类用于通过向其中添加参数来构建请求。如果请求类型为PUT或POST,则它会将参数作为URL编码实体添加到请求中。
使用**post()**方法创建一个(POST类型的)RequestBuilder对象。并将要向其发送请求的Uri作为参数传递给它。
//Building the post request object RequestBuilder reqbuilder = RequestBuilder.post("http://httpbin.org/post");
步骤8 - 将实体对象设置为RequestBuilder
使用**RequestBuilder**类的**setEntity()**方法将上面创建的多部分实体设置为RequestBuilder。
//Setting the entity object to the RequestBuilder reqbuilder.setEntity(mutiPartHttpEntity);
步骤9 - 构建HttpUriRequest
使用**RequestBuilder**类的**build()**方法构建**HttpUriRequest**请求对象。
//Building the request HttpUriRequest multipartRequest = reqbuilder.build();
步骤10 - 执行请求
使用**execute()**方法执行上一步中构建的请求(将请求作为参数传递给此方法)。
//Executing the request HttpResponse httpresponse = httpclient.execute(multipartRequest);
示例
以下示例演示如何使用HttpClient库发送多部分请求。在此示例中,我们尝试发送一个由文件支持的多部分请求。
import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; public class MultipartUploadExample { public static void main(String args[]) throws Exception{ //Creating CloseableHttpClient object CloseableHttpClient httpclient = HttpClients.createDefault(); //Creating a file object File file = new File("sample.txt"); //Creating the FileBody object FileBody filebody = new FileBody(file, ContentType.DEFAULT_BINARY); //Creating the MultipartEntityBuilder MultipartEntityBuilder entitybuilder = MultipartEntityBuilder.create(); //Setting the mode entitybuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); //Adding text entitybuilder.addTextBody("sample_text", "This is the text part of our file"); //Adding a file entitybuilder.addBinaryBody("image", new File("logo.png")); //Building a single entity using the parts HttpEntity mutiPartHttpEntity = entitybuilder.build(); //Building the RequestBuilder request object RequestBuilder reqbuilder = RequestBuilder.post("http://httpbin.org/post"); //Set the entity object to the RequestBuilder reqbuilder.setEntity(mutiPartHttpEntity); //Building the request HttpUriRequest multipartRequest = reqbuilder.build(); //Executing the request HttpResponse httpresponse = httpclient.execute(multipartRequest); //Printing the status and the contents of the response System.out.println(EntityUtils.toString(httpresponse.getEntity())); System.out.println(httpresponse.getStatusLine()); } }
输出
执行上述程序后,将生成以下输出:
{ "args": {}, "data": "", "files": { "image": "data:application/octets66PohrH3IWNk1FzpohfdXPIfv9X3490FGcuXsHn9X0piCwomF/xdgADZ9GsfSyvLYAAAAAE lFTkSuQmCC" }, "form": { "sample_text": "This is the text part of our file" }, "headers": { "Accept-Encoding": "gzip,deflate", "Connection": "close", "Content-Length": "11104", "Content-Type": "multipart/form-data; boundary=UFJbPHT7mTwpVq70LpZgCi5I2nvxd1g-I8Rt", "Host": "httpbin.org", "User-Agent": "Apache-HttpClient/4.5.6 (Java/1.8.0_91)" }, "json": null, "origin": "117.216.245.180", "url": "http://httpbin.org/post" } HTTP/1.1 200 OK