所有的Demo都在https://httpbin.org/上测试,这真是个了解Http协议的好网站,推荐一下。
get请求
/**
* httpClient执行get请求
*/
@Test
public void getMethodDemo() throws IOException, URISyntaxException {
URI uri = new URIBuilder()
.setScheme("http")
.setHost("www.httpbin.org")
.setPath("get")
.setParameter("test", "hello")
.setParameter("q", "httpclient")
.build();
httpRequest = new HttpGet(uri);
}
如果执行post请求只需将HttpGet换成HttpPost即可
Http协议中只有Post,Put和Patch三种方法支持实体内容的发送。
HttpClient中支持的实体内容种类有二十多种,常用的应该有以下几种:StringEntity, ByteArrayEntity,InputStreamEntity和 FileEntity
下面的Demo以Post方法发送StringEntity为例:
请求添加http实体
/**
* httpClient通过post发送实体
*/
@Test
public void sendEntityDemo() throws IOException, URISyntaxException {
URI uri = new URIBuilder()
.setScheme("http")
.setHost("www.httpbin.org")
.setPath("post")
.build();
HttpPost httpPost = new HttpPost(uri);
StringEntity stringEntity = new StringEntity("string entity");
httpPost.setEntity(stringEntity);
httpRequest = httpPost;
}
HttpClient使用策略模式将Http设置封装为一组接口,这使我们能够选择性地用自定义这些设置,例如连接管理,状态管理,认证和重定向。
keep-alive设置
ConnectionKeepAliveStrategy keepAliveStrat = new DefaultConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(
HttpResponse response,
HttpContext context) {
long keepAlive = super.getKeepAliveDuration(response, context);
if (keepAlive == -1) {
// Keep connections alive 5 seconds if a keep-alive value
// has not be explicitly set by the server
keepAlive = 5000;
}
return keepAlive;
}
};
CloseableHttpClient httpclient = HttpClients.custom()
.setKeepAliveStrategy(keepAliveStrat)
.build();
HttpClient自动为我们处理了重定向。下面是一个查看重定向URI的例子:
查看重定向URI
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpClientContext context = HttpClientContext.create();
HttpGet httpget = new HttpGet("http://www.httpbin.org/redirect/6");
CloseableHttpResponse response = httpclient.execute(httpget, context);
try {
HttpHost target = context.getTargetHost();
List redirectLocations = context.getRedirectLocations();
System.out.println(redirectLocations);
URI location = URIUtils.resolve(httpget.getURI(), target, redirectLocations);
System.out.println("Final HTTP location: " + location.toASCIIString());
} finally {
response.close();
httpclient.close();
}
发生重定向时之前传递的参数默认不会被传递到重定向的urI,这一点需要注意。
通过RequestConfig类进行超时时间的设定:
超时设定
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(1000)
.setConnectTimeout(1000)
.build();
HttpGet httpget = new HttpGet("http://localhost/1");
httpget.setConfig(requestConfig);
//还可以放在HttpClient的设置中将这个超时设置为默认配置
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.build();
通过HttpClientBuilder#setRoutePlanner()方法或者RequestConfig.Builder#setProxy()可以设置代理,这里大家可以用自己的Http代理来试验下面的代码。
代理设置
HttpHost proxy = new HttpHost("proxy", port);
// 方法一:通过requestConfig设置代理
requestConfig = RequestConfig.custom()
.setProxy(proxy)
.build();
httpRequest.setRequestConfig(requestConfig);
// 方法二:通过setRoutePlanner设置全局代理
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
httpClient = HttpClients.custom()
.setRoutePlanner(routePlanner)
.build();
URI uri = new URIBuilder()
.setScheme("http")
.setHost("www.httpbin.org")
.setPath("get")
.setParameter("test", "hello")
.setParameter("q", "httpclient")
.build();
httpRequest = new HttpGet(uri);
1.2.5 BA认证
1.2.6 重试设置
我们可以使用HttpRequestRetryHandler设置重试策略,处理当一些异常抛出的情况。
重试策略
HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
public boolean retryRequest(
IOException exception,
int executionCount,
HttpContext context) {
if (executionCount >= 5) {
// Do not retry if over max retry count
return false;
}
if (exception instanceof InterruptedIOException) {
// Timeout
return false;
}
if (exception instanceof UnknownHostException) {
// Unknown host
return false;
}
if (exception instanceof ConnectTimeoutException) {
// Connection refused
return false;
}
if (exception instanceof SSLException) {
// SSL handshake exception
return false;
}
HttpClientContext clientContext = HttpClientContext.adapt(context);
HttpRequest request = clientContext.getRequest();
boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
if (idempotent) {
// Retry if the request is considered idempotent
return true;
}
return false;
}
};
CloseableHttpClient httpclient = HttpClients.custom()
.setRetryHandler(myRetryHandler)
.build();
我们可以使用ResponseHandler接口来对Http返回结果做处理,这个接口有一个handleResponse方法,接收一个HttpResponse参数,返回一个T类型参数。
ResponseHandler
@After
public void requestWithResponseHandler() throws IOException {
String responseStr = httpClient.execute(httpRequest, (response) ->IOUtils.toString(response.getEntity().getContent(), "utf-8"));
System.out.println(responseStr);
}
在执行http请求时直接把responseHandler添加在HttpClient#executed的参数中,这样直接返回一个处理之后的对象。这样做的好处是HttpClient会自动关闭Entity#getContent()的流,详情可以看源码。
参考:httpclient官方文档