HttpUtils工具类(二)Apache HttpClient 5 使用详细教程
目录
一、Apache HttpClient 5介绍
(1)核心特性
(2)Apache HttpClient 5 的新特性
(3)在 Java 项目的主要使用场景及缺点
使用场景:
缺点:
二、在实际项目中的应用
(1)引入maven配置
(2)自定义HttpUtils工具类---实现连接管理、重试策略等
功能概述
(3)代码中的具体实现
1、Get请求
2、POST请求-常规
3、POST请求-上传文件
(4)高级用法
1、处理重定向
2、SSL/TLS 支持
3、处理异步请求
4、处理 Cookie
5、HTTPDNS支持
一、Apache HttpClient 5介绍
Apache HttpClient 5 是一个功能齐全且高度可定制的 HTTP 客户端库, 其专门用于发送 HTTP 请求、处理 HTTP 响应并支持各种 HTTP 协议特性。特别适合处理复杂的 HTTP 请求需求,如多协议支持、认证、连接池、代理等。它适合中大型项目或需要高级 HTTP 特性的应用开发。
(1)核心特性
-
功能强大:
- 同步与异步支持:支持同步和异步的 HTTP 请求处理,异步请求在处理大量并发请求时能够显著提高效率。
- 连接池管理:内置的连接池机制能提高并发处理性能,减少资源消耗。
- 多种认证机制:支持多种认证方式,包括 Basic、Digest、NTLM、Kerberos 等,能够处理多种安全场景。
- 支持Cookie管理:内置 Cookie 管理功能,能够自动处理服务端返回的 Cookie 并在后续请求中使用,模拟浏览器行为。
-
协议支持广泛:
- HTTP/1.1 和 HTTP/2 支持:支持现代 HTTP 协议,包括 HTTP/2 的多路复用和流优先级等特性,提升了网络请求效率;特别是 HTTP/2 多路复用的优势。
- SSL/TLS 支持:支持 HTTPS,提供自定义 SSL/TLS 配置,确保通信的安全性。HttpClient 5 可以方便地处理 HTTPS 请求,支持定制化的 SSL/TLS 配置。
-
灵活性和可扩展性:
- 易于扩展和定制:允许开发者根据需要进行灵活的定制,HttpClient 5 的设计高度模块化,用户可以根据需要对连接管理、重定向策略、请求重试策略、代理设置等进行灵活定制。
- 代理支持:可以轻松配置 HTTP 或 SOCKS 代理,用于跨网络访问和隐私保护。
-
健壮的错误处理机制:
- 自动重试和重定向处理:内置的重试机制和自动重定向处理,可以减少由于网络问题导致的失败请求。开发者可以定制是否启用自动重定向。
(2)Apache HttpClient 5 的新特性
与之前的 4.x 版本相比,HttpClient 5 进行了大量的改进和优化,特别是在性能和安全性方面:
- HTTP/2 支持:提供了完整的 HTTP/2 支持,包括多路复用、流优先级等特性。
- 更好的异步支持:在处理并发请求时,通过异步模型极大提升了响应速度和吞吐量。
- 灵活的响应处理:通过改进的响应处理 API,可以更方便地处理大型响应体,避免内存溢出问题。
(3)在 Java 项目的主要使用场景及缺点
使用场景:
- RESTful API 客户端:与第三方 API 交互,发送各种 HTTP 请求。
- Web 爬虫:抓取网页内容,处理重定向、Cookie 等。
- 分布式系统通信:用于微服务间的 HTTP 通信。
- 测试与自动化:模拟 HTTP 请求,进行集成和自动化测试。
- 代理与网关:处理请求代理和认证机制。
- 文件上传下载:实现大文件的传输。
- 认证交互:处理 OAuth2、JWT 等认证协议。
- 安全通信:处理 HTTPS 请求,确保数据安全。
缺点:
- 学习曲线陡峭:高级特性(如自定义连接池、SSL 配置、异步请求等)较为复杂,新手需要时间学习和掌握。
- 体积较大:相比轻量级客户端,如 OkHttp,HttpClient 依赖库较多,可能不适合小型项目。
- 性能消耗高:默认配置下的内存和 CPU 占用较高,需调整才能达到最佳性能。
- 配置繁琐:高级定制(如连接管理、认证、代理)需要较多配置,增加开发复杂度。
- 异步编程复杂:异步请求的回调、错误处理等逻辑复杂,增加代码难度。
二、在实际项目中的应用
(1)引入maven配置
首先,你需要将 HttpClient 5 的依赖加入到项目中。pom.xml
文件如下:
<dependency><groupId>org.apache.httpcomponents.client5</groupId><artifactId>httpclient5</artifactId><version>5.1</version>
</dependency>
(2)自定义HttpUtils工具类---实现连接管理、重试策略等
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.util.Timeout;
import org.springframework.stereotype.Component;import java.io.Closeable;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.Map;/*** @author 响叮当* @since 2024/8/15 14:10**/
@Slf4j
@Component
public class ApacheHttpClientUtil {private CloseableHttpClient httpClient;public void init() {SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(Timeout.ofMilliseconds(1000)).build();PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create().setDefaultSocketConfig(socketConfig).setMaxConnTotal(1000).setMaxConnPerRoute(50).build();RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(Timeout.ofMilliseconds(8000)).setResponseTimeout(Timeout.ofMilliseconds(8000)).setConnectTimeout(Timeout.ofMilliseconds(8000)).build();httpClient = HttpClients.custom().disableContentCompression().setConnectionManager(connectionManager).setDefaultRequestConfig(requestConfig).build();}public CloseableHttpResponse getOrHead(String url, String method, Map<String, String> headers) throws IOException {HttpUriRequestBase request = new HttpUriRequestBase(method, URI.create(url));BasicHeader[] head = mapToHeaders(headers);request.setHeaders(head);return httpClient.execute(request);}public CloseableHttpResponse post(String url, Map<String, String> headers, HttpEntity httpEntity) throws IOException {HttpPost request = new HttpPost(url);BasicHeader[] head = mapToHeaders(headers);request.setHeaders(head);request.setEntity(httpEntity);return httpClient.execute(request);}public static BasicHeader[] mapToHeaders(Map<String, String> map) {BasicHeader[] headers = new BasicHeader[map.size()];int i = 0;for (Map.Entry<String, String> entry : map.entrySet()) {headers[i++] = new BasicHeader(entry.getKey(), entry.getValue());}return headers;}public static void closeQuietly(Closeable is) {if (is != null) {try {is.close();} catch (Exception ex) {log.error("Resources encounter an exception when closing,ex:{}", ex.getMessage());}}}}
功能概述
- 初始化 HTTP 客户端:
init()
方法初始化CloseableHttpClient
,配置连接池、请求超时和套接字超时。- 连接池配置:通过
PoolingHttpClientConnectionManagerBuilder
设置最大连接数(1000)和每路由的最大连接数(50),用于高并发场景。 - 请求配置:包括连接超时、请求超时和响应超时,确保在合理的时间内处理请求。
- 连接池配置:通过
- HTTP 请求处理:
- GET/HEAD 请求:
getOrHead()
方法可发送 GET 或 HEAD 请求,并接受自定义请求头。 - POST 请求:
post()
方法可发送 POST 请求,支持自定义请求头和实体。
- GET/HEAD 请求:
- 资源管理:
closeQuietly()
方法用于关闭资源,避免抛出异常。
(3)代码中的具体实现
1、Get请求
@GetMapping("/get")public void testGet() {String url = "http://xxx.com.cn";try {// 1、构建入参、添加 headersMap<String, String> headers = new HashMap<>();// 2、发起http请求CloseableHttpResponse httpResponse = apacheHttpClientUtil.getOrHead(url, "GET", headers);// 3、返回结果,异常处理if (httpResponse.getCode() == 200) {String resStr = EntityUtils.toString(httpResponse.getEntity());log.info("request_success, response:{}, httpResponse_Code:{}, reasonPhrase:{}", resStr, httpResponse.getCode(), httpResponse.getReasonPhrase());} else {log.error("request_fail, httpResponse_Code:{}, reasonPhrase:{}", httpResponse.getCode(), httpResponse.getReasonPhrase());}} catch (Exception e) {log.error("request_udmp_fail, ex:{}", e);}}
2、POST请求-常规
@PostMapping("/post")public void testPost(@RequestBody PostReq req) {String url = "http://xxx.com.cn";try {// 1、构建入参、添加 headersStringEntity stringEntity = new StringEntity(JSONUtil.toJsonStr(req), ContentType.APPLICATION_JSON);Map<String, String> headers = new HashMap<>();// 2、发起http请求CloseableHttpResponse httpResponse = apacheHttpClientUtil.post(url, headers, stringEntity);// 3、返回结果,异常处理if (httpResponse.getCode() == 200) {String resStr = EntityUtils.toString(httpResponse.getEntity());log.info("request_success, response:{}, httpResponse_Code:{}, reasonPhrase:{}", resStr, httpResponse.getCode(), httpResponse.getReasonPhrase());} else {log.error("request_fail, httpResponse_Code:{}, reasonPhrase:{}", httpResponse.getCode(), httpResponse.getReasonPhrase());}} catch (Exception e) {log.error("request_udmp_fail, ex:{}", e);}}
3、POST请求-上传文件
/*** 上传文件* @param multipartFile* @param token* @param key* @return*/@PostMapping("/uploadFile")public UploadRes testPostFile(@RequestParam("file") MultipartFile multipartFile,@RequestParam("token") String token,@RequestParam("key") String key) {UploadRes res = null;String url = "http://xxx.com.cn";try {// 1、构建File参数File file = new File(multipartFile.getOriginalFilename());try (FileOutputStream fos = new FileOutputStream(file)) {fos.write(multipartFile.getBytes());}MultipartEntityBuilder builder = MultipartEntityBuilder.create();builder.addBinaryBody("file", file, ContentType.MULTIPART_FORM_DATA, "ex.xlsx");// 2、构建其他参数builder.addTextBody("token", token, ContentType.TEXT_PLAIN);builder.addTextBody("key", key, ContentType.TEXT_PLAIN);HttpEntity multipartEntity = builder.build();// 3、需要加 header,在这里加Map<String, String> headers = new HashMap<>();// 4、发起http请求CloseableHttpResponse httpResponse = apacheHttpClientUtil.post(url, headers, multipartEntity);// 5、返回结果,异常处理if (httpResponse.getCode() == 200) {String resStr = EntityUtils.toString(httpResponse.getEntity());res = JSONUtil.toBean(resStr, UploadRes.class);log.info("request_success, response:{}, httpResponse_Code:{}, reasonPhrase:{}", resStr, httpResponse.getCode(), httpResponse.getReasonPhrase());} else {log.error("request_fail, httpResponse_Code:{}, reasonPhrase:{}", httpResponse.getCode(), httpResponse.getReasonPhrase());}} catch (Exception e) {log.error("request_udmp_fail, ex:{}", e);}return res;}
(4)高级用法
1、处理重定向
HttpClient 5 默认会处理 3XX 重定向,但你也可以自定义行为。
CloseableHttpClient httpClient = HttpClients.custom().disableRedirectHandling() // 禁用自动重定向.build();
2、SSL/TLS 支持
使用 HttpClient 5 可以轻松处理 HTTPS 请求,下面展示如何自定义 SSL 配置。
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import javax.net.ssl.SSLContext;SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial((chain, authType) -> true) // 信任所有证书.build();CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
3、处理异步请求
如果你需要发送异步 HTTP 请求,可以使用 HttpAsyncClient
。
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.client5.http.classic.methods.HttpGet;CloseableHttpAsyncClient asyncClient = HttpAsyncClients.createDefault();asyncClient.start();HttpGet request = new HttpGet("https://jsonplaceholder.typicode.com/posts/1");asyncClient.execute(request, new FutureCallback<>() {@Overridepublic void completed(CloseableHttpResponse response) {System.out.println("Response received: " + response.getCode());}@Overridepublic void failed(Exception ex) {System.out.println("Request failed: " + ex.getMessage());}@Overridepublic void cancelled() {System.out.println("Request cancelled");}
});
4、处理 Cookie
import org.apache.hc.client5.http.cookie.BasicCookieStore;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.cookie.CookieStore;CookieStore cookieStore = new BasicCookieStore();
CloseableHttpClient httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
5、HTTPDNS支持
// 当域名为www.baidu.com结尾时候,转到local的机器上String Target_IP= "127.0.0.1";String[] domains = new String[]{"www.baidu.com"};DnsResolver dnsResolver = new DnsResolver() {@Overridepublic InetAddress[] resolve(String host) throws UnknownHostException {if (host.endsWith(domains[0]))) {return new InetAddress[]{InetAddress.getByName(Target_IP)};}return new InetAddress[0];}@Overridepublic String resolveCanonicalHostname(String s) {return null;}};// @PostConstructpublic void init() {SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(Timeout.ofMilliseconds(1000)).build();PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create().setDnsResolver(dnsResolver) // 这里是HttpDns配置.setDefaultSocketConfig(socketConfig).setMaxConnTotal(1000).setMaxConnPerRoute(50).build();
相关文章:
HttpUtils工具类(二)Apache HttpClient 5 使用详细教程
目录 一、Apache HttpClient 5介绍 (1)核心特性 (2)Apache HttpClient 5 的新特性 (3)在 Java 项目的主要使用场景及缺点 使用场景: 缺点: 二、在实际项目中的应用 …...

Vue3.0生命周期钩子(包含:Vue 2.0 和 Vue 3.0)
1、Vue 2.0 生命周期钩子 每个应用程序实例在创建时都有一系列的初始化步骤。例如,创建数据绑定、编译模板、将实例挂载到 DOM 并在数据变化时触发 DOM 更新、销毁实例等。在这个过程中会运行一些叫做生命周期钩子的函数,通过这些钩子函数可以定义业务逻…...

遥感之常用各种指数总结大全
目前在遥感领域基本各种研究领域都会用到各种各样的指数,如水体指数,植被指数,农业长势指数,盐分指数,云指数,阴影指数,建筑物指数,水质指数,干旱指数等等众多。 本文对上…...

【C++】C++11新增特性
目录 C11简介: 1、统一的列表初始化: std::initializer_list 2、自动类型推导: auto: decltype: 3、final 和 override final: override: 4、默认成员函数控制: 显示缺省…...

【LeetCode每日一题】——662.二叉树最大宽度
文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 广度优先搜索 二【题目难度】 中等 三【题目编号】 662.二叉树最大宽度 四【题目描述】 给…...

第二十三节、血量更新逻辑的实现
一、创建代码 引入命名空间 using UnityEngine.UI; 调用UI必须有这个代码 二、ScriptObject类 1、是一个持久化存储文件的类型 接收所有的事件方法 先继承SO类,然后创建项目菜单 2、进行订阅 放入事件类,关联代码,即可进行广播 传递给这…...
Spring Authorization Server 认证服务器搭建
Spring Authorization Server实现了oauth2和oidc,最近有了解相关技术的需求,所以就尝试着进行了基本的环境搭建和技术测试,目前只测试了授权码模式,做一个记录,后续需要用时方便查找和参考。 1. 版本要求 Spring Authorization Server 版本:1.3.1 JDK 版本:17 Spring B…...

秋招突击——8/15——知识补充——垃圾回收机制
文章目录 引言正文指针引用可达性分析算法垃圾回收算法标记清除算法标记整理算法复制分代收集 垃圾收集器Serial收集器ParNew并行收集器Parallel Scavenge吞吐量优先收集器Serial Old老年代收集器Parallel old收集器CMS收集器G1收集器(Garbage First垃圾优先&#x…...

【iOS】UITableViewCell的重用问题解决方法
我自己在实验中对cell的重用总结如下: 非自定义Cell和非自定义cell的复用情况一样: 第一次加载创建tableView的时候,是屏幕上最多也显示几行cell就先创建几个cell,此时复用池里什么都没有开始下滑tableView,刚开始滑…...
开发一个微信小程序商城需要哪些技术栈
开发一个小程序商城需要掌握以下技术栈: 前端技术:包括HTML、CSS和JavaScript,用于定义商城的页面结构、样式设计和交互功能。 微信小程序专用技术:如WXML、WXSS、JavaScript和JSON,用于描述小程…...

望繁信科技荣膺上海市浦东新区博士后创新实践基地称号
近日,上海望繁信科技有限公司(简称“望繁信科技”)凭借在大数据流程智能领域的卓越表现,成功入选上海市浦东新区博士后创新实践基地。这一荣誉不仅是对望繁信科技创新能力和技术实力的高度认可,也标志着公司在推动产学…...

Nginx--代理与负载均衡(扩展nginx配置7层协议及4层协议方法、会话保持)
前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除 一、代理原理 1、反向代理产生的背景 单个服务器的处理客户端(用户)请求能力有一个极限,当接入请求过多时&#…...

Ubuntu20.4 系统安装后无wifi图标
0. 问题排查 1.检查 BIOS 设置: 有时候,无线网卡可能在 BIOS 中被禁用。重启电脑,进入 BIOS 设置,确保无线网卡选项是启用的。 2.检查硬件开关: 检查您的笔记本电脑是否有物理开关或键盘快捷键来启用或禁用无线网卡。 3.在软件更新中切换…...

牛客网SQL进阶135 :每个6/7级用户活跃情况
每个67级用户活跃情况_牛客题霸_牛客网 0 问题描述 基于用户信息表user_info、、试卷作答记录表exam_record、题目练习记录表practice_record,统计 每个6/7级用户总活跃月份数、2021年活跃天数、2021年试卷作答活跃天数、2021年答题活跃天数,结果 按照总…...
SQLite3使用接口写入二进制文件
使用接口的方式写入二进制文件 ,有二种方案。 一、全部文件 一次性写下到数据中 使用sqlite3_bind_blob接口 FILE* fpfopen("user.bmp","rb"); iLenfread(buffer,1,65535,fp); fclose(fp);sqlite3_prepare(pDB,"insert into user values …...
在复杂的数据库架构中,如何优化 SQL 查询以提高性能和减少资源消耗?
在优化 SQL 查询以提高性能和减少资源消耗时,可以考虑以下几个方面: 使用索引:为经常被查询的列创建索引,可以大大加快查询速度。同时,避免过多的索引,因为过多的索引会增加写入操作的开销。 编写高效的查…...

【HarmonyOS】端云一体化初始化项目
简介 端云一体化开发是HarmonyOS对云端开发的支持、实现端云联动。云开发服务提供了云函数、云数据库、云存储等服务,可以使开发者专注于应用的业务逻辑开发,无需关注基础设施,例如:服务器、操作系统等问题。 因此,…...
LLM之KG:利用大语言模型(LLM)对文本语料提取概念和概念之间的语义关系进而实现自动构建知识图谱
LLM之KG:利用大语言模型(LLM)对文本语料提取概念和概念之间的语义关系进而实现自动构建知识图谱 目录 ML之KG:基于MovieLens电影评分数据集利用基于知识图谱的推荐算法(networkx+基于路径相似度的方法)实现对用户进行Top电影推荐案例 LLMs之AutoKG:《大型语言模型在知识图…...
Spring Security 6如何使用?
Spring Security 6 是一个功能强大且高度可定制的身份验证和访问控制框架,它专注于为基于Java的应用程序提供全面的安全解决方案。以下是对Spring Security 6的详细解析: 一、核心功能 身份验证(Authentication): 验…...

PyTorch深度学习快速入门教程--学习笔记
目录 P4 PyCharm和Jupyter的对比 P5 PyTorch加载数据 P6 Dataset类代码实现 P7 Tensorboard 写日志 读取日志文件 Tensorboard 读图片 P10 Transforms使用 Transforms用途 常见的Transforms工具 P14 torchvision数据集使用 P15 Dataloader使用 P16 nn.Module模块使…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

前端开发者常用网站
Can I use网站:一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use:Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站:MDN JavaScript权威网站:JavaScript | MDN...