当前位置: 首页 > news >正文

HTTP 四、HttpClient的使用

一、简单介绍

        1、简介

        HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。

         HTTP和浏览器有点像,但却不是浏览器。很多人觉得既然HttpClient是一个HTTP客户端编程工具,很多人把他当做浏览器来理解,但是其实HttpClient不是浏览器,它是一个HTTP通信库,因此它只提供一个通用浏览器应用程序所期望的功能子集,最根本的区别是HttpClient中没有用户界面,浏览器需要一个渲染引擎来显示页面,并解释用户输入,例如鼠标点击显示页面上的某处,有一个布局引擎,计算如何显示HTML页面,包括级联样式表和图像。javascript解释器运行嵌入HTML页面或从HTML页面引用的javascript代码。来自用户界面的事件被传递到javascript解释器进行处理。除此之外,还有用于插件的接口,可以处理Applet,嵌入式媒体对象(如pdf文件,Quicktime电影和Flash动画)或ActiveX控件(可以执行任何操作)。HttpClient只能以编程的方式通过其API用于传输和接受HTTP消息。

      2、特性:
  1. 基于标准、纯净的java语言。实现了Http1.0和Http1.1
  2. 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。
  3.  支持HTTPS协议。
  4. 通过Http代理建立透明的连接。
  5. 利用CONNECT方法通过Http代理建立隧道的https连接。
  6. Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。
  7.  插件式的自定义认证方案。
  8. 便携可靠的套接字工厂使它更容易的使用第三方解决方案。
  9. 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。
  10.  自动处理Set-Cookie中的Cookie。
  11. 插件式的自定义Cookie策略。
  12. Request的输出流可以避免流中内容直接缓冲到socket服务器。
  13. Response的输入流可以有效的从socket服务器直接读取相应内容。
  14.  在http1.0和http1.1中利用KeepAlive保持持久连接。
  15.  直接获取服务器发送的response code和 headers。
  16.  设置连接超时的能力。
  17. 实验性的支持http1.1 response caching。
  18. 源代码基于Apache License 可免费获取。

二、简单使用

        1、引入依赖

        <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version></dependency>

        2、使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。

   //1. 创建HttpClient对象。CloseableHttpClient httpClient = HttpClientBuilder.create().build();//2. 创建请求方法的实例,并指定请求URL。// 如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。HttpGet httpGet = new HttpGet("http://localhost:8090/emp/get");//3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HttpParams params)方法来添加请求参数;// 对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。// 响应模型CloseableHttpResponse response = null;try {// 4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,// 该方法返回一个HttpResponse。response = httpClient.execute(httpGet);// 从响应模型中获取响应实体//5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;// 调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。HttpEntity responseEntity = response.getEntity();System.out.println("响应状态为:" + response.getStatusLine());if (responseEntity != null) {System.out.println("响应内容长度为:" + responseEntity.getContentLength());System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));}} catch (ClientProtocolException e) {e.printStackTrace();} catch (ParseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {// 6. 释放连接。无论执行方法是否成功,都必须释放连接if (httpClient != null) {httpClient.close();}if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}

三、各种使用案例

        1、GET请求  没有参数
       //1、创建HttpClient 客户端CloseableHttpClient httpClient = HttpClientBuilder.create().build();//2、 创建请求方法的实例,并指定请求URLHttpGet httpGet = new HttpGet("http://localhost:8090/user/get");//响应模型CloseableHttpResponse response = null;try {// 由客户端执行发送Get请求response = httpClient.execute(httpGet);// 从响应模型中获取响应实体HttpEntity responseEntity = response.getEntity();System.out.println("响应状态为:" + response.getStatusLine());if (responseEntity != null) {System.out.println("响应内容长度为:" + responseEntity.getContentLength());System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));}} catch (ClientProtocolException e) {e.printStackTrace();} catch (ParseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {// 释放资源if (httpClient != null) {httpClient.close();}if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}
        2、GET 请求 路径上拼接参数

        1)直接拼接参数

