聊聊HttpClientBuilder
序
本文主要研究一下HttpClientBuilder
HttpClientBuilder
httpclient-4.5.10-sources.jar!/org/apache/http/impl/client/HttpClientBuilder.java
public class HttpClientBuilder {public static HttpClientBuilder create() {return new HttpClientBuilder();}protected HttpClientBuilder() {super();}public CloseableHttpClient build() {// Create main request executor// We copy the instance fields to avoid changing them, and rename to avoid accidental use of the wrong versionPublicSuffixMatcher publicSuffixMatcherCopy = this.publicSuffixMatcher;if (publicSuffixMatcherCopy == null) {publicSuffixMatcherCopy = PublicSuffixMatcherLoader.getDefault();}HttpRequestExecutor requestExecCopy = this.requestExec;if (requestExecCopy == null) {requestExecCopy = new HttpRequestExecutor();}HttpClientConnectionManager connManagerCopy = this.connManager;if (connManagerCopy == null) {LayeredConnectionSocketFactory sslSocketFactoryCopy = this.sslSocketFactory;if (sslSocketFactoryCopy == null) {final String[] supportedProtocols = systemProperties ? split(System.getProperty("https.protocols")) : null;final String[] supportedCipherSuites = systemProperties ? split(System.getProperty("https.cipherSuites")) : null;HostnameVerifier hostnameVerifierCopy = this.hostnameVerifier;if (hostnameVerifierCopy == null) {hostnameVerifierCopy = new DefaultHostnameVerifier(publicSuffixMatcherCopy);}if (sslContext != null) {sslSocketFactoryCopy = new SSLConnectionSocketFactory(sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifierCopy);} else {if (systemProperties) {sslSocketFactoryCopy = new SSLConnectionSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault(),supportedProtocols, supportedCipherSuites, hostnameVerifierCopy);} else {sslSocketFactoryCopy = new SSLConnectionSocketFactory(SSLContexts.createDefault(),hostnameVerifierCopy);}}}@SuppressWarnings("resource")final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactoryCopy).build(),null,null,dnsResolver,connTimeToLive,connTimeToLiveTimeUnit != null ? connTimeToLiveTimeUnit : TimeUnit.MILLISECONDS);if (defaultSocketConfig != null) {poolingmgr.setDefaultSocketConfig(defaultSocketConfig);}if (defaultConnectionConfig != null) {poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig);}if (systemProperties) {String s = System.getProperty("http.keepAlive", "true");if ("true".equalsIgnoreCase(s)) {s = System.getProperty("http.maxConnections", "5");final int max = Integer.parseInt(s);poolingmgr.setDefaultMaxPerRoute(max);poolingmgr.setMaxTotal(2 * max);}}if (maxConnTotal > 0) {poolingmgr.setMaxTotal(maxConnTotal);}if (maxConnPerRoute > 0) {poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute);}connManagerCopy = poolingmgr;}ConnectionReuseStrategy reuseStrategyCopy = this.reuseStrategy;if (reuseStrategyCopy == null) {if (systemProperties) {final String s = System.getProperty("http.keepAlive", "true");if ("true".equalsIgnoreCase(s)) {reuseStrategyCopy = DefaultClientConnectionReuseStrategy.INSTANCE;} else {reuseStrategyCopy = NoConnectionReuseStrategy.INSTANCE;}} else {reuseStrategyCopy = DefaultClientConnectionReuseStrategy.INSTANCE;}}ConnectionKeepAliveStrategy keepAliveStrategyCopy = this.keepAliveStrategy;if (keepAliveStrategyCopy == null) {keepAliveStrategyCopy = DefaultConnectionKeepAliveStrategy.INSTANCE;}AuthenticationStrategy targetAuthStrategyCopy = this.targetAuthStrategy;if (targetAuthStrategyCopy == null) {targetAuthStrategyCopy = TargetAuthenticationStrategy.INSTANCE;}AuthenticationStrategy proxyAuthStrategyCopy = this.proxyAuthStrategy;if (proxyAuthStrategyCopy == null) {proxyAuthStrategyCopy = ProxyAuthenticationStrategy.INSTANCE;}UserTokenHandler userTokenHandlerCopy = this.userTokenHandler;if (userTokenHandlerCopy == null) {if (!connectionStateDisabled) {userTokenHandlerCopy = DefaultUserTokenHandler.INSTANCE;} else {userTokenHandlerCopy = NoopUserTokenHandler.INSTANCE;}}String userAgentCopy = this.userAgent;if (userAgentCopy == null) {if (systemProperties) {userAgentCopy = System.getProperty("http.agent");}if (userAgentCopy == null && !defaultUserAgentDisabled) {userAgentCopy = VersionInfo.getUserAgent("Apache-HttpClient","org.apache.http.client", getClass());}}ClientExecChain execChain = createMainExec(requestExecCopy,connManagerCopy,reuseStrategyCopy,keepAliveStrategyCopy,new ImmutableHttpProcessor(new RequestTargetHost(), new RequestUserAgent(userAgentCopy)),targetAuthStrategyCopy,proxyAuthStrategyCopy,userTokenHandlerCopy);execChain = decorateMainExec(execChain);HttpProcessor httpprocessorCopy = this.httpprocessor;if (httpprocessorCopy == null) {final HttpProcessorBuilder b = HttpProcessorBuilder.create();if (requestFirst != null) {for (final HttpRequestInterceptor i: requestFirst) {b.addFirst(i);}}if (responseFirst != null) {for (final HttpResponseInterceptor i: responseFirst) {b.addFirst(i);}}b.addAll(new RequestDefaultHeaders(defaultHeaders),new RequestContent(),new RequestTargetHost(),new RequestClientConnControl(),new RequestUserAgent(userAgentCopy),new RequestExpectContinue());if (!cookieManagementDisabled) {b.add(new RequestAddCookies());}if (!contentCompressionDisabled) {if (contentDecoderMap != null) {final List<String> encodings = new ArrayList<String>(contentDecoderMap.keySet());Collections.sort(encodings);b.add(new RequestAcceptEncoding(encodings));} else {b.add(new RequestAcceptEncoding());}}if (!authCachingDisabled) {b.add(new RequestAuthCache());}if (!cookieManagementDisabled) {b.add(new ResponseProcessCookies());}if (!contentCompressionDisabled) {if (contentDecoderMap != null) {final RegistryBuilder<InputStreamFactory> b2 = RegistryBuilder.create();for (final Map.Entry<String, InputStreamFactory> entry: contentDecoderMap.entrySet()) {b2.register(entry.getKey(), entry.getValue());}b.add(new ResponseContentEncoding(b2.build()));} else {b.add(new ResponseContentEncoding());}}if (requestLast != null) {for (final HttpRequestInterceptor i: requestLast) {b.addLast(i);}}if (responseLast != null) {for (final HttpResponseInterceptor i: responseLast) {b.addLast(i);}}httpprocessorCopy = b.build();}execChain = new ProtocolExec(execChain, httpprocessorCopy);execChain = decorateProtocolExec(execChain);// Add request retry executor, if not disabledif (!automaticRetriesDisabled) {HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;if (retryHandlerCopy == null) {retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE;}execChain = new RetryExec(execChain, retryHandlerCopy);}HttpRoutePlanner routePlannerCopy = this.routePlanner;if (routePlannerCopy == null) {SchemePortResolver schemePortResolverCopy = this.schemePortResolver;if (schemePortResolverCopy == null) {schemePortResolverCopy = DefaultSchemePortResolver.INSTANCE;}if (proxy != null) {routePlannerCopy = new DefaultProxyRoutePlanner(proxy, schemePortResolverCopy);} else if (systemProperties) {routePlannerCopy = new SystemDefaultRoutePlanner(schemePortResolverCopy, ProxySelector.getDefault());} else {routePlannerCopy = new DefaultRoutePlanner(schemePortResolverCopy);}}// Optionally, add service unavailable retry executorfinal ServiceUnavailableRetryStrategy serviceUnavailStrategyCopy = this.serviceUnavailStrategy;if (serviceUnavailStrategyCopy != null) {execChain = new ServiceUnavailableRetryExec(execChain, serviceUnavailStrategyCopy);}// Add redirect executor, if not disabledif (!redirectHandlingDisabled) {RedirectStrategy redirectStrategyCopy = this.redirectStrategy;if (redirectStrategyCopy == null) {redirectStrategyCopy = DefaultRedirectStrategy.INSTANCE;}execChain = new RedirectExec(execChain, routePlannerCopy, redirectStrategyCopy);}// Optionally, add connection back-off executorif (this.backoffManager != null && this.connectionBackoffStrategy != null) {execChain = new BackoffStrategyExec(execChain, this.connectionBackoffStrategy, this.backoffManager);}Lookup<AuthSchemeProvider> authSchemeRegistryCopy = this.authSchemeRegistry;if (authSchemeRegistryCopy == null) {authSchemeRegistryCopy = RegistryBuilder.<AuthSchemeProvider>create().register(AuthSchemes.BASIC, new BasicSchemeFactory()).register(AuthSchemes.DIGEST, new DigestSchemeFactory()).register(AuthSchemes.NTLM, new NTLMSchemeFactory()).register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory()).register(AuthSchemes.KERBEROS, new KerberosSchemeFactory()).build();}Lookup<CookieSpecProvider> cookieSpecRegistryCopy = this.cookieSpecRegistry;if (cookieSpecRegistryCopy == null) {cookieSpecRegistryCopy = CookieSpecRegistries.createDefault(publicSuffixMatcherCopy);}CookieStore defaultCookieStore = this.cookieStore;if (defaultCookieStore == null) {defaultCookieStore = new BasicCookieStore();}CredentialsProvider defaultCredentialsProvider = this.credentialsProvider;if (defaultCredentialsProvider == null) {if (systemProperties) {defaultCredentialsProvider = new SystemDefaultCredentialsProvider();} else {defaultCredentialsProvider = new BasicCredentialsProvider();}}List<Closeable> closeablesCopy = closeables != null ? new ArrayList<Closeable>(closeables) : null;if (!this.connManagerShared) {if (closeablesCopy == null) {closeablesCopy = new ArrayList<Closeable>(1);}final HttpClientConnectionManager cm = connManagerCopy;if (evictExpiredConnections || evictIdleConnections) {final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor(cm,maxIdleTime > 0 ? maxIdleTime : 10, maxIdleTimeUnit != null ? maxIdleTimeUnit : TimeUnit.SECONDS,maxIdleTime, maxIdleTimeUnit);closeablesCopy.add(new Closeable() {@Overridepublic void close() throws IOException {connectionEvictor.shutdown();try {connectionEvictor.awaitTermination(1L, TimeUnit.SECONDS);} catch (final InterruptedException interrupted) {Thread.currentThread().interrupt();}}});connectionEvictor.start();}closeablesCopy.add(new Closeable() {@Overridepublic void close() throws IOException {cm.shutdown();}});}return new InternalHttpClient(execChain,connManagerCopy,routePlannerCopy,cookieSpecRegistryCopy,authSchemeRegistryCopy,defaultCookieStore,defaultCredentialsProvider,defaultRequestConfig != null ? defaultRequestConfig : RequestConfig.DEFAULT,closeablesCopy);}
}
HttpClientBuilder提供了静态方法create用于创建builder,其build方法用于创建CloseableHttpClient,它主要是构建ClientExecChain(
HttpRequestExecutor、HttpClientConnectionManager、ConnectionReuseStrategy、ConnectionKeepAliveStrategy、AuthenticationStrategy、UserTokenHandler
)、ProtocolExec(ClientExecChain、HttpProcessor
)、RetryExec(ClientExecChain、HttpRequestRetryHandler
)、RedirectExec(HttpRoutePlanner、ServiceUnavailableRetryStrategy、RedirectStrategy
)、BackoffStrategyExec;最后构建的是InternalHttpClient
SSLContext
org/apache/http/ssl/SSLContexts.java
对于sslContext不为null的则创建SSLConnectionSocketFactory(sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifierCopy),为null的话,则通过SSLContexts.createDefault()来创建默认的SSLContext
public static SSLContext createDefault() throws SSLInitializationException {try {final SSLContext sslContext = SSLContext.getInstance(SSLContextBuilder.TLS);sslContext.init(null, null, null);return sslContext;} catch (final NoSuchAlgorithmException ex) {throw new SSLInitializationException(ex.getMessage(), ex);} catch (final KeyManagementException ex) {throw new SSLInitializationException(ex.getMessage(), ex);}}
HostnameVerifier
若hostnameVerifier为null,则创建默认的DefaultHostnameVerifier
public DefaultHostnameVerifier(final PublicSuffixMatcher publicSuffixMatcher) {this.publicSuffixMatcher = publicSuffixMatcher;}public DefaultHostnameVerifier() {this(null);}@Overridepublic boolean verify(final String host, final SSLSession session) {try {final Certificate[] certs = session.getPeerCertificates();final X509Certificate x509 = (X509Certificate) certs[0];verify(host, x509);return true;} catch (final SSLException ex) {if (log.isDebugEnabled()) {log.debug(ex.getMessage(), ex);}return false;}}
PoolingHttpClientConnectionManager
org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java
@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL)
public class PoolingHttpClientConnectionManagerimplements HttpClientConnectionManager, ConnPoolControl<HttpRoute>, Closeable {private final ConfigData configData;private final CPool pool;private final HttpClientConnectionOperator connectionOperator;private final AtomicBoolean isShutDown;public PoolingHttpClientConnectionManager(final HttpClientConnectionOperator httpClientConnectionOperator,final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,final long timeToLive, final TimeUnit timeUnit) {super();this.configData = new ConfigData();this.pool = new CPool(new InternalConnectionFactory(this.configData, connFactory), 2, 20, timeToLive, timeUnit);this.pool.setValidateAfterInactivity(2000);this.connectionOperator = Args.notNull(httpClientConnectionOperator, "HttpClientConnectionOperator");this.isShutDown = new AtomicBoolean(false);}@Overrideprotected void finalize() throws Throwable {try {shutdown();} finally {super.finalize();}}@Overridepublic void close() {shutdown();}//......
}
PoolingHttpClientConnectionManager实现了HttpClientConnectionManager、ConnPoolControl、Closeable接口,它使用了CPool作为连接池来管理连接,默认的maxPerRoute为2,maxTotal为20
小结
apache的httpclient的HttpClientBuilder提供了构建CloseableHttpClient的方法,它提供了设置sslContext的方法,如果没有设置则通过SSLContexts.createDefault()来创建默认的SSLContext,若hostnameVerifier为null,则创建默认的DefaultHostnameVerifier,其默认会创建HttpClientConnectionManager,使用的是maxPerRoute为2,maxTotal为20的连接池。
相关文章:
聊聊HttpClientBuilder
序 本文主要研究一下HttpClientBuilder HttpClientBuilder httpclient-4.5.10-sources.jar!/org/apache/http/impl/client/HttpClientBuilder.java public class HttpClientBuilder {public static HttpClientBuilder create() {return new HttpClientBuilder();}protected…...

MacOS - Sonoma更新了啥
1 系统介绍 苹果公司于2023年9月26日发布了macOS Sonoma 14.0正式版。名称由来不知道,可能是地名:Sonoma是一个地名,指加利福尼亚州北部索诺玛县(Sonoma County)。 2 系统重要更新 2.1 将小组件添加到桌面 速览提醒事项和临近日程等。按住Control键点…...

C++17中头文件filesystem的使用
C17引入了std::filesystem库(文件系统库, filesystem library),相关类及函数的声明在头文件filesystem中,命名空间为std::filesystem。 1.path类:文件路径相关操作,如指定的路径是否存在等,其介绍参见:http…...

「专题速递」数字人直播带货、传统行业数字化升级、远程协作中的低延时视频、地产物业中的通讯终端...
音视频技术作为企业数字化转型的核心要素之一,已在各行各业展现出广泛的应用和卓越的价值。实时通信、社交互动、高清视频等技术不仅令传统行业焕发新生,还为其在生产、管理、服务提供与维护等各个领域带来了巨大的助力,实现了生产效率和服务…...

PE格式之PE头部
1. PE头部总体组成 2. DOS MZ头 3. PE头 PE头由3部分组成: 下面分别: OptionalHeader比较大: 然后是节表, 节表有多个: PE文件头部就结束了, 最后就是节区了, 来看几段代码: ; main.asm .586 .model flat, stdcall option casemap:noneinclude windows.inc include ke…...

SLAM从入门到精通(用python实现机器人运动控制)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 在ROS下面,开发的方法很多,可以是c,可以是python。大部分接口操作类的应用,其实都可以用python来开…...
接口和抽象类有什么区别?
接口和抽象类都是用于实现抽象类型的机制: 抽象类:抽象类可以包含抽象方法(未实现的方法)和具体方法(已实现的方法)。抽象类可以有字段(成员变量),这些字段可以是具体的,也可以是抽象的。一个类只能继承一个抽象类,Java不支持多继承。抽象类可以拥有构造方法,用于初…...

基于springboot+vue的人事系统
目录 前言 一、技术栈 二、系统功能介绍 员工信息管理 考勤信息管理 考勤信息管理 下班记录管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用,作为学校以及一些培训机构,都在用信息…...

记住这份软件测试八股文还怕不能拿offer?你值得拥有
前言 2023秋招即将来临,很多同学会问软件测试面试八股文有必要背吗? 我的回答是:很有必要。你可以讨厌这种模式,但你一定要去背,因为不背你就进不了大厂。 国内的互联网面试,恐怕是现存的、最接近科举考试…...

2023年,在CSDN拥有10000粉丝有多难?
该数据来源于粉丝数人数排行前5000名用户的关注用户列表中产生的,由于采集样本数有限,数据可能具有一定的误差,仅供参考,本次采样用户数大概在100万以上。 筛选条件人数粉丝人数大于50007519粉丝人数大于100003763粉丝人数大于500…...

C++ -- 学习系列 关联式容器 set 与 map
一 关联式容器是什么? c 中有两种容器类型:关联式容器与序列式容器(顺序容器) 关联式中的容器是按照关键字来存储与访问的,序列式容器(顺序容器)则是元素在容器中的相对位置来存储与访问的。…...

Day 04 python学习笔记
Python数据容器 元组 元组的声明 变量名称(元素1,元素2,元素3,元素4…….) (元素类型可以不同) eg: tuple_01 ("hello", 1, 2,-20,[11,22,33]) print(type(tuple_01))结果&#x…...

Moonbeam Ignite强势回归
参与Moonbeam上最新的流动性计划 还记得新一轮的流动性激励计划吗?Moonbeam Ignite社区活动带着超过300万枚GLMR奖励来啦!体验新项目,顺便薅一把GLMR羊毛。 本次Moonbeam Ignite活动的参与项目均为第二批Moonbeam生态系统Grant资助提案中获…...
【改造后序遍历算法】95. 不同的二叉搜索树 II
95. 不同的二叉搜索树 II 解题思路 遍历每一个节点查看以k为根节点的二叉搜索树储存所有左子树的根节点储存所有右子树的根节点将左子树和右子树组装起来 将根节点储存在向量中 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeN…...
栈的基本操作(数据结构)
顺序栈的基本操作 #include <stdlib.h> #include <iostream> #include <stdio.h> #define MaxSize 10typedef struct{int data[MaxSize];int top; }SqStack;//初始化栈 void InitStack(SqStack &S){S.top -1; } //判断栈空 bool StackEmpty(SqStack S)…...
D. Jellyfish and Mex Codeforces Round 901 (Div. 2)
Problem - D - Codeforces 题目大意:有一个n个数的数组a,数m初始为0,每次操作可以删除任意一个数,然后m加上那个数,求n次操作和m的最小值 1<n<5000;0<a[i]<1e9 思路:可以发现&am…...

操作系统内存管理相关
1. 虚拟内存 1.1 什么是虚拟内存 虚拟内存是计算机系统内存管理的一种技术,我们可以手动设置自己电脑的虚拟内存。不要单纯认为虚拟内存只是“使用硬盘空间来扩展内存“的技术。虚拟内存的重要意义是它定义了一个连续的虚拟地址空间,并且 把内存扩展到硬…...

Sui流动性质押黑客松获胜者公布,助力资产再流通
Sui流动质押黑客松于日前结束Demo Day演示,其中有五个团队获奖、六个团队荣誉提名,共有超过30个项目获得参赛资格。此外,有两个团队赢得了Sui上DeFi协议提供的赏金。 本次黑客松的目的是挖掘并奖励将流动质押功能集成到其apps和产品中的开发…...

为什么在使用PageHelper插件时,指定的每页记录数大小失效?显示所有的记录数
1.问题现象: 这里指定每页显示5条,却把所有的记录数都显示出来了 2.分析: 之前是可以的,然后发现:PageHelper.startPage(pageNum,pageSize) 和执行sql的语句 顺序颠倒了,然后就出错了。 3.验证…...
XML文档基础
什么是XML XML (eXtensible Markup Language,可扩展标记语言) 是一种用于存储和传输数据的文本文件格式。用户可以按照XML规则自定义标记,XML 的设计目标是传输数据,而不是显示数据,因此它是一种通用的标记语言,可用于…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...