tomcat和nginx
Tomcat 和 Nginx 都可以部署 Web 应用,但它们的核心功能和适用场景不同,因此在 2024 年生产环境及未来,是否使用 Tomcat 取决于需求和技术架构的特点。
1. Tomcat 的特点与适用场景
Tomcat 是 Java Servlet 容器,主要用来运行基于 Java 的 Web 应用,支持 Java Servlet、JSP(Java Server Pages)、以及 Java EE(Jakarta EE)标准的部分实现。以下是其关键特点:
特点
- 支持 Java 应用:Tomcat 专为 Java 构建,直接支持 Java Servlet、JSP 和其他 Java Web 技术。
- 动态内容处理:适用于运行动态应用程序,例如需要复杂后端逻辑的企业级 Java Web 应用。
- 内置 Servlet 容器:直接运行 Java 代码,简化了 Java 应用部署流程。
- 与开发框架兼容:能与 Spring、Hibernate 等流行的 Java 框架无缝集成。
适用场景
- 企业级应用:金融、银行、保险等行业大量使用 Java 构建其核心系统。
- 微服务架构:在基于 Spring Boot 的微服务中,Tomcat 通常作为默认嵌入式服务器。
- 需要 Servlet 容器:如果应用需要 Servlet 容器支持,Tomcat 是首选。
2. Nginx 的特点与适用场景
Nginx 是高性能的 HTTP 服务器和反向代理服务器,更适用于静态内容分发和负载均衡。以下是其关键特点:
特点
- 静态文件处理能力强:Nginx 优化了处理静态内容的性能,如 HTML、CSS、JS。
- 高并发性能:采用异步事件驱动架构,能够同时处理数十万并发连接。
- 负载均衡:支持多种策略,如轮询、IP 哈希。
- 反向代理和缓存:可以作为中间层,优化后端服务器的请求负载。
适用场景
- 前端服务:用作 CDN、反向代理、负载均衡器,特别是在前端与后端之间。
- 混合架构:搭配 Tomcat 等后端服务器,为用户提供更快的静态内容加载速度。
- 微服务网关:作为 API Gateway,管理微服务间的流量和路由。
3. 为什么在 2024 年及未来生产中选择 Tomcat
在现代 Web 架构中,Tomcat 仍然占据重要地位,特别是在需要运行 Java 后端的场景中。以下是选择 Tomcat 的原因:
优势
- Java 项目的需求:如果业务是基于 Java 技术栈开发的,Tomcat 是不可替代的,特别是在运行 Spring Framework 应用时。
- 内嵌轻量化部署:Spring Boot 提供了内嵌的 Tomcat,简化了微服务的部署和管理。
- 企业系统兼容性:许多遗留系统仍然基于 Java 构建,Tomcat 是这些系统的核心运行环境。
- 开发效率:对于 Java 开发团队,Tomcat 的易用性和工具链支持(如 Eclipse、IntelliJ IDEA)非常强大。
未来趋势
- 云原生与容器化支持:Tomcat 完全可以运行在容器中,且与 Kubernetes 等云原生平台兼容。
- 微服务生态:作为后端服务运行时的一部分,Tomcat 仍然是许多企业分布式系统架构的关键。
- Jakarta EE 的演进:Jakarta EE(Java EE 的继任)将持续发展,Tomcat 作为核心实现之一会保持其重要性。
4. Tomcat 与 Nginx 的协作
在生产中,Tomcat 通常与 Nginx 组合使用:
- Nginx:处理静态资源、负载均衡和反向代理。
- Tomcat:专注于动态内容的生成和 Java 应用的运行。
这种分层架构充分发挥两者的优势,提升性能和可靠性。
总结
在 2024 年及未来,选择 Tomcat 的关键在于是否有 Java 技术栈需求。对于高性能、静态内容交付,Nginx 是更好的选择,但 Tomcat 对于动态 Java 应用仍是无可替代的。两者结合使用能够满足复杂的生产需求,尤其是在云原生和微服务架构中,两者的作用会更加显著。
以下是关于 Tomcat 和 Nginx 配合部署 Web 网站 的实践案例和具体应用场景,重点解析它们的角色分工及优势:
案例一:动态与静态内容分离
- 背景:某电商网站使用 Tomcat 提供动态内容服务(如订单查询、商品详情等),但静态资源(如图片、CSS、JavaScript 文件)数量庞大。
- 配置:
- Nginx:用作反向代理和静态资源服务器。通过高效的 IO 处理,减少 Tomcat 的压力。
- Tomcat:负责处理动态请求,通过 Nginx 转发的 API 调用(如
/api/*)。
- 步骤:
- 配置 Nginx,将
/static/路径指向本地文件系统。 - 设置 Nginx 的反向代理,将
/api/请求转发到后端的 Tomcat(如http://localhost:8080)。 - 配置 gzip 和缓存头提升静态资源加载效率。
- 配置 Nginx,将
案例二:负载均衡与高可用
- 背景:某 SaaS 平台需要高可用架构,前端有大量用户访问,后端的 Tomcat 容易成为瓶颈。
- 配置:
- Nginx:配置为负载均衡器,分发请求到多个 Tomcat 实例。
- Tomcat:通过集群部署,支持高可用和故障切换。
- 步骤:
- 启用 Nginx 的
upstream模块,定义多个 Tomcat 后端服务器地址。 - 配置健康检查,确保 Nginx 自动剔除不可用的 Tomcat 实例。
- 使用 Tomcat 的 Session 复制功能,确保用户会话在多实例间保持一致。
- 启用 Nginx 的
案例三:SSL 加速与安全优化
- 背景:为了实现 HTTPS 加密,直接在 Tomcat 配置 SSL 性能较差。
- 解决方案:
- 使用 Nginx 实现 SSL 卸载。
- Tomcat 只处理解密后的 HTTP 流量。
- 配置:
- 在 Nginx 中绑定证书文件,启用
ssl模块。 - 配置
proxy_pass将解密后的请求转发给 Tomcat。 - 使用 HSTS 和其他安全头增强 HTTPS 安全性。
- 在 Nginx 中绑定证书文件,启用
总结
在 2024 年及未来,微服务、云原生架构和 DevOps 实践 使 Nginx 和 Tomcat 的协作更加紧密:
- Nginx 更适合处理边缘请求:流量分发、安全过滤、缓存优化等。
- Tomcat 专注于动态逻辑:结合 Java 技术栈,适用于复杂的后台服务。
这种分层设计确保了性能与扩展性的平衡,同时也符合未来分布式系统的最佳实践。
动态与静态内容分离的实践配置是现代Web架构优化的常见方案,能够提高网站性能、扩展性和安全性。以下是基于Tomcat和Nginx的具体配置案例:
场景背景
- 动态内容(如API、数据库交互)通过Tomcat处理。
- 静态内容(如HTML、CSS、JS、图片)通过Nginx处理。
配置步骤
1. 准备环境
- 安装Nginx:
sudo yum install nginx或sudo apt install nginx - 安装Tomcat:下载并解压官方Tomcat二进制包,或通过包管理器安装。
2. 配置Nginx
Nginx作为反向代理和静态资源服务器,以下是配置文件示例:
文件路径:/etc/nginx/nginx.conf
server {listen 80;server_name example.com;# 静态资源路径location /static/ {root /var/www/;}# 动态请求转发到Tomcatlocation / {proxy_pass http://127.0.0.1:8080;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}
}
3. 配置Tomcat
确保Tomcat仅处理动态内容,并调整监听端口以避免与Nginx冲突。
文件路径:$CATALINA_HOME/conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
- 部署动态Web应用到
$CATALINA_HOME/webapps。 - 确保静态资源如图片、CSS不部署在Tomcat中。
4. 优化与安全
- 缓存静态资源:在Nginx配置中添加缓存头:
location /static/ {root /var/www/;expires 1d;add_header Cache-Control "public, must-revalidate"; } - 开启Gzip压缩:在Nginx中启用:
gzip on; gzip_types text/css application/javascript image/png image/jpeg; - 限制Tomcat访问:通过防火墙限制8080端口的外部访问,确保所有流量通过Nginx。
5. 测试配置
- 访问
http://example.com/static/查看静态资源是否加载成功。 - 访问
http://example.com/验证动态请求是否通过Nginx转发到Tomcat。
未来趋势的优化
- 使用Docker:将Nginx和Tomcat容器化,方便部署与扩展。
- Kubernetes集群化:动态扩展Nginx和Tomcat副本以应对高并发需求。
- CDN加速:结合CDN分发静态资源,进一步优化用户体验。
通过这种配置,充分利用Nginx的高效静态资源处理能力和Tomcat的动态内容支持,实现动态与静态内容的高效分离与协作。
在 Tomcat 服务器中,/var/lib/tomcat/webapps 和 /usr/share/tomcat/webapps 这两个目录都涉及到 Tomcat 的 Web 应用程序部署,但它们的用途和意义有所不同。
1. /var/lib/tomcat/webapps
- 用途:这个目录通常用于存放 Tomcat 实际运行时部署的 Web 应用程序。应用程序会被放置在这里,然后通过 Tomcat 启动和管理。
- 特点:
- 动态内容:这里存放的是需要被 Tomcat 启动的 Web 应用,例如
.war文件,或者已经解压的 Web 应用目录。 - 部署目录:通常是 Tomcat 在启动时加载应用的目录。Tomcat 会扫描此目录来部署应用。
- 可写权限:该目录通常允许 Tomcat 服务进行读写操作,因此可以通过管理工具(如 Tomcat Manager)进行动态部署。
- 动态内容:这里存放的是需要被 Tomcat 启动的 Web 应用,例如
2. /usr/share/tomcat/webapps
- 用途:这个目录通常用于存放 Tomcat 安装包自带的 Web 应用程序,或者是由操作系统或包管理器(如
apt或yum)安装的默认应用程序。 - 特点:
- 默认应用:一般情况下,Tomcat 包管理器安装时会将一些默认的应用程序(如
ROOT,docs,examples, 和manager)放在这个目录下。 - 静态内容:这个目录中的内容通常不会频繁变动。它包含了预装的默认示例和管理应用程序。
- 只读权限:在某些环境中,这个目录可能是只读的,因为它包含了由操作系统或包管理器提供的文件。
- 默认应用:一般情况下,Tomcat 包管理器安装时会将一些默认的应用程序(如
总结:
/var/lib/tomcat/webapps是 Tomcat 实际部署和管理 Web 应用程序的目录,通常是动态的,用户会把自己的应用放到这个目录中。/usr/share/tomcat/webapps是 Tomcat 安装时提供的默认目录,通常包含了系统级别的默认应用和示例文件。
如果你部署一个新的 Web 应用,通常会选择将其放入 /var/lib/tomcat/webapps 目录下。
创建一个简单的动态Web博客网站需要使用HTML、CSS和JavaScript来设计前端页面,以及使用服务器端语言如Python、PHP或Node.js来处理动态内容和数据库交互。下面是一个简单的示例,使用Python的Flask框架和SQLite数据库来创建一个基本的博客网站。
首先,您需要安装Flask和Flask-SQLAlchemy:
pip install Flask Flask-SQLAlchemy
然后,您可以创建一个名为 blog 的目录,并在其中创建以下文件:
app.py- 这是主应用程序文件。templates/- 存储HTML模板的目录。index.html- 主页模板。create.html- 创建新博客的模板。post.html- 单个博客文章的模板。
static/- 存储CSS和JavaScript文件的目录。style.css- CSS样式表。
接下来,您可以为这些文件编写代码:
app.py:
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app)
class Post(db.Model):id = db.Column(db.Integer, primary_key=True)title = db.Column(db.String(100), nullable=False)content = db.Column(db.Text, nullable=False)date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)def __repr__(self):return f"Post('{self.title}', '{self.date_posted}')"
@app.route("/")
@app.route("/home")
def home():posts = Post.query.order_by(Post.date_posted.desc()).all()return render_template('index.html', posts=posts)
@app.route("/create", methods=['GET', 'POST'])
def create():if request.method == 'POST':title = request.form['title']content = request.form['content']new_post = Post(title=title, content=content)db.session.add(new_post)db.session.commit()return redirect(url_for('home'))return render_template('create.html')
@app.route("/post/<int:post_id>")
def post(post_id):post = Post.query.get_or_404(post_id)return render_template('post.html', post=post)
if __name__ == '__main__':db.create_all()app.run(debug=True)
templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Home</title><link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body><h1>Home</h1><a href="{{ url_for('create') }}">Create New Post</a><div class="posts">{% for post in posts %}<div class="post"><h2>{{ post.title }}</h2><p>{{ post.content }}</p><small>{{ post.date_posted.strftime('%Y-%m-%d %H:%M:%S') }}</small><a href="{{ url_for('post', post_id=post.id) }}">Read More</a></div>{% endfor %}</div>
</body>
</html>
templates/create.html:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Create New Post</title><link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body><h1>Create New Post</h1><form method="POST"><label for="title">Title:</label><input type="text" id="title" name="title" required><label for="content">Content:</label><textarea id="content" name="content" required></textarea><button type="submit">Post</button></form>
</body>
</html>
templates/post.html:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>{{ post.title }}</title><link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body><h1>{{ post.title }}</h1><p>{{ post.content }}</p><small>{{ post.date_posted.strftime('%Y-%m-%d %H:%M:%S') }}</small><a href="{{ url_for('home') }}">Back</a>
</body>
</html>
static/style.css:
body {font-family: Arial, sans-serif;
}
.post {margin-bottom: 20px;
}
.post h2 {color: #333;
}
.post p {color: #666;
}
.post small {color: #999;
}
运行 app.py 后,您将能够访问基本的博客网站。您可以在主页上看到所有博客文章,点击 “Create New Post” 来创建新的博客文章,点击文章标题来阅读完整内容。
2. 使用查找命令
如果不确定安装路径,可以通过以下命令查找:
- Linux/Unix:
find / -name "server.xml" 2>/dev/null
3. 使用环境变量
如果 Tomcat 已配置系统环境变量 $CATALINA_HOME,可以直接使用:
echo $CATALINA_HOME
然后进入目录:
cd $CATALINA_HOME/conf
4. 检查安装管理工具
如果是通过包管理工具安装(如 apt、yum),可以查看安装位置:
- Debian/Ubuntu:
dpkg -L tomcat9 | grep "server.xml" - CentOS/RHEL:
rpm -ql tomcat | grep "server.xml"
示例:
假设 Tomcat 安装在 /usr/local/tomcat 下,可以通过以下命令打开配置文件:
nano /usr/local/tomcat/conf/server.xml
注意事项:
server.xml是 Tomcat 的主配置文件,用于定义连接器(Connector)、主机(Host)等。- 修改前请备份原始文件,以便在出错时还原配置。
- 如果找不到文件,确认 Tomcat 是否正确安装或环境变量是否配置正确。
希望这些方法可以帮助您快速定位 server.xml 文件!
相关文章:
tomcat和nginx
Tomcat 和 Nginx 都可以部署 Web 应用,但它们的核心功能和适用场景不同,因此在 2024 年生产环境及未来,是否使用 Tomcat 取决于需求和技术架构的特点。 1. Tomcat 的特点与适用场景 Tomcat 是 Java Servlet 容器,主要用来运行基于…...
服务器带宽与数据安全的重要性与作用
服务器带宽指的是服务器与外部网络通信的能力,即服务器发送和接收数据的速率。带宽越大,服务器在同一时间内能够处理的数据量就越多,数据传输的速度和稳定性也就越高。在数字化时代,企业对于数据的依赖程度日益加深,无…...
JSON数据处理
1. JSON注解 Data NoArgsConstructor AllArgsConstructor JsonIgnoreProperties(ignoreUnknowntrue) JSON注解: JsonIgnoreProperties(ignoreUnknowntrue) Hutool 日期格式化: DatePattern DateTimeFormat(pattern "yyyy-MM-dd HH:mm:ss")…...
FSWIND脉动风-风载时程生成器软件原理
大量风的实测资料表明,在风的时程曲线中,瞬时风速包含两个部分:一部分是自振周期一般在 10 分钟以上的平均风,另一部分是周期一般只有几秒左右的脉动风。平均风由于其周期一般比结构的自振周期大,因而考虑其作用性质相…...
搭建高可用负载均衡系统:Nginx 与云服务的最佳实践
搭建高可用负载均衡系统:Nginx 与云服务的最佳实践 引言 在项目开发过程中,我们通常在开发和测试阶段采用单机架构进行开发和测试。这是因为在这个阶段,系统的主要目的是功能实现和验证,单机架构足以满足开发人员的日常需求&…...
对比git命令与TortoiseGit工具,理解git解决冲突的过程
1 引言 此前用TortoiseSvn习惯了,所以,转到git时也同时选择了TortoiseGit工具。 同时,对比了可视化工具和git命令的操作,来深入理解git解决冲突的方式。 2 使用远程仓库替代本地仓库的内容 2.1 TortoiseGit做法 using “MERGE_…...
guava缓存的get方法的回调函数讲解一下
CacheBuilder.newBuilder()//设置缓存初始大小,应该合理设置,后续会扩容.initialCapacity(10)//最大值.maximumSize(100)//并发数设置.concurrencyLevel(5)//缓存过期时间,写入后10分钟过期.expireAfterWrite(600,TimeUnit.SECONDS)//统计缓存…...
React基础知识四 Hooks
什么是hooks? (coderwhy) hooks是react 16.8(2019年)出的新特性。 react有两种形式来创建组件——类式和函数式。在hooks之前类式组件就是react最主流的编程方式。 这个时候,函数式组件是非常鸡肋的,几乎没什么用。因…...
线性代数中的谱分解
一、谱分解的基本原理 谱分解(Spectral Decomposition)是线性代数中的一个重要概念,特别是在研究矩阵的特征值和特征向量时。它指的是将一个矩阵分解为其特征值和特征向量的组合,从而简化矩阵的运算和分析。谱分解通常适用于对称…...
Redis 数据结结构(一)—字符串、哈希表、列表
Redis(版本7.0)的数据结构主要包括字符串(String)、哈希表(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)、超日志(…...
【Python】用Python和Paramiko实现远程服务器自动化管理
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在现代IT环境中,远程服务器管理已成为运维工作的常态。随着自动化运维的需求不断增加,如何高效地管理远程服务器,提升操作的灵活性和效率…...
PDF处理的创新工具:福昕低代码平台尝鲜
在当今数字化时代,PDF文件的处理和管理变得越来越重要。福昕低代码平台是新发布的一款创新的工具,旨在简化PDF处理和管理的流程。通过这个平台,用户可以通过简单的拖拽界面上的按钮,轻松完成对Cloud API的调用工作流,而…...
openstack创建浮动IP全过程
1、创建外部网络,即是provider网络,有关provider网络的详细解释请参见我之前的文章openstack中的self-service和provider网络_openstack provider网络不能创建vlan吗-CSDN博客 network create --share --external --provider-physical-network physnet1…...
nginx漏洞修复
漏洞名称:web服务器http信息头公开 解决,在以下各个监听端口加上一行,然后重启****nginx server_tokens off; 漏洞名称:默认的nginx http服务器设置 解决:请求头加上以下参数 add_header Content-Security-Policy “…...
Jackson - 序列化时更改字段名称
在这个简短的教程中,我将向您展示如何在序列化时更改字段名称以映射到另一个JSON属性。 Jackson库提供了JsonProperty注解,用于改变序列化JSON中的属性名称。 依赖项 首先,在pom.xml文件中添加以下依赖项: <dependency>…...
策略模式实战 - 猜拳游戏
**可以整体的替换一套算法,这就是策略模式。**这样对于同一个问题,可以有多种解决方案——算法实现的时候,可以通过策略模式来非常方便的进行算法的整体替换,而各种算法是独立封装好的,不用修改其内部逻辑。 具体的实…...
AWS ECS Task 添加 Prometheus 监控采集配置详细指南
以下是一篇完整的博文,介绍如何在 AWS ECS 环境中实现 JVM 监控。 AWS ECS 环境下的 JVM 监控实践 概述 在 AWS ECS (Elastic Container Service) 环境中监控 Java 应用性能是一项重要任务。本文将详细介绍如何使用 AWS Distro for OpenTelemetry (ADOT) 结合 Spring Boot …...
5. 一分钟读懂“工厂方法模式”
5.1 模式介绍 你可能会发现,简单工厂模式没在经典设计模式里出现,别急,它其实只是个常用的编程技巧,而不是标准的设计模式。简单工厂模式有三个要素:1个产品接口、n个产品类、1个工厂类,工厂类通过if/else来…...
基于 AutoFlow 快速搭建基于 TiDB 向量搜索的本地知识库问答机器人
导读 本文将详细介绍如何通过 PingCAP 开源项目 AutoFlow 实现快速搭建基于 TiDB 的本地知识库问答机器人。如果提前准备好 Docker、TiDB 环境,整个搭建过程估计在 10 分钟左右即可完成,无须开发任何代码。 文中使用一篇 TiDB 文档作为本地数据源作为示…...
C语言学习:速通指针(2)
这里要学习的有以下内容 1. const修饰指针 2. 野指针 3. assert断⾔ 4. 指针的使⽤和传址调⽤ 那么从这里开始 1. const 修饰指针 const修饰变量 首先我们知道变量是可以修改的,如果把变量的地址交给⼀个指针变量,通过指针变量的也可以修改这个变…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