String userId = "1";String userName = "张三";//1、创建HttpClient 客户端CloseableHttpClient httpClient = HttpClientBuilder.create().build();//参数 拼接StringBuffer params = new StringBuffer();try {// 字符数据最好encoding一下;这样一来,某些特殊字符才能传过去(如:某人的名字就是“&”,不encoding的话,传不过去)params.append("userId=" + URLEncoder.encode(userId, "utf-8"));params.append("&");params.append("userName="+ URLEncoder.encode(userName, "utf-8"));} catch (UnsupportedEncodingException e1) {e1.printStackTrace();}//2、 创建请求方法的实例,并指定请求URLHttpGet httpGet = new HttpGet("http://localhost:8090/user/get"+ "?" + params);//响应模型CloseableHttpResponse response = null;try {//添加配置信息RequestConfig requestConfig  = RequestConfig.custom()//设置连接超时时间(单位毫秒).setConnectTimeout(5000)//设置请求超时时间(单位毫秒).setConnectionRequestTimeout(5000)//socket读写超时时间(单位毫秒).setSocketTimeout(50000)//设置是否允许重定向(默认为true).setRedirectsEnabled(true).build();// 将上面的配置信息,添加到Get请求中httpGet.setConfig(requestConfig);// 由客户端执行发送Get请求response = httpClient.execute(httpGet);// 从响应模型中获取响应实体HttpEntity responseEntity = response.getEntity();System.out.println("响应状态为:" + response.getStatusLine());if (responseEntity != null) {System.out.println("响应内容长度为:" + responseEntity.getContentLength());System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));}} catch (ClientProtocolException e) {e.printStackTrace();} catch (ParseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {// 释放资源if (httpClient != null) {httpClient.close();}if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}

        2)使用URI获得HttpGet

   String userId = "1";String userName = "张三";//1、创建HttpClient 客户端CloseableHttpClient httpClient = HttpClientBuilder.create().build();// 使用URI 拼接好请求路径URI uri = null;try {// 将参数放入键值对类NameValuePair中,再放入集合中List<NameValuePair> params = new ArrayList<>();params.add(new BasicNameValuePair("userId", userId));params.add(new BasicNameValuePair("userName", userName));// 设置uri信息,并将参数集合放入uri;// 注:这里也支持一个键值对一个键值对地往里面放setParameter(String key, String value)uri = new URIBuilder().setScheme("http").setHost("localhost").setPort(8090).setPath("/user/get").setParameters(params).build();} catch (URISyntaxException e1) {e1.printStackTrace();}//2、 创建请求方法的实例,并指定请求URLHttpGet httpGet = new HttpGet(uri);//响应模型CloseableHttpResponse response = null;try {//添加配置信息RequestConfig requestConfig  = RequestConfig.custom()//设置连接超时时间(单位毫秒).setConnectTimeout(5000)//设置请求超时时间(单位毫秒).setConnectionRequestTimeout(5000)//socket读写超时时间(单位毫秒).setSocketTimeout(50000)//设置是否允许重定向(默认为true).setRedirectsEnabled(true).build();// 将上面的配置信息,添加到Get请求中httpGet.setConfig(requestConfig);// 由客户端执行发送Get请求response = httpClient.execute(httpGet);// 从响应模型中获取响应实体HttpEntity responseEntity = response.getEntity();System.out.println("响应状态为:" + response.getStatusLine());if (responseEntity != null) {System.out.println("响应内容长度为:" + responseEntity.getContentLength());System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));}} catch (ClientProtocolException e) {e.printStackTrace();} catch (ParseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {// 释放资源if (httpClient != null) {httpClient.close();}if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}
        3、POST请求 没有参数
         //1、创建HttpClient 客户端CloseableHttpClient httpClient = HttpClientBuilder.create().build();//2、 创建请求方法的实例,并指定请求URLHttpPost httpPost = new HttpPost("http://localhost:8090/user/get");//响应模型CloseableHttpResponse response = null;try {// 由客户端执行发送Post请求response = httpClient.execute(httpPost);// 从响应模型中获取响应实体HttpEntity responseEntity = response.getEntity();System.out.println("响应状态为:" + response.getStatusLine());if (responseEntity != null) {System.out.println("响应内容长度为:" + responseEntity.getContentLength());System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));}} catch (ClientProtocolException e) {e.printStackTrace();} catch (ParseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {// 释放资源if (httpClient != null) {httpClient.close();}if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}

        4、POST请求 有参(对象参数 或 路径参数)

        1)路径拼接参数

        String userId = "1";String userName = "张三";//1、创建HttpClient 客户端CloseableHttpClient httpClient = HttpClientBuilder.create().build();//参数 拼接StringBuffer params = new StringBuffer();try {// 字符数据最好encoding一下;这样一来,某些特殊字符才能传过去(如:某人的名字就是“&”,不encoding的话,传不过去)params.append("userId=" + URLEncoder.encode(userId, "utf-8"));params.append("&");params.append("userName="+ URLEncoder.encode(userName, "utf-8"));} catch (UnsupportedEncodingException e1) {e1.printStackTrace();}//2、 创建请求方法的实例,并指定请求URLHttpPost httpPost = new HttpPost("http://localhost:8090/user/get"+"?"+params);// 设置ContentType(注:一般路径拼接参数请求头都是application/x-www-form-urlencoded)httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");//响应模型CloseableHttpResponse response = null;try {//添加配置信息RequestConfig requestConfig  = RequestConfig.custom()//设置连接超时时间(单位毫秒).setConnectTimeout(5000)//设置请求超时时间(单位毫秒).setConnectionRequestTimeout(5000)//socket读写超时时间(单位毫秒).setSocketTimeout(50000)//设置是否允许重定向(默认为true).setRedirectsEnabled(true).build();// 将上面的配置信息,添加到Get请求中httpPost.setConfig(requestConfig);// 由客户端执行发送Get请求response = httpClient.execute(httpPost);// 从响应模型中获取响应实体HttpEntity responseEntity = response.getEntity();System.out.println("响应状态为:" + response.getStatusLine());if (responseEntity != null) {System.out.println("响应内容长度为:" + responseEntity.getContentLength());System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));}} catch (ClientProtocolException e) {e.printStackTrace();} catch (ParseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {// 释放资源if (httpClient != null) {httpClient.close();}if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}

        2)对象参数

