HttpClient系列-基础知识(一)

简述

今天开始介绍下Apache HttpClient 4的全面指南,从基础到高级进阶,本文是基础知识一。

状态码

从Http响应中得出状态码

发送Http请求后 - 我们返回一个org.apache.http.HttpResponse实例,我们可以获取到响应的状态行,并隐式地访问状态代码:

response.getStatusLine().getStatusCode()
复制代码

使用它,我们可以验证从服务器收到的代码是否是正确的:

@Test
public void test() 
  throws ClientProtocolException, IOException {
    HttpClient client = HttpClientBuilder.create().build();    
    HttpResponse response = client.execute(new HttpGet(SAMPLE_URL));
    int statusCode = response.getStatusLine().getStatusCode();
    assertThat(statusCode, equalTo(HttpStatus.SC_OK));
}
复制代码

这里面,使用org.apache.http.HttpStatus中库中提供的预定义状态代码。

超时

HttpClient可以配置超时的时间,接下来,我们看下如何使用。

通过字符串参数配置超时

HttpClient的自带了大量的配置参数,而所有的这些都可以在一个通用的Map集合中来设置。

有3个超时参数配置:

DefaultHttpClient httpClient = new DefaultHttpClient();
 
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(
  CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));
复制代码

通过API配置超时

这些参数中更重要的 - 即前两个 - 也可以通过更安全的API进行设置:

DefaultHttpClient httpClient = new DefaultHttpClient();
 
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(
  httpParams, timeout * 1000); // http.connection.timeout
HttpConnectionParams.setSoTimeout(
  httpParams, timeout * 1000); // http.socket.timeout
复制代码

第三个参数在HttpConnectionParams中没有自定义setter ,它仍然需要通过setParameter方法手动设置。

使用新的4.3配置超时

4.3中引入新API来设置超时的方法,这个更方便快捷:

int timeout = 5;
RequestConfig config = RequestConfig.custom()
  .setConnectTimeout(timeout * 1000)
  .setConnectionRequestTimeout(timeout * 1000)
  .setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = 
  HttpClientBuilder.create().setDefaultRequestConfig(config).build();
复制代码

这是以类型安全且可读的方式配置所有三个超时的推荐方法。

超时属性说明

现在,让我们解释一下这些不同类型的超时意味着什么:

  • 连接超时(http.connection.timeout) - 建立与远程主机的连接的时间
  • socket超时(http.socket.timeout) - 等待数据的时间-建立连接后; 两个数据包之间的最长不活动时间
  • 连接管理器超时(http.connection-manager.timeout) - 从连接管理器/池中获取一个连接的等待时间。

前两个参数,connection和socket超时是最重要的。但是,在高负载情况下设置获取连接的超时非常重要,这就是不应忽略第三个参数的原因。

强制超时

虽然设置建立HTTP连接和不接收数据的超时非常有用,但有时我们需要为整个请求设置强制超时。

例如,可能大型文件的下载符合此类别。在这种情况下,可以成功建立连接,数据可以一直通过,但是我们仍然需要确保操作不会超过某个特定时间阈值。

HttpClient没有任何允许我们为请求设置总超时的配置; 但是,它确实为请求提供了中止功能,因此我们可以利用该机制实现一个简单的超时机制:


HttpGet getMethod =new HttpGet("http://localhost:8080/");


int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        if (getMethod != null) {
            getMethod.abort();
        }
    }
};
new Timer(true).schedule(task, hardTimeout * 1000);
 
HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());
复制代码

我们正在利用java.util.Timerjava.util.TimerTask来设置一个简单的延迟任务,该任务在5秒强制超时后中止HTTP GET请求。

DNS循环超时

一些较大的域名将使用DNS循环配置是很常见的,基本上具有映射到多个IP地址的相同域名。这引发了针对此类域的超时的新挑战,原因很简单,因为HttpClient将尝试连接到超时的域:

HttpClient获取到该域的IP路由列表 它尝试第一个 - 超时 它尝试第二个 - 也超时 等等 … 因此,正如你所看到的 - 当我们期望它时,整体操作不会超时。相反 - 当所有可能的路线超时时它会超时。更重要的是 - 这将完全透明地发生在客户端上(除非你在DEBUG级别配置了日志)。

这是一个可以运行并复制此问题的简单示例:

int timeout = 3;
RequestConfig config = RequestConfig.custom().
  setConnectTimeout(timeout * 1000).
  setConnectionRequestTimeout(timeout * 1000).
  setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = HttpClientBuilder.create()
  .setDefaultRequestConfig(config).build();

HttpGet request =new  HttpGet("http://www.domain.com");

 response = client.execute(request);
复制代码

你将注意到具有DEBUG日志级别的重试逻辑:

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.domain.com/173.194.34.212:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator - 
 Connect to www.domain.com/173.194.34.212:81 timed out. Connection will be retried using another IP address
 
DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.domain.com/173.194.34.208:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator - 
 Connect to www.domain.com/173.194.34.208:81 timed out. Connection will be retried using another IP address
 
DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.domain.com/173.194.34.209:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator - 
 Connect to www.domain.com/173.194.34.209:81 timed out. Connection will be retried using another IP address
//...
复制代码

小结

本文介绍了状态码和超时的配置以及机制,希望对你有所帮助。

转载于:https://juejin.im/post/5d0a079c6fb9a07ed524a40b

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用Apache HttpClient库来发送带有form-data的HTTP请求。以下是一个示例代码: ```java import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; public class HttpClientExample { public static void main(String[] args) throws Exception { // 创建HttpClient实例 HttpClient httpClient = HttpClientBuilder.create().build(); // 创建HttpPost请求 HttpPost httpPost = new HttpPost("http://example.com/upload"); // 创建MultipartEntityBuilder来构建form-data请求体 MultipartEntityBuilder builder = MultipartEntityBuilder.create(); // 添加文本参数 builder.addTextBody("username", "John Doe"); // 添加文件参数 File file = new File("path/to/file.txt"); builder.addBinaryBody("file", file); // 设置请求体 HttpEntity multipart = builder.build(); httpPost.setEntity(multipart); // 发送请求并获取响应 HttpResponse response = httpClient.execute(httpPost); HttpEntity responseEntity = response.getEntity(); // 解析响应 String responseBody = EntityUtils.toString(responseEntity); // 处理响应数据 System.out.println(responseBody); // 关闭HttpClient连接 httpClient.close(); } } ``` 上述代码创建了一个带有form-data的POST请求,并发送到指定的URL。你可以使用`addTextBody`方法添加文本参数,使用`addBinaryBody`方法添加文件参数。最后获取响应并处理响应数据。 请注意,以上示例使用的是Apache HttpClient 4.x版本。确保你的项目中包含相应的依赖库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值