1、简介
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。
HttpClient 相比传统 JDK 自带的 URLConnection
,增加了易用性和灵活性,它不仅是客户端发送 HTTP 请求变得容易,而且也方便了开发人员测试接口(基于 HTTP 协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握 HttpClient 是很重要的必修内容,掌握 HttpClient 后,相信对于 HTTP 协议的了解会更加深入。
2、引入依赖
HttpClient 是三方工具,首先需要引入依赖。如下:
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.1.1</version>
</dependency>
3、获取客户端
在使用时,首先需要 获取 HttpClient 对象,有如下几种获取方式
-
默认创建方式
CloseableHttpClient httpClient = HttpClients.createDefault();
-
根据系统配置创建
CloseableHttpClient httpClient = HttpClients.createSystem();
在项目启动时可以通过设置如下JVM启动参数:
- http.agent 配置 userAgent
- http.keepAlive 配置 keepAlive 数据
-
自定义创建
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultHeaders(Collections.emptyList())
.setDefaultRequestConfig(RequestConfig.DEFAULT)
.build();
4、配置参数
HttpClient 可以通过在创建 HttpClient 对象时就设置全局配置,也可以为单个请求设置请求配置。
-
创建配置对象
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(Timeout.of(3000, TimeUnit.MILLISECONDS))
.setResponseTimeout(3000, TimeUnit.MILLISECONDS)
.setConnectionRequestTimeout(3000, TimeUnit.MILLISECONDS)
.build();
-
设置全局配置
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultHeaders(Collections.emptyList())
.setDefaultRequestConfig(requestConfig)
.build();
-
单个请求设置配置
HttpGet httpGet = new HttpGet(uri);
httpGet.setConfig(requestConfig);
5、设置请求头信息
在请求时,经常会遇到设置自定义请求头,或者更改 Conent-Type
的值,可以通过如下两种方式设置:
-
设置公共请求头
List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON));
headers.add(new BasicHeader(HttpHeaders.ACCEPT_ENCODING, "gzip, x-gzip, deflate"));
headers.add(new BasicHeader(HttpHeaders.CONNECTION, "keep-alive"));
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultHeaders(headers)
.build()
-
单个请求设置请求头
HttpPost httpPost = new HttpPost(uri);
httpPost.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED);
httpPost.addHeader(new BasicHeader(HttpHeaders.ACCEPT, "*/*"));
6、发送请求
GET 请求
GET请求的所有参数是直接拼接在 URL 后面的,在 HttpClient 中 有两种方式可以实现,如下所示:
-
请求参数直接拼接在请求路径后面
String name = URLEncoder.encode("张三", "utf-8");
String url = "http://localhost:10010/user/params?age=20&name=" + name;
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpClient.execute(httpGet);
int code = response.getCode();
if(code == HttpStatus.SC_OK){
LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
}
-
通过 URIBuilder 构建请求路径
URL url = new URL("http://localhost:10010/user/params");
URI uri = new URIBuilder()
.setScheme(url.getProtocol())
.setHost(url.getHost())
.setPort(url.getPort())
.setPath(url.getPath())
.setParameters(
new BasicNameValuePair("name", "张三"),
new BasicNameValuePair("age", "20")
).build();
HttpGet httpGet = new HttpGet(uri);
CloseableHttpResponse response = httpClient.execute(httpGet);
int code = response.getCode();
if(code == HttpStatus.SC_OK){
LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
}
POST 请求
众所周知,HTTP 中的 POST 请求的数据是包含在请求体中的。在 HttpClient 中 POST 请求发送数据是通过,调用 HttpPost
类的 setEntity(HttpEntity entity)
方法设置消息内容的。
-
发送 JSON 数据
HttpClient 中发送 JSON 数据可以使用 StringHttpEntity 类实现,如下所示:
String url = "http://localhost:10010/user/body";
HttpPost httpPost = new HttpPost(url);
User user = new User();
user.setName("张三")
.setAge(20)
.setAddress(new Address()
.setCounty("中国")
.setCity("北京"))
.setAihao(Arrays.asList("跑步", "爬山", "看书"));
HttpEntity httpEntity = new StringEntity(JSON.toJSONString(user));
httpPost.setEntity(httpEntity);
httpClient.execute(httpPost);
-
模拟form表单数据
在实际使用时,可以存在 需要模拟 form
表单的情况进行请求数据,在 HttpClent 中也可以很方便的实现 form 的提交功能。操作步骤如下:
-
修改 contentType
ContentType contentType = ContentType.create("application/x-www-form-urlencoded", StandardCharsets.UTF_8);
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
-
创建请求数据 HttpEntity
String query = "name="+ URLEncoder.encode("张三", "utf-8") +"&age=20";
HttpEntity httpEntity = new StringEntity(query);
HttpEntity httpEntity = new UrlEncodedFormEntity(
Arrays.asList(new BasicNameValuePair("name", "张三"),
new BasicNameValuePair("age", "20")),
StandardCharsets.UTF_8
);
httpPost.setEntity(httpEntity);
完整代码如下所示:
HttpPost httpPost = new HttpPost("http://localhost:10010/user/map");
HttpEntity httpEntity = new UrlEncodedFormEntity(
Arrays.asList(new BasicNameValuePair("name", "张三"),
new BasicNameValuePair("age", "20")),
StandardCharsets.UTF_8
);
httpPost.setEntity(httpEntity);
ContentType contentType = ContentType.APPLICATION_FORM_URLENCODED.withCharset(StandardCharsets.UTF_8);
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
CloseableHttpResponse response = httpClient.execute(httpPost);
int code = response.getCode();
if(code == HttpStatus.SC_OK){
LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
}
7、上传下载
上传
在 HttpClient 中实现上传功能是非常方便的,可以通过 MultipartEntityBuilder
直接构建 HttpEntity 即可。
File file = new File("F:/20150703212056_Yxi4L.jpeg");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", file);
ContentType contentType = ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8);
builder.addTextBody("name", "张三", contentType);
HttpEntity httpEntity = builder.build();
HttpPost httpPost = new HttpPost("http://localhost:10010/user/upload");
httpPost.setEntity(httpEntity);
CloseableHttpResponse response = httpClient.execute(httpPost);
int code = response.getCode();
if(code == HttpStatus.SC_OK){
LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
}
下载
HttpClient 中的下载也相当简单,只需要发送请求,判断请求成功后,读取输入流,然后保存到响应的路径下即可,如下:
HttpGet httpGet = new HttpGet("http://localhost:10010/user/downLoad");
CloseableHttpResponse response = httpClient.execute(httpGet);
if (response.getCode() == HttpStatus.SC_OK){
Header header = response.getFirstHeader("File-Name");
String value = header.getValue();
byte[] bytes = EntityUtils.toByteArray(response.getEntity());
try (OutputStream outputStream = new FileOutputStream("F:/" + value);){
outputStream.write(bytes);
outputStream.flush();
}
}
8、响应处理
在 HttpClient 中把响应封装成了 CloseableHttpResponse
对象,在此对象中可以获取如下数据:
- getCode() 获取响应状态
- getEntity() 获取响应数据
if(code == HttpStatus.SC_OK){
LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
}
HttpClient 提供了 EntityUtils
工具类,可以很好的把 响应的 HttpEntity 转换为 字节数组或者字符串
EntityUtils.toString(response.getEntity());
EntityUtils.toByteArray(response.getEntity());
除了上述外,还可以在 调用 HttpClient 的 execute()
方法时 传入,响应处理器,返回自定义的数据类型。如下所示,是返回一个 自定义的 Response 对象
@Data
@Accessors(chain = true)
class Response {
private int code;
private String msg;
private String body;
}
Response execute = httpClient.execute(httpGet, response -> {
return new Response().setCode(response.getCode())
.setMsg(response.getReasonPhrase())
.setBody(EntityUtils.toString(response.getEntity(),
StandardCharsets.UTF_8));
});
9、会话保持
在实际项目中,经常会遇到需要先登录然后才能进行访问其他接口,那么, 在 HttpClient 中提供了 HttpClientContext
类,可以很好的实现,会话保持功能。
- 创建
HttpClientContext
- 在 execute() 方法中传入 第一步创建的对象
如下所示:
HttpContext httpContext = new BasicHttpContext();
httpContext.setAttribute("name", "zhangsan");
HttpClientContext httpClientContext = HttpClientContext.adapt(httpContext);
httpClient.execute(new HttpPost(""), httpClientContext);
httpClient.execute(new HttpGet(""), httpClientContext);
10、总结
这里只是 HttpClient 的使用做了简单的介绍,起到抛砖引玉的作用,其实,HttpClient 提供的功能非常强大的,在接下来会对 HttpClient 层层剖析,慢慢揭开 其神秘面纱。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)