//1、创建HttpClient 客户端CloseableHttpClient httpClient = HttpClientBuilder.create().build();//2、 创建请求方法的实例,并指定请求URLHttpPost httpPost = new HttpPost("http://localhost:8090/user/get");User user = new User();user.setId(1L);user.setName("张三");// 我这里利用阿里的fastjson,将Object转换为json字符串;// (需要导入com.alibaba.fastjson.JSON包)String jsonString = JSON.toJSONString(user);// post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中StringEntity entity = new StringEntity(jsonString, "UTF-8");httpPost.setEntity(entity);// json参数需要设置请求头为 application/jsonhttpPost.setHeader("Content-Type", "application/json;charset=utf8");//响应模型CloseableHttpResponse response = null;try {//添加配置信息RequestConfig requestConfig  = RequestConfig.custom()//设置连接超时时间(单位毫秒).setConnectTimeout(5000)//设置请求超时时间(单位毫秒).setConnectionRequestTimeout(5000)//socket读写超时时间(单位毫秒).setSocketTimeout(50000)//设置是否允许重定向(默认为true).setRedirectsEnabled(true).build();// 将上面的配置信息,添加到Get请求中httpPost.setConfig(requestConfig);// 由客户端执行发送Get请求response = httpClient.execute(httpPost);// 从响应模型中获取响应实体HttpEntity responseEntity = response.getEntity();System.out.println("响应状态为:" + response.getStatusLine());if (responseEntity != null) {System.out.println("响应内容长度为:" + responseEntity.getContentLength());System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));}} catch (ClientProtocolException e) {e.printStackTrace();} catch (ParseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {// 释放资源if (httpClient != null) {httpClient.close();}if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}

        3)(普通参数 + 对象参数)

