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、特性:
- 基于标准、纯净的java语言。实现了Http1.0和Http1.1
- 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。
- 支持HTTPS协议。
- 通过Http代理建立透明的连接。
- 利用CONNECT方法通过Http代理建立隧道的https连接。
- Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。
- 插件式的自定义认证方案。
- 便携可靠的套接字工厂使它更容易的使用第三方解决方案。
- 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。
- 自动处理Set-Cookie中的Cookie。
- 插件式的自定义Cookie策略。
- Request的输出流可以避免流中内容直接缓冲到socket服务器。
- Response的输入流可以有效的从socket服务器直接读取相应内容。
- 在http1.0和http1.1中利用KeepAlive保持持久连接。
- 直接获取服务器发送的response code和 headers。
- 设置连接超时的能力。
- 实验性的支持http1.1 response caching。
- 源代码基于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下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著…...
C语言:结构体变量
1. 结构体变量的引用方法 例如,若有数据定义: struct Student{char name[10];int age;struct Date birthday; }s1,s2,stu[10]; 则下面对结构体变量的引用都是正确的: s1.age20; scanf("%d",&s1.age); gets(stu[0].name); s…...
bibtex是什么
BibTeX 是一个用于处理和格式化参考文献的工具,常与 LaTeX 一起使用。它提供了一种方便的方式来管理和生成参考文献列表,特别适用于学术写作和科研论文中。以下是对 BibTeX 的详细介绍: 基本概念 BibTeX 是 LaTeX 的一个附加工具࿰…...

【大模型专栏—进阶篇】智能对话全总结
大模型专栏介绍 😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本文为大模型专栏子篇,大模型专栏将持续更新,主要讲解大模型从入门到实战打怪升级。如有兴趣,欢迎您的阅读。 Ǵ…...
MVC应用单元测试以及请求参数的验证
SpringMVC支持对Controller单元测试 RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(locations {"classpath:mvc-dispatcher-servlet.xml", }) WebAppConfiguration public class ControllerJUnitBase{Resourceprivate RequestMappingHandlerMappin…...

算法:TopK问题
题目 有10亿个数字,需要找出其中的前k大个数字。 为了方便讲解,这里令k为5。 思路分析(以找前k大个数字为例) 很容易想到,进行排序,然后取前k个数字即可。 但是,难点在于,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中常见的加载事件
一、文档加载监听 (1)抛出疑惑,什么是文档加载监听?为什么要有这个东西? 老样子,我们先讲一个场景,带着大家熟悉为什么会有文档加载监听,是来解决什么问题来着的。 我们先看下这段…...

[网络]https的概念及加密过程
文章目录 一. HTTPS二. https加密过程 一. HTTPS https本质上就是http的基础上增加了一个加密层, 抛开加密之后, 剩下的就是个http是一样的 s > SSL HTTPS HTTP SSL 这个过程, 涉及到密码学的几个核心概念 明文 要传输的真正意思是啥 2)密文 加密之后得到的数据 这个密文…...
React 嵌套类名样式不生效
修改前 父级.blog样式生效,子级.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. 材料选择:为了确保无人机能够承载20Kg的负载,同时实现30分钟的续航,其机架材料需选用轻质高强度的材料,如碳纤维或铝合金。这些材料不仅具有良好的承重能力,还能有效减轻无人机的整体重量&…...
详解c++:认识类
文章目录 前言一、类是什么二、类(class)的使用publicprivate:protected: 前言 C 是一种面向对象的编程语言。面向对象编程是一种编程范式,它使用“对象”来设计软件应用程序。在面向对象编程中,对象包含了…...

HTML5中的重要元素详解
第3章 HTML5中的重要元素 3.1 html根元素 HTML文档中,元素html代表了文档的根,其他所有元素都是在该元素的基础上进行延伸或拓展的,该元素也是HTML文档的最外层元素,因此也称为根元素。 html元素的常用属性: manif…...
八股文知识汇总(常考)
八股文知识汇总(常考) 语言特性相关 JAVA知识 - JDK动态代理为什么只能代理有接口的类? 说一下对象创建的过程?ThreadLocal是什么?他的实现原理是什么?ThreadLocal会出现内存泄露吗?String、…...

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

【C语言】(指针系列2)指针运算+指针与数组的关系+二级指针+指针数组+《剑指offer面试题》
前言:开始之前先感谢一位大佬,清风~徐~来-CSDN博客,由于是时间久远,博主指针的系列忘的差不多了,所以有些部分借鉴了该播主的,有些地方如果解释的不到位,请翻看这位大佬的,感谢大家&…...

探索信号处理:使用傅里叶小波变换分析和恢复信号
在现代信号处理领域,傅里叶变换是分析和处理信号的一种基本工具。然而,传统的傅里叶变换在处理非平稳信号时存在局限性,因为它无法同时提供时间和频率的信息。为了克服这一挑战,傅里叶小波变换(FSWT)应运而…...

俄罗斯方块——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:如果出现这个界面的问题 说明是根目录的index.php编码出了问题,用备份的源文件退换一下即可。 问题2 问题2:如果出现页面错位现象,可能是某个WP插件引起的问题,这里需要逐步排查插件,或者你刚…...

为什么H.266未能普及?EasyCVR视频编码技术如何填补市场空白
H.266,也被称为Versatile Video Coding(VVC),是近年来由MPEG(Moving Picture Experts Group)和ITU(International Telecommunication Union)联合开发并发布的新一代国际视频编码标准…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...

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

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

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

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...

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