前言

由于HttpClient 4.x.x 是从原包的分支出来独立成包的,以后原来那个包的httpclient 不会再升级,所以以后我们是用httpclient 新分支。而且 4.x 与之前的 3.1 包结构以及接口都有较大变化,不仅如此,在4.3.x 相对于 4.2及以前版本又废弃了很多方法。故对于要升级到httpclient_4.3.x的资料和文档之类的都需要对应版本,非对应的版本可能引入其他漏洞

4.3.x  官方参考资料如下:

HttpClient 官方下载路径 ​​http://hc.apache.org/downloads.cgi​

HttpClient 官方资料 ​​http://hc.apache.org/httpcomponents-client-4.3.x/index.html​

HttpClient api ​​http://hc.apache.org/httpcomponents-client-4.3.x/httpclient/apidocs/index.html​

HttpClient Tutorial ​​http://hc.apache.org/httpcomponents-client-4.3.x/tutorial/html/index.html​

1      什么是HttpClient

1.1       简介

HttpClient 不是一个浏览器。它是一个客户端的HTTP通信实现库。HttpClient的目的是发送和接收HTTP报文。

HttpClient 提供的主要功能

(1)实现了所有 HTTP 的方法(GET,POST,PUT,HEAD等)

(2)支持自动转向

(3)支持 HTTPS 协议

(4)支持代理服务器等

1.2       httpClient的使用步骤

l  创建 HttpClient 的实例

l  创建某种连接方法的实例,在这里是 GetMethod。在 GetMethod 的构造函数中传入待连接的地址

l  调用第一步中创建好的实例的 execute 方法来执行第二步中创建好的 method 实例

l  读 response

l  释放连接。无论执行方法是否成功,都必须释放连接

l 对得到后的内容进行处理

2

2.1      执行请求

HttpClient 最重要的功能是执行Http方法。执行一个HTTP方法涉及一个或多个HTTP请求/HTTP响应信息的交流,通常由HttpClient的内部来处理。用户提供一个要执行的请求对象, HttpClient发送请求到目标服务器,期望服务器返回对应的响应对象,或者当执行不成功时抛出异常。

 

2.1.1HttpClient_3

使用httpClient 3 执行get 和 post 请求的执行过程,并得到响应结果的过程示例如下,由程序可知httpClient的响应结果可以多次读取:



//创建一个url作为请求路径
//String url = protocol + "://" + ip + ":" + port + request.getRequestURI();
String url = "http://10.137.152.171:5764";
//创建一个默认的HttpClient 实例
HttpClient client = new HttpClient();
//创建一个请求方法,这里写了post和get 两种方式
//HttpMethod method = new PostMethod(url);
HttpMethod method = new GetMethod(url);
try
{
//得到返回响应码,返回的值为200 表示响应成功
int statusCode = client.executeMethod(method);
if (200 == statusCode)
{
//返回响应结果,HttpClient 的三种常用返回响应结果的方法
byte[] bytes = method.getResponseBody();
String str = method.getResponseBodyAsString();
InputStream in = method.getResponseBodyAsStream();
}
}
catch (HttpException e)
{ //<...>
}

 

2.1.2HttpClient_4.3.x

使用httpClient 4.3.x 执行get 和 post 请求的执行过程,并得到响应结果的过程示例如下, httpClient的响应内容只可以读取一次,若是需要多次读取,需要先储存起来,以免数据丢失。

httpClient 提供了直接读取消息实体的类EntityUtils.toString(),但该类使用有一定的限制,一般不建议使用,推荐使用HttpEntity#getContent() 或HttpEntity#writeTo(OutputStream)