String userId = "1";String userName = "张三";//1、创建HttpClient 客户端CloseableHttpClient httpClient = HttpClientBuilder.create().build();//参数 拼接StringBuffer params = new StringBuffer();try {// 字符数据最好encoding一下;这样一来,某些特殊字符才能传过去(如:某人的名字就是“&”,不encoding的话,传不过去)params.append("userId=" + URLEncoder.encode(userId, "utf-8"));params.append("&");params.append("userName="+ URLEncoder.encode(userName, "utf-8"));} catch (UnsupportedEncodingException e1) {e1.printStackTrace();}//2、 创建请求方法的实例,并指定请求URLHttpPost httpPost = new HttpPost("http://localhost:8090/user/get"+"?"+params);User user = new User();user.setId(1L);user.setName("张三");// 我这里利用阿里的fastjson,将Object转换为json字符串;// (需要导入com.alibaba.fastjson.JSON包)String jsonString = JSON.toJSONString(user);// post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中StringEntity entity = new StringEntity(jsonString, "UTF-8");httpPost.setEntity(entity);// json参数需要设置请求头为 application/jsonhttpPost.setHeader("Content-Type", "application/json;charset=utf8");//响应模型CloseableHttpResponse response = null;try {//添加配置信息RequestConfig requestConfig  = RequestConfig.custom()//设置连接超时时间(单位毫秒).setConnectTimeout(5000)//设置请求超时时间(单位毫秒).setConnectionRequestTimeout(5000)//socket读写超时时间(单位毫秒).setSocketTimeout(50000)//设置是否允许重定向(默认为true).setRedirectsEnabled(true).build();// 将上面的配置信息,添加到Get请求中httpPost.setConfig(requestConfig);// 由客户端执行发送Get请求response = httpClient.execute(httpPost);// 从响应模型中获取响应实体HttpEntity responseEntity = response.getEntity();System.out.println("响应状态为:" + response.getStatusLine());if (responseEntity != null) {System.out.println("响应内容长度为:" + responseEntity.getContentLength());System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));}} catch (ClientProtocolException e) {e.printStackTrace();} catch (ParseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {// 释放资源if (httpClient != null) {httpClient.close();}if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}

        

        5、使用httpClient下载文件

        使用httpclient下载文件,其实在调用上跟上面没有区别,唯一需要注意的是,再获取响应实体时,容易出现 Attempted read from closed stream尝试读取关闭的流 异常,我们可以用BufferedHttpEntity 的方式获取流:

//1、创建HttpClient 客户端CloseableHttpClient httpClient = HttpClientBuilder.create().build();//2、 创建请求方法的实例,并指定请求URLHttpPost httpPost = new HttpPost("http://localhost:8090/user/get");//响应模型CloseableHttpResponse response = null;try {//添加配置信息RequestConfig requestConfig  = RequestConfig.custom()//设置连接超时时间(单位毫秒).setConnectTimeout(5000)//设置请求超时时间(单位毫秒).setConnectionRequestTimeout(5000)//socket读写超时时间(单位毫秒).setSocketTimeout(50000)//设置是否允许重定向(默认为true).setRedirectsEnabled(true).build();// 将上面的配置信息,添加到Get请求中httpPost.setConfig(requestConfig);// 由客户端执行发送Get请求response = httpClient.execute(httpPost);// 从响应模型中获取响应实体HttpEntity responseEntity = response.getEntity();//entity实体流保存缓冲区,否则只能操作一次流就会关闭 ,BufferedHttpEntity可以多次读取流responseEntity = new BufferedHttpEntity(responseEntity);System.out.println("响应状态为:" + response.getStatusLine());if (responseEntity != null) {System.out.println("响应内容长度为:" + responseEntity.getContentLength());System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));try(FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\新建文件夹 (2)\\测试.docx")){responseEntity.writeTo(fileOutputStream);}}} catch (ClientProtocolException e) {e.printStackTrace();} catch (ParseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {// 释放资源if (httpClient != null) {httpClient.close();}if (response != null) {response.close();}} catch (IOException e) {e.printStackTrace();}}
        6、关于https的调用

        目前还没使用到,等使用到再补充。

四、HttpClient连接池

        事实上对于httpClient 连接池以及相关的配置大有学问,针对高并发的场景有很多解决策略,这里只先简单介绍一下如何配置连接池以及怎么使用,复杂的业务范围可自行查询。

   HttpClient连接池是用于优化HTTP请求性能的一个关键机制,特别是在处理大量HTTP请求时,通过重用现有连接来减少每次新建连接的开销。连接池的主要优势包括减少建立连接的时间、减少资源消耗、提高请求的并发处理能力。

        以下是HttpClient连接池的几个核心概念和配置:

        

        1. 连接池的作用

        每次HTTP请求都需要进行TCP握手,特别是对于HTTPS,还需要进行TLS握手,这个过程非常耗时。连接池通过复用连接(连接保持在一个"池"中)避免了为每次请求都新建连接,从而大大提高性能。

        2、配置HttpClient连接池

        在Apache HttpClient中,可以通过PoolingHttpClientConnectionManager类来配置连接池。以下是一个基本的配置示例:

