HttpClient的使用
一、maven坐标
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
二、 主要API
2.1 CloseableHttpClient
表示Http客户端对象,用来发送请求并得到响应。线程安全,如果项目中只是偶尔httpclinet,建议每次使用时都新建、关闭此对象。如果项目中频繁使用httpclinet,建议把此对象作为单例使用;
httpClient.execute(request); // 执行get、post等请求
httpClient.close(); // 关闭此客户端对象,释放资源
2.2 HttpClients
用来创建HttpClinet对象的工具类
createDefault(); /创建默认的CloseableHttpClient对象
2.3 URIBuilder
用来构建URI,可以方便的在请求路径后面追加查询字符串
URI uri = new URIBuilder("http://localhost:8080/test")// 设置请求路径
.setCharset(Charset.forName("UTF-8"))// 设置编码(默认为项目编码),一般不用设置
.addParameter("k1", "v1")// 连续调用此方法可以设置多个请求参数
.build();// 构建并返回URI对象
URI
表示一个资源路径,可以认为等价于URL
2.4 HttpGet
表示一个get请求对象
HttpGet httpGet = new HttpGet(uri);
httpGet.addHeader("h1", "v1");
2.5 HttpPost
表示一个post请求对象
HttpPost httpPost = new HttpPost("http://localhost:8080/test/test2");
httpPost.addHeader("h1", "v1");
2.6 HttpEntity
表示一个请求体
2.7 StringEntity
表示字符串请求体
StringEntity entity = new StringEntity("hello httpclient !", "UTF-8");
2.8 NameValuePair
表示一对键值对数据
NameValuePair param = new BasicNameValuePair("age", "16");
2.9 UrlEncodedFormEntity
表示进行URL编码的、符合表单提交格式的字符串请求体
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("name", "蛋蛋"));
params.add(new BasicNameValuePair("age", "16"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
httpPost.setEntity(entity);
2.10 InputStreamEntity
表示字节流形式的请求体
InputStreamEntity entity = new InputStreamEntity(instream);
2.11 CloseableHttpResponse
表示一个响应对象
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
httpResponse.headerIterator();//响应头迭代器
HttpEntity resultEntity = httpResponse.getEntity();//响应体数据
2.12 HttpEntity
表示一个响应体(和请求体是同一个类)
HttpEntity resultEntity = httpResponse.getEntity();
// 使用流的方式操作响应体数据
InputStream inputStream = resultEntity.getContent();
// 如果响应体是字符串数据,可能需要字符编码信息
Header header = resultEntity.getContentEncoding();
2.13 EntityUtils
可以方便取出响应体数据的工具类,因为此工具类会把所有响应体数据全部缓存到内存中,所以如果响应体数据量较大的话建议直接使用httpEntity.getContent()获取到响应体的读取流,进行流操作;
HttpEntity resultEntity = httpResponse.getEntity();
//此方法会自动根据响应头中的编码信息对响应体内容进行编码,也可以手动指定编码
String result = EntityUtils.toString(resultEntity);
三、 案例代码
注意:
httpclinet可自动管理cookie,所以支持session会话
- 如果发送请求或者接收响应过程中出现的IOException,httpclinet默认会重新发送请求(尝试5次),可能会造成服务器重复处理此请求,如果此请求会修改数据库,就可能造成数据错乱。所以如果某个请求不允许这种情况出现的话,可以禁用重复发送功能;
CloseableHttpClient httpclient = HttpClients.custom()
.setRetryHandler(new StandardHttpRequestRetryHandler(0, false)).build();
3.1 发送不带请求参数的get请求
CloseableHttpClient httpClient = null;
CloseableHttpResponse httpResponse = null;
try {
httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://localhost:8080/test");
httpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity entity = httpResponse.getEntity();
String result = EntityUtils.toString(entity);
// 处理result的代码...
} finally {
if (httpResponse != null) {
httpResponse.close();
}
if (httpClient != null) {
httpClient.close();
}
}
3.2 发送携带请求参数的get请求
CloseableHttpClient httpClient = null;
CloseableHttpResponse httpResponse = null;
try {
httpClient = HttpClients.createDefault();
URI uri = new URIBuilder("http://localhost:8080/test")// 设置请求路径
.setCharset(Charset.forName("UTF-8"))// 设置编码(默认为项目编码),一般不用设置
.addParameter("k1", "v1")// 连续调用此方法可以设置多个请求参数
.build();// 构建并返回URI对象
HttpGet httpGet = new HttpGet(uri);
httpResponse = httpClient.execute(httpGet);
HttpEntity entity = httpResponse.getEntity();
String result = EntityUtils.toString(entity);
// 处理result的代码...
} finally {
if (httpResponse != null) {
httpResponse.close();
}
if (httpClient != null) {
httpClient.close();
}
}
3.3 发送不带请求参数以及其他请求体数据的post请求
CloseableHttpClient httpClient = null;
CloseableHttpResponse httpResponse = null;
try {
httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://localhost:8080/test");
httpResponse = httpClient.execute(httpPost);
HttpEntity entity = httpResponse.getEntity();
String result = EntityUtils.toString(entity);
// 处理result的代码...
} finally {
if (httpResponse != null) {
httpResponse.close();
}
if (httpClient != null) {
httpClient.close();
}
}
3.4 发送携带表单格式请求参数的post请求
CloseableHttpClient httpClient = null;
CloseableHttpResponse httpResponse = null;
try {
httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://localhost:8080/test");
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("name", "Hali"));
params.add(new BasicNameValuePair("age", "16"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
httpPost.setEntity(entity);
httpResponse = httpClient.execute(httpPost);
HttpEntity resultEntity = httpResponse.getEntity();
String result = EntityUtils.toString(resultEntity);
// 处理result的代码...
} finally {
if (httpResponse != null) {
httpResponse.close();
}
if (httpClient != null) {
httpClient.close();
}
}
3.5 发送携带一般字符串请求体数据的post请求
CloseableHttpClient httpClient = null;
CloseableHttpResponse httpResponse = null;
try {
httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://localhost:8080/test");
StringEntity entity = new StringEntity("hello httpclient !", "UTF-8");
httpPost.setEntity(entity);
httpResponse = httpClient.execute(httpPost);
HttpEntity resultEntity = httpResponse.getEntity();
String result = EntityUtils.toString(resultEntity);
// 处理result的代码...
} finally {
if (httpResponse != null) {
httpResponse.close();
}
if (httpClient != null) {
httpClient.close();
}
}
3.6 发送 https的get请求
/**
* 创建一个可以访问Https类型URL的工具类,返回一个CloseableHttpClient实例
*/
public static CloseableHttpClient createSSLClientDefault(){
try {
SSLContext sslContext=new SSLContextBuilder().loadTrustMaterial(
null,new TrustStrategy() {
//信任所有
public boolean isTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf=new SSLConnectionSocketFactory(sslContext);
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
return HttpClients.createDefault();
}
/**
* @throws IOException
* @throws ClientProtocolException
*
*/
public static void main(String[] args) throws ClientProtocolException, IOException {
//从工具方法中获得对应的可以访问Https的httpClient
CloseableHttpClient httpClient =createSSLClientDefault();
HttpGet httpGet=new HttpGet("https://etrade.ccbfund.cn/etrading/tradereq/main.do?method=doInit&isHome=1&menuId=10000");
//自己先在浏览器登录一下,自行复制具体的Cookie
httpGet.setHeader("Cookie", "HS_ETS_SID=4jSFY2wWwT0gPrWJ45ly!-1286216704; Null=31111111.51237.0000; logtype=2; certtype=0; certNo=33****************; isorgloginpage_cookie=0; hs_etrading_customskin=app_css");
//设置代理,方便Fiddle捕获具体信息
RequestConfig config=RequestConfig.custom()
.setProxy(HttpHost.create("127.0.0.1:8888"))
.build();
httpGet.setConfig(config);
//执行get请求,获得对应的响应实例
CloseableHttpResponse response=httpClient.execute(httpGet);
//打印响应的到的html正文
HttpEntity entity =response.getEntity();
String html=EntityUtils.toString(entity);
System.out.println(html);
//关闭连接
response.close();
httpClient.close();
}
四、 一个简单的HttpClientUtil
地址: https://github.com/lunarku/Code_Snippets/blob/master/CodeSnippets/jdk/src/main/java/jdk/util/http/HttpClientUtils.java