springboot http添加请求头 添加请求证书
首先明确两个事情:请求对象,连接对象
我们知道你要是想发起一个请求,需要指定两个环节内容,一个是请求内容对象(request),一个是连接内容对象(httpClient)
它们两个的作用我们在下面会看到
简要分析源码
1.先说一下结论,spring所有的核心代码都在doxxx()方法里面,而http请求的核心代码在doExecute()中。
# 我们平时会写这个一个方法去开启http请求调用
restTemplate.postForObject(url,httpEntity, xxx.class);# 往里钻
@Nullablepublic <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {RequestCallback requestCallback = this.httpEntityCallback(request, responseType);HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, (Object[])uriVariables);}#继续钻,发现了doxxx()方法
@Nullablepublic <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException {URI expanded = this.getUriTemplateHandler().expand(url, uriVariables);return this.doExecute(expanded, method, requestCallback, responseExtractor);}#看看实现,我们会发现有一个创建request的操作
@Nullableprotected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {Assert.notNull(url, "URI is required");Assert.notNull(method, "HttpMethod is required");ClientHttpResponse response = null;Object var14;try {# 核心!!!ClientHttpRequest request = this.createRequest(url, method);if (requestCallback != null) {requestCallback.doWithRequest(request);}response = request.execute();this.handleResponse(url, method, response);var14 = responseExtractor != null ? responseExtractor.extractData(response) : null;} catch (IOException var12) {String resource = url.toString();String query = url.getRawQuery();resource = query != null ? resource.substring(0, resource.indexOf(63)) : resource;throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + resource + "\": " + var12.getMessage(), var12);} finally {if (response != null) {response.close();}}return var14;}# 我们发现所有的request对象都是通过factory创建的,不同的factory会创建不同的request对象
# 因为目前我们位于抽象类HttpAccessor中,所以我们要继续往实现类追踪getRequestFactory()方法
protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {ClientHttpRequest request = this.getRequestFactory().createRequest(url, method);this.initialize(request);if (this.logger.isDebugEnabled()) {this.logger.debug("HTTP " + method.name() + " " + url);}return request;}# 此时我们位于InterceptingHttpAccessor抽象类中,继续往下追踪就是RestInterceptors类了,没有重写getRequestFactory()方法,所以我们要重点关注InterceptingHttpAccessor抽象类中的重写逻辑:
public ClientHttpRequestFactory getRequestFactory() {List<ClientHttpRequestInterceptor> interceptors = this.getInterceptors();if (!CollectionUtils.isEmpty(interceptors)) {ClientHttpRequestFactory factory = this.interceptingRequestFactory;if (factory == null) {// 如果有interceptors,则融合父类的factory和interceptors,返回一个新的factory来覆盖原有父类factoryfactory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors);this.interceptingRequestFactory = (ClientHttpRequestFactory)factory;}return (ClientHttpRequestFactory)factory;} else {// 如果没有则interceptors,则直接用父类中的factory,return super.getRequestFactory();}}
至此,我们可以得到以下结论,如果想对原有请求进行扩展,我们需要从两个对象进行下手:factory,interceptor。
接下来我们看一下factory和interceptor两个类中都有什么内容:
#factory
public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequestFactory, DisposableBean {// 重点关注!!!连接对象private HttpClient httpClient;@Nullableprivate RequestConfig requestConfig;private boolean bufferRequestBody = true;@Nullableprivate BiFunction<HttpMethod, URI, HttpContext> httpContextFactory;
}#interceptor
public interface ClientHttpRequestInterceptor {// 重点关注!!!request对象ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException;
}
我们可以发现在factory中我们可以对连接对象进行修改,在interceptor中可以对请求对象进行修改;我们回归下文章开头,一个请求的两个组成部分我们已经发现了。接下来就演示下不同场景应该怎么使用这两种对象。
场景1:添加固定请求头
分析:请求头内容属于请求对象,所以我们通过interceptor来实现
@Configuration
public class RestTemplateConfig {/*** restTemplate*/@ConditionalOnMissingBean@Beanpublic RestTemplate restTemplate(ClientHttpRequestFactory factory) {RestTemplate restTemplate = new RestTemplate();ClientHttpRequestInterceptor clientHttpRequestInterceptor = new ClientHttpRequestInterceptor() {@Overridepublic ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)throws IOException {request.getHeaders().set("X-ID", "");request.getHeaders().set("X-APPKEY", "");return execution.execute(request, body);}};restTemplate.setInterceptors(Collections.singletonList(clientHttpRequestInterceptor));return restTemplate;}
}
场景二:添加请求证书
分析:请求头内容属于连接对象,所以我们通过factory来实现
public static HttpComponentsClientHttpRequestFactory generateHttpRequestFactory() {TrustStrategy acceptingTrustStrategy = (x509Certificates, authType) -> true;SSLContext sslContext = null;try {sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy)// 增加请求证书.loadKeyMaterial(ks, keyStorePassword.toCharArray()).setProtocol("TLSv1.2").build();} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {log.error("generateHttpRequestFactory failed:", e);}SSLConnectionSocketFactory connectionSocketFactory =new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());HttpClientBuilder httpClientBuilder = HttpClients.custom();httpClientBuilder.setSSLSocketFactory(connectionSocketFactory);CloseableHttpClient httpClient = httpClientBuilder.build();HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();factory.setHttpClient(httpClient);factory.setConnectTimeout(15000);factory.setReadTimeout(5000);return factory;
}
当然两者可以同时存在:
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {// 修改factoryRestTemplate restTemplate = new RestTemplate(generateHttpRequestFactory());ClientHttpRequestInterceptor clientHttpRequestInterceptor = new ClientHttpRequestInterceptor() {@Overridepublic ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)throws IOException {request.getHeaders().set("X-HW-ID", "com.huawei.osec");request.getHeaders().set("X-HW-APPKEY", "/D2QodV7Lu2EUk4D9HEUsQ==");return execution.execute(request, body);}};// 修改interceptorrestTemplate.setInterceptors(Collections.singletonList(clientHttpRequestInterceptor));return restTemplate;}
相关文章:
springboot http添加请求头 添加请求证书
首先明确两个事情:请求对象,连接对象 我们知道你要是想发起一个请求,需要指定两个环节内容,一个是请求内容对象(request),一个是连接内容对象(httpClient) 它们两个的作用我们在下面会看到 简要分析源码 1.先说一下…...
【Qt之数据库操作】
使用Qt实现SQLite数据库操作可以分为以下几个步骤: 添加SQLite头文件和库文件: 在Qt项目中,需要在.pro文件中添加以下内容: QT sql打开/创建数据库: 可以使用QSqlDatabase类中的静态函数addDatabase()来添加数据库…...
数据结构(c语言版) 队列
链队列 要求:实现链队列的创建、初始化、入队、出队 (先进先出) 代码 // // Created by My.cy on 2023/10/19. // //链队列 创建、初始化、入队、出队 先进先出#include <stdio.h> #include <malloc.h>//定义结构体 struct…...
kimera论文阅读
文章目录 功能构成:Kimera线程A. Kimera-VIO:B. Kimera-RPGO:C. Kimera-Mesher:D. Kimera-Semantics:E.调试工具 功能构成: Kimera包括四个关键模块: Kimera-VIO的核心是基于gtsam的VIO方法[45],使用IMUpreintegration和无结构视觉因子[27]…...
golang gorm通过泛型实现通用单表增删改
golang gorm通过泛型实现通用单表增删改 无废话,直接上代码 想实现通用,首先得实现查询的通用,可以用传递map实现 func Where(where map[string]interface{}) func(db *gorm.DB) *gorm.DB {return func(db *gorm.DB) *gorm.DB {dbTmp : db…...
十、K8S之ConfigMap
ConfigMap 一、概念 在K8S中,ConfigMap是一种用于存储配置数据的API对象,一般用于存储Pod中应用所需的一些配置信息,或者环境变量。将配置于 Pod 分开,避免应为修改配置导致还需要重新构建 镜像与容器。 二、创建 可以使用 ku…...
python飞书群机器人通过webhook发送消息
python飞书群机器人通过webhook发送消息 import json import loggingimport requestslogger logging.getLogger(__name__) logging.basicConfig(levellogging.DEBUG)class FeishuTalk:"""飞书群机器人通过webhook发送消息"""def __init__(self…...
埃隆·马斯克的 AI 聊天机器人 Grok 已经上线
昨天,埃隆马斯克 (Elon Musk) 通过他的公司 xAI 推出了一款名为 Grok 的新型人工智能聊天机器人。这款新的聊天机器人将通过 Twitter 更新实时获取世界知识,使其成为最新的对话 AI 系统。 Grok 的独特和基本优势在于它可以通过 𝕏 平台实时了…...
【代码随想录】算法训练营 第十五天 第六章 二叉树 Part 2
102. 二叉树的层序遍历 层序遍历,就是一层一层地遍历二叉树,最常见的就是从上到下,从左到右来遍历,遍历的方法依然有两种,第一种是借助队列,第二种则是递归,都算是很简单、很容易理解的方法&am…...
使用ssl_certificate_by_lua指令动态加载证书
1、下载 OpenResty - 下载 根据自己系统选择下载,我的是64位 2、解压到目录 3、启动openresty 进入解压后的目录,执行nginx.exe 浏览器输入 http://localhost 查看是否正常。显示以下画面就表示没有问题。 接下来可以开始准备动态安装证书 4、使用o…...
Qt中Opencv转Qimage出现重影或者颜色不对
废话不多说 在qt中opencv获取的图像转qimage时出现重影原因: 图像数据的内存对齐可能会导致画面重影,如果出现误差转换出来的图就会出现重影 解决办法: cv::Mat image_bgr cv::imread(“example.jpg”); cv::Mat image_aligned; cv::copyMak…...
upload-labs-1
文章目录 Pass-01 Pass-01 先上传一个正常的图片,查看返回结果,结果中带有文件上传路径,可以进行利用: 上传一个恶意的webshell,里面写入一句话木马: <?php eval($_POST[cmd]); echo "hello&quo…...
【vite配置路径别名@】/启动配置
npm install types/node --save-dev npm install path --save import { defineConfig } from vite import vue from vitejs/plugin-vue // 配置别名 import { resolve } from "path";// https://vitejs.dev/config/ export default defineConfig({plugins: [vue()]…...
3. List
数据结构在Java集合中的对应关系 线性表【数组】 -> ArrayList 线性表【链表】-> LinkedList 队列 -> Queue -> LinkedList,PriorityQueue, ArrayBlockingQueue … etc. 双端队列 -> Deque -> ArrayDeque 栈 -> LinkedList 哈希表 -> Hash…...
Django初窥门径-oauth登录认证
引言 在现代Web应用程序中,用户身份验证和授权是至关重要的组成部分。Django,一个流行的Python Web框架,为用户身份验证提供了内置支持。本文将探讨如何创建和注册Django应用,自定义身份验证服务,配置AUTHENTICATION_…...
数学到底在哪里支撑着编程?
数学到底在哪里支撑着编程? 除了少数算法等明显相关情况外,说点日常的。 编程是个极度依赖逻辑的领域,逻辑严谨性好,你的编程工作会顺畅很多一-绝大多 数的bug都是最近很多小伙伴找我,说想要一些嵌入式的资料&#x…...
Python模块ADB的, 已经 pyadb
Python模块ADB的使用指南_笔记大全_设计学院 (python100.com) pip install adb Python 调用ADB_python 调用adb命令_实相实相的博客-CSDN博客 Python ADB.shell_command Examples, pyadb.ADB.shell_command Python Examples - HotExamples Gitee 极速下载/PyADB - 码云 - 开…...
猫头虎分享从Python到JavaScript传参数:多面手的数据传递术
🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…...
注解汇总:Spring 常用的注解
前言 本栏目的内容已经讲完了,本案例将把案例中所有讲到的注解都汇总起来,方便日后的学习需要用到的时候能够快速的找到相应的注解。本案例将结合小案例一起做汇总,也想丹玉是再复习一遍讲过用过的注解。 一、注解汇总 1、Component Reposi…...
合肥工业大学操作系统实验5
✅作者简介:CSDN内容合伙人、信息安全专业在校大学生🏆 🔥系列专栏 :hfut实验课设 📃新人博主 :欢迎点赞收藏关注,会回访! 💬舞台再大,你不上台,永远是个观众。平台再好,你不参与,永远是局外人。能力再大,你不行动,只能看别人成功!没有人会关心你付出过多少…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