// 创建连接池管理器
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
// 设置最大连接数
cm.setMaxTotal(100);
// 设置每个路由的最大连接数
cm.setDefaultMaxPerRoute(20);
// 创建HttpClient实例
CloseableHttpClient client = HttpClients.custom().setConnectionManager(connectionManager).setConnectionManagerShared(true).evictIdleConnections(30, TimeUnit.SECONDS)  // 超过30秒的闲置连接会被清除.build();

最大连接数(MaxTotal): 池中允许的最大连接数。默认值较小,通常需要根据实际情况调大。

每个路由的最大连接数(DefaultMaxPerRoute): 每个目标主机(路由)允许的最大并发连接数。不同的主机或API服务器通常会有各自的并发限制。

保持连接活动时间(ConnectionKeepAlive): 指定一个连接在闲置后可以保持多久。短时间的保活可以避免不必要的重建连接,但太长时间可能导致连接闲置过多,浪费资源。

        注意事项

  • 连接泄漏: 如果不正确管理连接(如未关闭),可能会导致连接泄漏,从而耗尽连接池中的可用连接,影响系统的稳定性。
  • 线程安全: PoolingHttpClientConnectionManager是线程安全的,可以在多个线程中共享同一个HttpClient实例。

高并发场景下的 HttpClient 优化方案,QPS 大大提升!

相关文章:

HTTP 四、HttpClient的使用

一、简单介绍 1、简介 HttpClient是Apache Jakarta Common下的子项目&#xff0c;用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包&#xff0c;并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中&#xff0c;比如Apache Jakarta上很著…...

C语言:结构体变量

1. 结构体变量的引用方法 例如&#xff0c;若有数据定义&#xff1a; struct Student{char name[10];int age;struct Date birthday; }s1,s2,stu[10]; 则下面对结构体变量的引用都是正确的&#xff1a; s1.age20; scanf("%d",&s1.age); gets(stu[0].name); s…...

bibtex是什么

BibTeX 是一个用于处理和格式化参考文献的工具&#xff0c;常与 LaTeX 一起使用。它提供了一种方便的方式来管理和生成参考文献列表&#xff0c;特别适用于学术写作和科研论文中。以下是对 BibTeX 的详细介绍&#xff1a; 基本概念 BibTeX 是 LaTeX 的一个附加工具&#xff0…...

【大模型专栏—进阶篇】智能对话全总结

大模型专栏介绍 &#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本文为大模型专栏子篇&#xff0c;大模型专栏将持续更新&#xff0c;主要讲解大模型从入门到实战打怪升级。如有兴趣&#xff0c;欢迎您的阅读。 &#x1f4…...

MVC应用单元测试以及请求参数的验证

SpringMVC支持对Controller单元测试 RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(locations {"classpath:mvc-dispatcher-servlet.xml", }) WebAppConfiguration public class ControllerJUnitBase{Resourceprivate RequestMappingHandlerMappin…...

算法:TopK问题

题目 有10亿个数字&#xff0c;需要找出其中的前k大个数字。 为了方便讲解&#xff0c;这里令k为5。 思路分析&#xff08;以找前k大个数字为例&#xff09; 很容易想到&#xff0c;进行排序&#xff0c;然后取前k个数字即可。 但是&#xff0c;难点在于&#xff0c;10亿个数…...

.json文件的C#解析,基于Newtonsoft.Json插件

目录 1. 前言 2. 正文 2.1 问题 2.2 解决办法 2.2.1 思路 2.2.2 代码实现 2.2.3 测试结果 3. 备注 1. 前言 天气晚来秋,这几天天气变凉了,各位同学注意好多穿衣服。回归正题 由于需要,需要将json的配置里面的调理解析出来,做成接口,以便于开发。 2. 正文 2.1 …...

四、(JS)JS中常见的加载事件

一、文档加载监听 &#xff08;1&#xff09;抛出疑惑&#xff0c;什么是文档加载监听&#xff1f;为什么要有这个东西&#xff1f; 老样子&#xff0c;我们先讲一个场景&#xff0c;带着大家熟悉为什么会有文档加载监听&#xff0c;是来解决什么问题来着的。 我们先看下这段…...

[网络]https的概念及加密过程

文章目录 一. HTTPS二. https加密过程 一. HTTPS https本质上就是http的基础上增加了一个加密层, 抛开加密之后, 剩下的就是个http是一样的 s > SSL HTTPS HTTP SSL 这个过程, 涉及到密码学的几个核心概念 明文 要传输的真正意思是啥 2)密文 加密之后得到的数据 这个密文…...

