Java9之HttpClientAPI实战详解

news/2024/4/20 22:28:44/文章来源:https://blog.csdn.net/weixin_38933806/article/details/129263308

Java9 之 HttpClientAPI 实战详解

前言

相信关注 java9 的小伙伴们都知道 java9 版本内置模块提供了 Http 功能,当然并不是说之前 jdk 之前并不支持,那么这次更新又多了什么呢?或者是解决了什么问题?

说明

自 JDK 1.0 以来,Java 已经支持 HTTP/1.1。 HTTP API 由 java.net 包中的几种类型组成。 现有的 API 有以下问题:

  • 它被设计为支持多个协议,如 http,ftp,gopher 等,其中许多协议不再被使用。
  • 太抽象了,很难使用。
  • 它包含许多未公开的行为。
  • 它只支持一种模式,阻塞模式,这要求每个请求 / 响应有一个单独的线程。

2015 年 5 月,IETF(Internet Engineering Task Force)发布了 HTTP/2 规范。 有关 HTTP/2 规范的完整文本,请访问 https://tools.ietf.org/html/rfc7540。 HTTP/2 不会修改应用程序级语义。 也就是说,对应用程序中的 HTTP 协议的了解和使用情况并没有改变。 它具有更有效的方式准备数据包,然后发送到客户端和服务器之间的电线。 所有之前知道的 HTTP,如 HTTP 头,方法,状态码,URL 等都保持不变。 HTTP/2 尝试解决与 HTTP/1 连接所面临的许多性能相关的问题:

  • HTTP/2 支持二进制数据交换,来代替 HTTP/1.1 支持的文本数据。
  • HTTP/2 支持多路复用和并发,这意味着多个数据交换可以同时发生在 TCP 连接的两个方向上,而对请求的响应可以按顺序接收。 这消除了在对等体之间具有多个连接的开销,这在使用 HTTP/1.1 时通常是这种情况。 在 HTTP/1.1 中,必须按照发送请求的顺序接收响应,这称为 head-of-line 阻塞。 HTTP/2 通过在同一 TCP 连接上进行复用来解决线路阻塞问题。
  • 客户端可以建议请求的优先级,服务器可以在对响应进行优先级排序时予以遵守。
  • HTTP 首部(header)被压缩,这大大降低了首部大小,从而降低了延迟。
  • 它允许从服务器到客户端的资源推送。

JDK 9 不是更新现有的 HTTP/1.1 API,而是提供了一个支持 HTTP/1.1 和 HTTP/2 的 HTTP/2 Client API。 该 API 旨在最终取代旧的 API。 新 API 还包含使用 WebSocket 协议开发客户端应用程序的类和接口。 有关完整的 WebSocket 协议规范,请访问 https://tools.ietf.org/html/rfc6455。新的 HTTP/2 客户端 API 与现有的 API 相比有以下几个好处:

  • 在大多数常见情况下,学习和使用简单易用。
  • 它提供基于事件的通知。 例如,当收到首部信息,收到正文并发生错误时,会生成通知。
  • 它支持服务器推送,这允许服务器将资源推送到客户端,而客户端不需要明确的请求。 它使得与服务器的 WebSocket 通信设置变得简单。
  • 它支持 HTTP/2 和 HTTPS/TLS 协议。
  • 它同时工作在同步(阻塞模式)和异步(非阻塞模式)模式。

如果想使用 Java9 的 HttpClient 服务,那么你必须熟悉(jdk.incubator.http)包中的以下三个类:

HttpClient http 客户端

该类是 Java9 开始引入的,官方文档的翻译说明是这样的

  • HttpClient 是一个对多个请求配置了公共信息的容器。所有的请求通过一个 HttpClient 进行发送。HttpClients 是不可变的,通过 HttpClient 的 newBuilder () 创建返回。请求 Builders 被 HttpRequest#newBuilder () 来创建。
  • 接口 API

