JDK11新特性 --httpClient
一:HttpURLConnenction目前存在的问题
1.其基类 URLConnection 当初是设计为支持多协议,但其中大多已经成为非主流(ftp, gopher…)
2.API 的设计早于 HTTP/1.1,过度抽象
3.难以使用,存在许多没有文档化的行为
4.它只支持阻塞模式(每个请求 / 响应占用一个线程)
二: HttpClient简介
httpclient是Apache Jakarta common下的子项目,用来提供高效的、最新的、更能丰富的支持http协议的客户端编程工具包,并且它支持http协议最新的版本和建议。httpclient已经应用在很多项目中,比如Apache Jakarta上很著名的两个开源项目cactus和httplunit都使用了httpclient。
三:HttpClient特性
1.以可扩展的面向对象的结构实现了HTTP全部的方法(GET、POST、put、delete、head、options、trace)。
2.支持HTTPS协议。
3.通过HTTP代理建立透明的连接。
4.连接管理器支持多线程应用。支持设置最大连接数,同事支持设置每个主机的最大连接数,发现并关闭过期的连接。
5.自动处理Set-Cookie中的Cookie。
6.插件式的自定义Cookie策略。
7.request的输出流可以避免流中内容直接缓冲到socket服务器。
8.Response的输入流可以有效的从socket服务器直接读取相应内容
三:使用方法
使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。
1、创建httpclient对象。
2、创建请求方法的实例,并制定请求url。如果需要发送get请求,创建httpclient对象;如果需要发送post请求,创建httpPOST对象。
3、如果需要发送请求参数,可调用httpget、httpPost共同的setparams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
4、调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
5、调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
6、释放连接。无论执行方法是否成功,都必须释放连接
四:代码实例
实例1:同步get请求
public void syncGet() throws InterruptedException, IOException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://www.baidu.com")).build();
HttpResponse response =
client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
实例2:异步Get 请求
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://www.baidu.com")).build();
CompletableFuture result = client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).thenApply(HttpResponse::body);
System.out.println(result.get());
}
实例四:Post请求
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://www.w3school.com.cn/demo/demo_form.asp"))
.header("Content-Type","application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString("name1=value1&name2=value2"))
.build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
}
实例五:JSON传参 header指定内容是表单类型,然后通过BodyPublishers.ofString传递表单数据,需要自己构建表单参数
ObjectMapper objectMapper = new ObjectMapper();
StockDto dto = new StockDto();
dto.setName("hj");
dto.setSymbol("hj");
dto.setType(StockDto.StockType.SH);
String requestBody = objectMapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(dto);
HttpRequest request = HttpRequest.newBuilder(URI.create("http://localhost:8080/json/demo"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
CompletableFuture result = HttpClient.newHttpClient()
.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenApply(body -> {
try {
return objectMapper.readValue(body,StockDto.class);
} catch (IOException e) {
return new StockDto();
}
});StockDto
System.out.println(result.get());
实例六:并发请求
//endAsync方法返回的是CompletableFuture,可以方便地进行转换、组合等操作
//这里使用CompletableFuture.allOf组合在一起,最后调用join等待所有future完成
public void testConcurrentRequests(){
HttpClient client = HttpClient.newHttpClient();
List
List
.map(url -> HttpRequest.newBuilder(URI.create(url)))
.map(reqBuilder -> reqBuilder.build())
.collect(Collectors.toList());
List>> futures = requests.stream()
.map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString()))
.collect(Collectors.toList());
futures.stream()
.forEach(e -> e.whenComplete((resp,err) -> {
if(err != null){
err.printStackTrace();
}else{
System.out.println(resp.body());
System.out.println(resp.statusCode());
}
}));
CompletableFuture.allOf(futures
.toArray(CompletableFuture>[]::new))
.join();
}
六:总结
HttpClient中常用到的类
HttpClient
|-- DefaultHttpClient
构造方法: DefaultHttpClient
主要方法: HttpResponse execute(HttpUriRequest request)
HttpUriRequest
|-- HttpGet
构造方法: HttpGet()
HttpGet(String uri)
|-- HttpPost
构造方法: HttpPost(String uri)
主要方法: void setEntity(HttpEntity entity)
HttpResponse
主要方法:
StatusLine getStatusLine()
Header[] getAllHeaders();
HttpEntity getEntity();
HttpEntity
主要方法:
InputStream getContent();
long getContentLength();
Header getContentType();
|-- UrlEncodedFormEntity
构造方法:UrlEncodedFormEntity(List extends NameValuePair> params)
//用于向请求对象中写入请求实体(包含请求参数(NameValuePair))
EntityUtils
public static byte[] toByteArray(HttpEntity entity)
public static String toString(HttpEntity entity)
public static String toString(HttpEntity entity , String encoding)
StatusLine
int getStatusCode()
HttpStatus
SC_OK SC_NOT_FOUND
Header
String getName()
String getValue()
NameValuePair
String getName()
String getValue()
|-- BasicNameValuePair
构造方法:BasicNameValuePair(String name , String value)