String url = "http://10.137.152.171:7548";
// 创建默认的HttpClient 实例
CloseableHttpClient httpclient = HttpClients.createDefault();
// 创建一个请求方法,这里提供了get和post两种方式
// HttpGet httpget = new HttpGet(url);
// HttpPost httppost = new HttpPost(url);
HttpUriRequest request = new HttpPost(url);
// 创建一个响应对象
CloseableHttpResponse response = null;
try
{
//执行请求得到响应结果
response = httpclient.execute(request);
//得到返回响应码,返回的值为200 表示响应成功
int statusCode = response.getStatusLine().getStatusCode();
//得到响应消息实体
HttpEntity entity = response.getEntity();
//得到响应消息内容
//InputStream in = entity.getContent();
if (entity != null)
{
//打印响应内容长度
System.out.println(entity.getContentLength());
//打印响应内容
System.out.println(EntityUtils.toString(entity));
}
//确保它被完全消耗
EntityUtils.consume(entity);
}
catch (IOException e)
{ //<...>}
finally
{//要释放响应流
response.close();
}


2.2      设置请求头(具体请参见API)

在发送Http请求的时候,需要设置请求头。

2.2.1HttpClient_3

HttpClient_3 设置请求头有两种方式,由API可知,HttpMethod#addRequestHeader()默认会将指定头添加到末尾,不会覆盖先前的值,如果出现多个值,会造成头识别报错。HttpMethod#setRequestHeader() 重新设置指定的头文件,会覆盖之前的值

2.2.2HttpClient_4.3.x

HttpClient_4 设置请求头有两种方式, HttpGet 或 HttpPost 等请求设置方法相同。由API可知,HttpGet#addHeader()默认会将指定头添加到末尾,不会覆盖先前的值。HttpGet#setHeader() 重新设置指定的头文件,会覆盖相同名字的值

2.3      添加参数

HttpClient 提供了一个实用的方法所有的Http请求有一个包含方法名,请求URI和HTTP协议版本的请求行。HttpClient 支持在HTTP/1.1 规范中定义的所有HTTP方法:GET、HEAD、POST、PUT、DELETE、TRACE 和 OPTIONS,用一些特殊的类来表示每一个方法:HttpGet、HttpPost、HttpHead、HttpPut、HttpDelete、HttpTrance 和 HttpOptions 。

 

HTTP 请求URI 的包含协议、主机名、可选的端口、资源的路径、可选的查询和可选的片段。

HTTP请求格式告诉我们,有两种方式可以为request 提供参数:request-line 方式与 request-body 方式。这里只做Get 和Post 请求添加参数的介绍。request-body 方式只适用于Post 请求。

2.3.1HttpClient_3

request-line 方式是指在请求行上通过URI 直接提供参数。

HttpClient_3 可以使用该函数getQueryString()直接添加参数,GetMethod 一般使用该方法,HttpClient_4 无此函数

 

PostMethod 添加参数addParameter()还有如下方法

 

2.3.2HttpClient_4.3.x

request-line 方式是指在请求行上通过URI 直接提供参数。

1)  request 对象时提供带参数的URI,如:



HttpUriRequest request1 = new HttpGet("http://localhost/index.html?param1=value1¶m2=value2");

         

 

 

2)  HttpClient 提供URIBuilder 来创建和修改URI(这是针对4.3的,之前版本不使用该方法)



 

URI uri = new URIBuilder()
.setScheme("http")
.setHost("www.google.com")
.setPath("/search")
.setParameter("param1", "value1")
.setParameter("param2", "value2")
.build();

 

Request-body 是在request-body中提供参数,此方式只能用于POST请求

1)使用UrlEncodedFormEntity 类

List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("param1", "value1"));
formparams.add(new BasicNameValuePair("param2", "value2"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
HttpPost httppost = new HttpPost("http://localhost/handler.do");
httppost.setEntity(entity);
System.out.println(httppost.getURI());


运行结果:http://localhost/handler.do? param1=value1&param2=value2

2)除了传统的application/x-www-form-urlencoded 表单,经常用到的是上传文件用的表单,这种表单类型为multipart/form-data . 在HttpClient 中MultipartEntityBuilder类与之对应

HttpEntity reqEntity = MultipartEntityBuilder.create()
.addPart("bin", bin)
.addPart("comment", comment)
.build();
httppost.setEntity(reqEntity);


示例如下:

CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httppost = new HttpPost("http://localhost:8080");
FileBody bin = new FileBody(new File(args[0]));
StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN);

HttpEntity reqEntity = MultipartEntityBuilder.create()
.addPart("bin", bin)
.addPart("comment", comment)
.build();
httppost.setEntity(reqEntity);
System.out.println("executing request " + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
System.out.println(response.getStatusLine());
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
System.out.println("Response content length: " + resEntity.getContentLength());
}
EntityUtils.consume(resEntity);
} finally {
response.close();
}
} finally {
httpclient.close();
}




 

2.4      设置连接超时

设置HttpClient 连接服务器的时间

2.4.1HttpClient_3

HttpClient client = new HttpClient();        client.getHttpConnectionManager().getParams().setConnectionTimeout(connTimeout);        client.getHttpConnectionManager().getParams().setSoTimeout(readTimeout);
2.4.2HttpClient_4.3.xCloseableHttpClient httpclient = HttpClients.createDefault();
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(1000)
.setConnectTimeout(1000)
.build();
HttpGet httpget1 = new HttpGet("http://localhost");
httpget1.setConfig(requestConfig);

RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(30000)
.setSocketTimeout(30000)
.build();
CloseableHttpClient client = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.build();