API 中 Builder 部分用来构建客户端的配置,send 相关的几个方法是进行请求发送,不同的是 Async 是异步操作。其他的基本是客户端的参数配置信息 (包括代理,线程,版本,SSL,cookie 等),同时也提供了 socket 支持。

  • 使用示例

    • 示例 1,使用默认配置

    HttpClient client = HttpClient.newHttpClient();

    • 示例 2, 自定义配置。

    try {
    Authenticator authenticator=new Authenticator() {
    };
    client= HttpClient.newBuilder()
    .authenticator(authenticator)//配置authenticator
    .sslContext(SSLContext.getDefault())//配置 sslContext
    .sslParameters(new SSLParameters())//配置 sslParameters
    .proxy(ProxySelector.getDefault())//配置 proxy
    .executor(Executors.newCachedThreadPool())//配置 executor
    .followRedirects(HttpClient.Redirect.ALWAYS)//配置 followRedirects
    .cookieManager(new CookieManager())//配置 cookieManager
    .version(HttpClient.Version.HTTP_2)//配置 version
    .build();

        } catch (NoSuchAlgorithmException e) {e.printStackTrace();}
    
  • 说明

    由于 HttpClient 隶属于 jdk.incubator.httpclient,所以使用的时候需要添加模块依赖方可执行。 如果你是单个 class,没有引入模块概念的话需要在 VM 参数中添加模块支持 --add-modules jdk.incubator.httpclient。如果你引入了模块的概念,需要在 你的 module.info 中添加 requires jdk.incubator.httpclient; 依赖。

HttpRequest 请求

  • API 文档说明

