JDK11新特性 --httpClient

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 urls = List.of("http://www.baidu.com","http://www.alibaba.com/","http://www.tencent.com");
List requests = urls.stream()
.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 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)

你可能感兴趣的:(JDK11新特性 --httpClient)