创建HTTP客户端
当执行一个完整内容的Http请求或者Http请求已经成功,服务器要发送响应到客户端时,Http实体就会被创建。通过HttpResponse的getEntity()方法可以获取HttpEntity,可以利用HttpEntity类的getContent方法来获取实体的输入流(java.io.InputStream),或者利用HttpEntity类的writeTo(OutputStream)方法来获取输出流,这个方法会把所有的内容写入到给定的流中或则使用EntityUtils。
最简单也是最方便的处理http响应的方法就是使用ResponseHandler接口,这个接口中有handleResponse(HttpResponse response)方法。使用这个方法,用户完全不用关心http连接管理器。当使用ResponseHandler时,HttpClient会自动地将Http连接释放给Http管理器,即使http请求失败了或者抛出了异常。
HttpClient已经实现了线程安全。所以在实例化HttpClient时,也要支持为多个请求使用。当一个CloseableHttpClient的实例不再被使用,并且它的作用范围即将失效,和它相关的连接必须被关闭,关闭方法可以调用CloseableHttpClient的close()方法。
一般说来,HttpClient实际上就是一系列特殊的handler或者说策略接口的实现,这些handler(测试接口)负责着处理Http协议的某一方面,比如重定向、认证处理、有关连接持久性和keep alive持续时间的决策。这样就允许用户使用自定义的参数来代替默认配置,实现个性化的功能。
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 也可以为客户端配置请求的参数,作为所有请求的默认值
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(5000)
.setConnectTimeout(5000)
.setSocketTimeout(5000)
.setCookieSpec(CookieSpecs.DEFAULT)
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.build();
创建GET请求
HttpGet httpGet = new HttpGet("http://localhost/index.html?param1=value1¶m2=value2");
HttpClient提供URIBuilder工具类来简化uri的创建
URI uri = null;
try {
uri= new URIBuilder()
.setScheme("http")
.setHost("localhost")
.setPath("/index.html")
.setParameter("param1", "value1")
.setParameter("param2", "value2")
.build();
} catch (URISyntaxException e) {
e.printStackTrace();
}
HttpGet httpGet = new HttpGet(uri);
如果参数中含有中文,需将参数进行URLEncoding处理
URI uri = null;
try {
uri = new URIBuilder()
.setScheme("http")
.setHost("localhost")
.setPath("/index.html")
.setParameter("param1", URLEncoder.encode("中国", "UTF-8"))
.setParameter("param2", "value2")
.build();
} catch (UnsupportedEncodingException | URISyntaxException e) {
e.printStackTrace();
}
HttpGet httpGet = new HttpGet(uri);
可以为单个请求设置一些配置
httpGet.setConfig(RequestConfig.DEFAULT);
创建POST请求
HttpPost httpPost = new HttpPost("http://www.baidu.com");
httpPost的uri和RequestConfig设置同httpGet。可以为httpGet和httpPost设置消息头
httpPost.addHeader(HttpHeaders.CONTENT_TYPE, "application/octet-stream;charset=utf-8");
httpGet.addHeader(HttpHeaders.ACCEPT, "application/xml");
执行请求
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpGet);
// 获取HTTP响应的状态码
int status = response.getStatusLine().getStatusCode();
System.out.println(status);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (response != null) response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
CloseableHttpResponse response = null;
try {
CloseableHttpResponse response = httpClient.execute(httpPost);
System.out.println(response.getStatusLine());
System.out.println(response.getAllHeaders());
System.out.println(response. getHeaders(HttpHeaders.CONTENT_TYPE);
System.out.println(response.getEntity());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (response != null) response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
使用HttpEntity
当执行一个完整内容的Http请求或者Http请求已经成功,服务器要发送响应到客户端时,Http实体就会被创建。通过HttpResponse的getEntity()方法可以获取HttpEntity,可以利用HttpEntity类的getContent方法来获取实体的输入流(java.io.InputStream),或者利用HttpEntity类的writeTo(OutputStream)方法来获取输出流,这个方法会把所有的内容写入到给定的流中或则使用EntityUtils。
// 获取响应的HttpEntity
HttpEntity entity = response.getEntity();
Header type = entity.getContentType();//Content-Type
long length = entity.getContentLength();//Content-Length
Header encoding = entity.getContentEncoding();
// 获取响应的媒体类型, 例如:text/html
String contentMimeType = ContentType.getOrDefault(entity).getMimeType();
// 获取响应的BODY部分
String bodyAsString = EntityUtils.toString(entity);
InputStream instream = entity.getContent();
try {
// do something useful
} finally {
instream.close();
}
有些情况下,希望可以重复读取Http实体的内容。这就需要把Http实体内容缓存在内存或者磁盘上。最简单的方法就是把Http Entity转化成BufferedHttpEntity,这样就把原Http实体的内容缓冲到了内存中。后面就可以重复读取BufferedHttpEntity中的内容。
HttpEntity entity = response.getEntity();
if (entity != null) {
entity = new BufferedHttpEntity(entity);
}
模拟提交Html表单请求
HttpPost httpPost = new HttpPost("http://www.baidu.com");
// 拼接参数
List<NameValuePair> formparams = new ArrayList<>();
formparams.add(new BasicNameValuePair("username", "vip"));
formparams.add(new BasicNameValuePair("password", "secret"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
httpPost.setEntity(entity);
发送二进制
httpPost.addHeader("Content-Type", "application/octet-stream;charset=utf-8");
httpPost.setEntity(new ByteArrayEntity(bytes));
ResponseHandler
最简单也是最方便的处理http响应的方法就是使用ResponseHandler接口,这个接口中有handleResponse(HttpResponse response)方法。使用这个方法,用户完全不用关心http连接管理器。当使用ResponseHandler时,HttpClient会自动地将Http连接释放给Http管理器,即使http请求失败了或者抛出了异常。
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://www.yeetrack.com/json");
ResponseHandler<MyJsonObject> rh = new ResponseHandler<MyJsonObject>() {
@Override
public JsonObject handleResponse(
final HttpResponse response) throws IOException {
StatusLine statusLine = response.getStatusLine();
HttpEntity entity = response.getEntity();
if (statusLine.getStatusCode() >= 300) {
throw new HttpResponseException(
statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
if (entity == null) {
throw new ClientProtocolException("Response contains no content");
}
Gson gson = new GsonBuilder().create();
ContentType contentType = ContentType.getOrDefault(entity);
Charset charset = contentType.getCharset();
Reader reader = new InputStreamReader(entity.getContent(), charset);
return gson.fromJson(reader, MyJsonObject.class);
}
};
//设置responseHandler,当执行http方法时,就会返回MyJsonObject对象。
MyJsonObject myjson = client.execute(httpget, rh);
HttpClient已经实现了线程安全。所以在实例化HttpClient时,也要支持为多个请求使用。当一个CloseableHttpClient的实例不再被使用,并且它的作用范围即将失效,和它相关的连接必须被关闭,关闭方法可以调用CloseableHttpClient的close()方法。
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
<...>
} finally {
//关闭连接
httpclient.close();
}
HttpClient接口没有对Http请求的过程做特别的限制和详细的规定,连接管理、状态管理、授权信息和重定向处理这些功能都单独实现。这样用户就可以更简单地拓展接口的功能(比如缓存响应内容)。
一般说来,HttpClient实际上就是一系列特殊的handler或者说策略接口的实现,这些handler(测试接口)负责着处理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-alive这个参数,我们就把它设置成5秒
keepAlive = 5000;
}
return keepAlive;
}
};
//定制我们自己的httpclient
CloseableHttpClient httpclient = HttpClients.custom()
.setKeepAliveStrategy(keepAliveStrat)
.build();
参考:
http://www.yeetrack.com/?p=779