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)联合开发并发布的新一代国际视频编码标准…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