React 嵌套类名样式不生效

修改前 父级.blog样式生效&#xff0c;子级.circle样式不生效 // app/blog/page.js import styles from "./page.module.scss"export default function Blog () {return (<div className{styles.blog}><div classNamecircle><div /></div>…...

20Kg载重30分钟续航多旋翼无人机技术详解

一、机架与结构设计 1. 材料选择&#xff1a;为了确保无人机能够承载20Kg的负载&#xff0c;同时实现30分钟的续航&#xff0c;其机架材料需选用轻质高强度的材料&#xff0c;如碳纤维或铝合金。这些材料不仅具有良好的承重能力&#xff0c;还能有效减轻无人机的整体重量&…...

详解c++:认识类

文章目录 前言一、类是什么二、类&#xff08;class&#xff09;的使用publicprivate&#xff1a;protected&#xff1a; 前言 C 是一种面向对象的编程语言。面向对象编程是一种编程范式&#xff0c;它使用“对象”来设计软件应用程序。在面向对象编程中&#xff0c;对象包含了…...

HTML5中的重要元素详解

第3章 HTML5中的重要元素 3.1 html根元素 HTML文档中&#xff0c;元素html代表了文档的根&#xff0c;其他所有元素都是在该元素的基础上进行延伸或拓展的&#xff0c;该元素也是HTML文档的最外层元素&#xff0c;因此也称为根元素。 html元素的常用属性&#xff1a; manif…...

八股文知识汇总(常考)

八股文知识汇总&#xff08;常考&#xff09; 语言特性相关 JAVA知识 - JDK动态代理为什么只能代理有接口的类&#xff1f; 说一下对象创建的过程&#xff1f;ThreadLocal是什么&#xff1f;他的实现原理是什么&#xff1f;ThreadLocal会出现内存泄露吗&#xff1f;String、…...

unity 图片置灰shader

我和chatgpt真强&#xff01; 在 Unity 编辑器中&#xff0c;右键点击 Assets 文件夹&#xff0c;选择 Create -> Shader -> Unlit Shader。shader代码如下&#xff0c;尽管我看的不是很懂&#xff0c;但确实有用 Shader "Custom/GrayScaleShader" {Properti…...

【C语言】(指针系列2)指针运算+指针与数组的关系+二级指针+指针数组+《剑指offer面试题》

前言&#xff1a;开始之前先感谢一位大佬&#xff0c;清风~徐~来-CSDN博客&#xff0c;由于是时间久远&#xff0c;博主指针的系列忘的差不多了&#xff0c;所以有些部分借鉴了该播主的&#xff0c;有些地方如果解释的不到位&#xff0c;请翻看这位大佬的&#xff0c;感谢大家&…...

探索信号处理:使用傅里叶小波变换分析和恢复信号

在现代信号处理领域&#xff0c;傅里叶变换是分析和处理信号的一种基本工具。然而&#xff0c;传统的傅里叶变换在处理非平稳信号时存在局限性&#xff0c;因为它无法同时提供时间和频率的信息。为了克服这一挑战&#xff0c;傅里叶小波变换&#xff08;FSWT&#xff09;应运而…...

俄罗斯方块——C语言实践(Dev-Cpp)

目录 1、创建项目(尽量不使用中文路径) 2、项目复制 3、项目配置 ​1、调整编译器 2、在配置窗口选择参数标签 3、添加头文件路径和库文件路径 4、代码实现 4.1、main.c 4.2、draw.h 4.3、draw.c 4.4、shape.h 4.5、shape.c 4.6、board.h 4.7、board.c 4.8、cont…...

关于wp网站出现的问题

问题1 问题1&#xff1a;如果出现这个界面的问题 说明是根目录的index.php编码出了问题&#xff0c;用备份的源文件退换一下即可。 问题2 问题2&#xff1a;如果出现页面错位现象&#xff0c;可能是某个WP插件引起的问题&#xff0c;这里需要逐步排查插件&#xff0c;或者你刚…...

为什么H.266未能普及?EasyCVR视频编码技术如何填补市场空白

H.266&#xff0c;也被称为Versatile Video Coding&#xff08;VVC&#xff09;&#xff0c;是近年来由MPEG&#xff08;Moving Picture Experts Group&#xff09;和ITU&#xff08;International Telecommunication Union&#xff09;联合开发并发布的新一代国际视频编码标准…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...