表示可以发送到服务器的一个 HTTP 请求。 HttpRequest 由 HttpRequest builders 构建生成。 HttpRequest 通过调用 HttpRequest.newBuilder 获得实例。 一个请求的 URI ,head 和 body 都可以设置。 请求体提供了 HttpRequest.BodyProcessor 对象的 DELETE , POST 或 PUT 方法。 GET 不用设置 body。 一旦所有必需的参数都在构建器设置, HttpRequest.Builder.build () 将返回一个 HttpRequest 实例 。 构建器也可以被多次复制和修改,以构建参数不同的多个相关请求。

  • 使用示例

    • 示例 1,GET 请求

    HttpResponse<String> response = client.send(
    HttpRequest
    .newBuilder(new URI(“http://www.foo.com/”))
    .headers(“Foo”, “foovalue”, “Bar”, “barvalue”)
    .GET()
    .build(),
    BodyHandler.asString()
    );
    int statusCode = response.statusCode();
    String body = response.body();

    • 示例 2,POST 请求。

    HttpResponseresponse = client.send(
    HttpRequest
    .newBuilder(new URI(“http://www.foo.com/”))
    .headers(“Foo”, “foovalue”, “Bar”, “barvalue”)
    .POST(BodyProcessor.fromString(“Hello world”))
    .build(),
    BodyHandler.asFile(Paths.get(“/path”))
    );
    int statusCode = response.statusCode();
    Path body = response.body(); // should be “/path”
    }

HttpResponse 响应

  • API 文档说明

表示 HttpRequest 的响应。 通常在响应正文,响应状态代码和 headers 被接收之后,HttpResponse 才是可用的。 这取决于发送请求时提供的响应体处理程序。 在所有情况下,在 Body 被读取之前调用 response body handler 程序。 此类中提供了访问响应头和响应主体的方法。

响应处理程序和处理器

Response bodies 有两种处理方式。 应用程序代码提供响应处理程序( HttpResponse.BodyHandler ), 一个是可以检查响应状态代码和头文件, 一个是返回一个 HttpResponse.BodyProcessor 以实际读取(或丢弃)正文并将其转换为一些有用的 Java 对象类型。 处理程序可以返回预定义的处理器类型之一或定制处理器, 如果正文被丢弃,则可以调用 BodyProcessor.discard () 并返回丢弃响应正文的处理器。 处理器和处理器的静态实现分别在 BodyHandler 和 BodyProcessor 中提供。 在所有情况下,提供的处理程序功能都是方便的实现, 它忽略了提供的状态代码和头文件,并返回相关的预定义的 BodyProcessor 。

  • 使用示例

    • 示例 1,BodyHandler

    HttpResponseresp = HttpRequest
    .create(URI.create(“http://www.foo.com”))
    .GET()
    .response(BodyHandler.asFile(Paths.get(“/tmp/f”)));
    }

    • 示例 2,BodyProcessor。

    HttpResponseresp1 = HttpRequest
    .create(URI.create(“http://www.foo.com”))
    .GET()
    .response(
    (status, headers) -> status == 200
    ? BodyProcessor.asFile(Paths.get(“/tmp/f”))
    : BodyProcessor.discard(Paths.get(“/NULL”)));
    }

实战应用

这里是一个完整的示例应用,涵盖了 HttpClient,httpRequest,HttpResponse 等的使用。

package com.javanine.http;import jdk.incubator.http.HttpClient;
import jdk.incubator.http.HttpRequest;
import jdk.incubator.http.HttpResponse;
import jdk.incubator.http.MultiMapResult;import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;/*** Created by bgt on 2017/10/1.* Java9http示例* <p>* VM 参数中添加模块支持* --add-modules jdk.incubator.httpclient*/
public class HttpDemo {// private static HttpClient client = HttpClient.newHttpClient();private static HttpClient client = null;static {//这里是httpclient的配置init();}public static void main(String[] args) {// HttpDemo.HttpGet();HttpDemo.HttpGet2();}public static void init(){try {Authenticator authenticator=new Authenticator() {};client= HttpClient.newBuilder().authenticator(authenticator)//配置authenticator.sslContext(SSLContext.getDefault())//配置 sslContext.sslParameters(new SSLParameters())//配置 sslParameters.proxy(ProxySelector.getDefault())//配置 proxy.executor(Executors.newCachedThreadPool())//配置 executor.followRedirects(HttpClient.Redirect.ALWAYS)//配置 followRedirects.cookieManager(new CookieManager())//配置 cookieManager.version(HttpClient.Version.HTTP_2)//配置 version.build();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}}/*** 普通get方式*** 结果:{"msg" : "未查询到用户,请认真检查账户或者是否登录","success" : false}响应码:200*/public static void HttpGet() {HttpRequest request = HttpRequest//.newBuilder(URI.create("http://blog.csdn.net/u014042066")).newBuilder(URI.create("http://www.rqbao.com/lotteryAward/gettenrecordlist")).header("refer", "http://www.oschina.com")//携带的参数.header("userId", "d3e750db32004972b0ae58f8129f50fc").timeout(Duration.ofSeconds(2))//2秒过期.GET().build();getReponse(request);}public static void HttpGet2() {HttpRequest request = HttpRequest//.newBuilder(URI.create("http://blog.csdn.net/u014042066")).newBuilder(URI.create("http://www.rqbao.com/lotteryAward/gettenrecordlist")).header("refer", "http://www.oschina.com")//携带的参数.header("userId", "d3e750db32004972b0ae58f8129f50fc").timeout(Duration.ofSeconds(2))//2秒过期.GET().build();getAsyReponse2(request);}/*** 文件上传*/public static void HttpPost() {try {HttpRequest request = HttpRequest.newBuilder(URI.create("http://blog.csdn.net/u014042066")).header("refer", "http://www.oschina.com").POST(HttpRequest.BodyProcessor.fromFile(Paths.get("/url.txt"))).build();getAsyReponse(request);} catch (FileNotFoundException e) {e.printStackTrace();}}/*** 携带参数*/public static void HttpPost2() {HttpRequest request = HttpRequest.newBuilder(URI.create("http://blog.csdn.net/u014042066")).header("refer", "http://www.oschina.com").POST(HttpRequest.BodyProcessor.fromString("name=ricky,pwd=123456")).build();getReponse(request);}/*** 输出响应结果* @param request* @throws IOException* @throws InterruptedException*/public static void getReponse(HttpRequest request) {HttpResponse<String> response = null;try {if (client==null) {init();}response = client.send(request, HttpResponse.BodyHandler.asString());} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}String result = response.body();int code = response.statusCode();if (code == 200) {System.out.println("结果:" + result);}System.out.println("响应码:" + code);}/*** 输出响应结果 带path形式* @param request* @throws IOException* @throws InterruptedException*/public static void getReponsePath(HttpRequest request) {HttpResponse<Path> response = null;try {client.send(request, HttpResponse.BodyHandler.asFile(Paths.get("/url.text")));Path body = response.body();System.out.println(body);} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}/*** 输出响应结果 带path形式的异步* @param request* @throws IOException* @throws InterruptedException*/public static void getAsyReponsePath(HttpRequest request) {CompletableFuture<Path> response = null;client.sendAsync(request, HttpResponse.BodyHandler.asFile(Paths.get("/url.text"))).thenApply((response1) -> response1.body());response.join();}/*** 异步的输出响应结果* @param request* @throws IOException* @throws InterruptedException*/public static void getAsyReponse(HttpRequest request) {CompletableFuture<HttpResponse<String>> cf;cf = client.sendAsync(request, HttpResponse.BodyHandler.asString());HttpResponse<String> response = cf.join();System.out.println(response.body());}/*** 异步的输出响应结果* @param request* @throws IOException* @throws InterruptedException*/public static void getAsyReponse2(HttpRequest request) {MultiMapResult<String> ress;ress = client.sendAsync(request, HttpResponse.MultiProcessor.asMap((req)-> Optional.of(HttpResponse.BodyHandler.asString()))).join();ress.forEach((req,cf)->{HttpResponse<String> resp=cf.join();System.out.println("uri:"+resp.uri()+"---body:"+resp.body());});}
}

Java9 的 HttpClient 提供了丰富的功能,这里只是做了个简单的入门与分享,不对之处还望指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_75469.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mac安装 Termius

1.下载安装包 链接: https://pan.baidu.com/s/1f5xmvYnVehCkMUD291SbsA?pwdy43k 提取码: y43k 2.打开系统偏好设置 -> 安全性与隐私 -> 通用&#xff0c;勾选“任何来源” 显示文件损坏的情况下执行下面操作 3.打开terminal终端 3.1 输入&#xff1a;sudo spctl --m…

“来源可靠、程序规范、要素合规”与“四性”

《从技术可行性的视角看电子档案的“四性”》一文中已经明确&#xff0c;笔者认为的电子档案“四性”是指“真实性、完整性、可用性和安全性”。而《从特斯拉“刹车失灵”事件看电子档案的法定要求》一文中&#xff0c;笔者对于“来源可靠、程序规范、要素合规”的解读如下&…

解决windows安装wxPython安装失败、速度过慢及PyCharm上wx包爆红问题

网上关于wxPython安装失败&#xff0c;安装速度过慢&#xff0c;以及安装成功后PyCharm中import wx仍然爆红的文章有很多&#xff0c;也特别杂&#xff0c;解决起来特别困难&#xff0c;今天在这里对问题的处理进行一个整合&#xff0c;希望能帮助到大家。 安装wxPython这里运用…

MySQL表的增删查改(基础)

gitee:博客中的所有操作整合新增语法:insert [into] table_name values(value_list)[案例] 创建一个学生表进行数据插入1.1单行数据全列插入[提示]我们可以想在记事本上写下命令,让后复制到数据库客户端,这样可以在出错的时候进行快速修改.同时为了美观和明了,我们可以进行适当…

计算机的发展

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。个人爱好: 编程&#xff0c;打篮球&#xff0c;计算机知识个人名言&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石…

低代码开发平台选型必看指南

低代码开发是近年来逐渐兴起的一种新型软件开发方式。它通过封装常见的软件开发流程和代码&#xff0c;使得非专业的开发者也能够轻松创建复杂的应用程序。这种开发方式已经受到了许多企业的青睐&#xff0c;成为提高生产效率、降低开发成本的一种有效途径。 低代码开发的核心…

docker部署zabbix6.2.7+grafana

目录 1、下载docker 2、下载相关镜像文件 3、创建一个供zabbix系统使用的网络环境 4、创建一个供mysql数据库存放文件的目录 5、启动mysql容器 6、为zabbix-server创建一个持久卷 7、启动zabbix-server容器 8、创建语言存放目录 9、启动zabbix-web容器 10、启动zabbix…

【解锁技能】学会Python条件语句的终极指南!

文章目录前言一. python条件语句的介绍1.1 什么是条件语句1.2 条件语句的语法1.3 关于内置函数bool()二. 分支语句之单分支三. 多分支语句3.1 二分支语句3.2 多分支语句3.3 嵌套循环总结前言 &#x1f3e0;个人主页&#xff1a;欢迎访问 沐风晓月的博客 &#x1f9d1;个人简介&…

EPICS synApps介绍

一、synApps是什么&#xff1f; 1&#xff09; 一个用于同步束线用户的EPICS模块集合。 2&#xff09; EPICS模块 alive, autosave, busy, calc, camac, caputRecorder, dac128V, delaygen, dxp, ip, ip330, ipUnidig, love, mca, measComp, modbus, motor, optics, quadEM,…

【蓝桥杯选拔赛真题38】python目标值判断 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析

目录 python目标值判断 一、题目要求 1、编程实现 2、输入输出 二、解题思路

【牛客刷题专栏】0x0E:JZ6 从尾到头打印链表(C语言编程题)

前言 个人推荐在牛客网刷题(点击可以跳转)&#xff0c;它登陆后会保存刷题记录进度&#xff0c;重新登录时写过的题目代码不会丢失。个人刷题练习系列专栏&#xff1a;个人CSDN牛客刷题专栏。 题目来自&#xff1a;牛客/题库 / 在线编程 / 剑指offer&#xff1a; 目录前言问题…

CVE-2022-42889 Apache Commons Text 漏洞

0x00 前言 所幸遇到&#xff0c;就简单看看&#xff0c;其中没有啥比较难的地方&#xff0c;仅做记录。10月13日的漏洞。 cve链接可以看下面这个&#xff1a; https://cve.mitre.org/cgi-bin/cvename.cgi?nameCVE-2022-42889 git地址&#xff1a; https://github.com/apache…

前端进阶JS运行原理

JS运行原理 深入了解V8引擎原理 浏览器内核是由两部分组成的&#xff0c;以webkit为例&#xff1a; WebCore&#xff1a;负责HTML解析、布局、渲染等等相关的工作&#xff1b;JavaScriptCore&#xff1a;解析、执行JavaScript代码&#xff1b; 官方对V8引擎的定义&#xff1…

汇编指令学习(MOV,MOVSX,MOVZX,LEA,XCHG)

一、MOV指令1、将十六进制0x1234数值&#xff0c;赋值给eax寄存器mov eax,0x12342、将十六进制0x123数值&#xff0c;赋值给内存地址为ebxmov dword [ebx],0x1233、将edx的高八位赋值给eax的低八位ax&#xff0c;eax的低16位&#xff0c;al&#xff0c;eax的低8位&#xff0c;a…

(三)随处可见的LED广告屏是怎么工作的呢?接入GUI

续上文&#xff0c;本篇我们将尝试接入一个GUI来控制点阵屏。在前两篇中&#xff0c;我们相继介绍了点阵屏的控制原理&#xff0c;以及如何让点阵屏按照我们所想的进行显示。本篇将在此基础上接入一个GUI&#xff0c;使点阵屏的控制更加优雅。限于阅读体验和展示效果&#xff0…

深入理解border以及应用

深入border属性以及应用&#x1f44f;&#x1f44f; border这个属性在开发过程中很常用&#xff0c;常常用它来作为边界的。但是大家真的了解border吗&#xff1f;以及它的形状是什么样子的。 我们先来看这样一段代码&#xff1a;&#x1f44f; <!--* Author: syk 185901…

k8s环境jenkins发布vue项目指定nodejs版本

k8s环境jenkins发布vue项目指定nodejs版本1、背景2、分析3、解决方法3.1、 找到配置镜像位置3.2、 制作新镜像3.3、 推送镜像到私有仓库3.4、 修改配置文件1、背景 发布一个前端项目&#xff0c;它需要nodejs 16.9.0版本支持&#xff0c;而kubesphere 3.2.0集成的jenkins 的镜…

小米mix2s刷win11和android双系统

在给电脑安装系统的过程中&#xff0c;可能会因为各种原因出现windows无法安装的情况&#xff0c;我在给小米mix2s安装win11时发现出现了“计算机意外地重新启动或遇到错误&#xff0c;windows无法安装”的情况&#xff0c;下面就来教一下大家两种解决方法&#xff0c;希望可以…

【解决办法】windows防火墙出入站规则放通telnet方法

【操作方法】windows防火墙出站规则放通telnet方法一、出站规则1.新建出站规则中选择“程序”2.选择路径&#xff0c;点击“下一页”3.选择“允许连接”4.选择所有区域二、入站规则注&#xff1a;打开防火墙添加出入站规则参考【操作方法】windows防火墙添加出入站规则方法 一、…

JUC(二)

1.可重入锁–ReentrantLock原理 1.1.非公平锁的实现原理 1.1.1.加锁解锁流程 1>.先从构造器开始看,默认为非公平锁,可以在构造函数中设置参数指定公平锁 public ReentrantLock() {sync = new NonfairSync(); }public ReentrantLock