1、概览 Docker 推动了容器化技术的普及,简化了高度分布式应用的创建、交付和运行流程。我们通常使用 docker container 命令管理独立的 Docker 容器。
Docker 最初聚焦于开发者和开发周期,但现已演进为通过简洁强大的编排器提供编排服务。
本文将带你了解容器化技术及编排器(orchestrator)的必要性,继而分析 Docker 容器与编排服务的区别及其适用场景。
2、容器化与编排技术解析 将应用容器化为自治单元是软件开发周期的关键步骤。然而,随着容器数量增长,部署和管理将面临重大挑战:
少量容器:通过 Docker 手动管理仍可行,故障时可手动重启或更新。 现代架构:应用通常拆分为多个组件,每个组件部署为独立容器。 大规模部署:当数十甚至数百个容器需跨多服务器协同工作时,手动管理将不可行。 此时需引入容器编排引擎。
容器编排工具可自动化容器管理,主要保障以下特性:
资源高效利用。 高可用性。 容错能力。 容器化应用的透明扩展。 在这些工具中,Kubernetes 无疑是应用最广泛且功能最全面的解决方案。
Docker 也提供了内置编排器 Docker Swarm 模式,该模式通过 services(服务)概念实现 Docker 容器的编排。
3、Docker 独立容器 以独立模式运行容器指直接在本地主机启动容器,无需编排器参与。每个容器相互隔离,通过 Docker CLI 或 API 手动管理。
3.1、部署 假设我们需要部署 bael-api(一个小型 REST Web 服务,用于查询最新或即将发布的课程和教程),同时配置存储课程元数据的数据库:
$ docker network create bael-network $ docker volume create bael-db-data $ docker container run -d --name db -v bael-db-data:/var/lib/mysql --network bael-network mysql $ docker container run -d --name bael-api -p 8080:8080 --network bael-network bael-api 此处我们创建自定义 Docker 网络确保容器间通信,并配置数据持久化卷。接着使用 docker container run 启动两个容器:
1、概览 现代应用日益采用自然语言界面简化系统交互,这对数据检索尤为实用 —— 非技术用户可直接用自然语言提问。
Text-to-SQL 聊天机器人便是典型实现,它充当人类语言与数据库间的桥梁。通常借助大语言模型(LLM)将自然语言问题转换为可执行 SQL 查询,随后在数据库中执行并返回结果。
本文将带你了解如何使用 Spring AI 构建 Text-to-SQL 聊天机器人。
2、项目设置 在实现聊天机器人前,需引入必要依赖并正确配置应用。
本文基于 Anthropic 的 Claude 模型构建 Text-To-Sql 聊天机器人。注意:本实现不限定特定 AI 模型,也可选用 Hugging Face 或 Ollama 的本地 LLM 作为替代方案。
2.1、依赖 首先在项目的 pom.xml 文件中添加必要依赖:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-anthropic</artifactId> <version>1.0.0</version> </dependency> Anthropic starter 依赖 是对 Anthropic Message API 的封装,我们将通过它与 Claude 模型交互。
接下来在 application.yaml 文件中配置 Anthropic API Key 和聊天模型:
spring: ai: anthropic: api-key: ${ANTHROPIC_API_KEY} chat: options: model: claude-opus-4-20250514 我们通过 ${} 属性占位符从环境变量加载 API Key。
本文由 Broadcom 的 Spring 开发者倡导者 Josh Long 和 Redis 的应用 AI 工程师 Brian Sam-Bodden 共同撰写,旨在展示如何在 Spring AI 1.0 中使用 Redis。
Spring AI 1.0 是面向 Java 开发的综合性 AI 工程解决方案。受 AI 领域飞速发展的影响,该版本经过了一个重要的开发阶段,现已发布。该版本为 AI 工程师提供了多项核心新功能。Redis 作为 Spring AI 的原生向量数据库,可助力构建高性能 AI 应用。
当前 Java 和 Spring 正处于 AI 应用的黄金时期。大量企业应用基于 Spring Boot 运行,这使其能轻松将 AI 能力集成至现有系统。你可直接将业务逻辑和数据无缝对接 AI 模型,无需复杂改造。
Spring AI 支持多种 AI 模型与技术:
Image model(图像模型):根据文本提示生成图像。 Transcription model(转录模型):将音频转换为文本。 Embedding model(嵌入模型):将任意数据转换为向量(专为语义相似性搜索优化的数据类型)。 Chat model(对话模型):用户最熟悉的类型,可辅助文档修正或诗歌创作(但暂不建议用于讲笑话),虽功能强大但仍存在局限。 在 Spring AI 中,需要解决一些问题:对话模型具有开放性思维,容易偏离主题,需要通过 system prompt(系统提示)来规范其响应结构和形式。
构建大规模企业级应用通常需要模块化设计、关注点分离和高效的依赖管理。多模块 Spring Boot 项目允许将复杂系统拆分为可管理的独立模块 —— 每个模块职责明确,同时能无缝协作。
本文将带你了解使用 Maven 和 Gradle 组织多模块 Spring Boot 项目的最佳实践。
1、为什么选择多模块架构? 多模块架构 具有以下优势:
关注点分离:将领域逻辑、Web 接口、持久层和共享工具拆分到独立模块。 提升构建性能:仅需重新构建受影响的模块。 更优的测试与部署:支持模块独立测试和部署。 清晰的依赖管理:确保单向依赖关系。 2、典型模块结构 常见的多模块结构如下所示:
root-project/ │ ├── api/ # DTO 和接口 ├── core/ # 业务逻辑与领域(Domain)模型 ├── persistence/ # 数据库访问(例如 JPA、Repository) ├── web/ # REST Controller、Spring Boot main 类 └── shared/ # 公共的工具类、枚举和异常 下图展示了模块间的依赖流向可视化表示:
core 模块依赖 api、shared 和 persistence 模块。 web 模块同时依赖 core 和 api 模块。 所有箭头向下指向,表示单向架构。 这种结构提升了复用性和清晰的层级划分:
web 依赖 core 和 api。 core 依赖 persistence 和 shared。 api 与 shared 作为依赖根模块。 3、Maven 设置 根目录的 pom.
1、概览 如今,应用程序极大地受益于神经网络集成,例如知识库、助手或分析引擎。其中一个实际用例是将文本转换为语音。这一过程被称为 文本转语音(Text-to-Speech,TTS),能够以自然逼真、类人的声音自动生成音频内容。
现代 TTS 系统利用深度学习技术处理发音、节奏、语调甚至情感。与早期的基于规则的方法不同,这些模型通过海量数据集训练,可以生成富有表现力的多语言语音,非常适合虚拟助手或包容性教育平台等全球化应用场景。
本文将带你了解如何在 Spring AI 中使用 OpenAI 文本转语音(TTS)。
2、依赖配置 首先,需要添加 spring-ai-starter-model-openai 依赖:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-openai</artifactId> <version>1.1.0</version> </dependency> 接下来,为 OpenAI 模型配置 Spring AI 属性:
# Api Key spring.ai.openai.api-key=${OPENAI_API_KEY} # 模型 spring.ai.openai.audio.speech.options.model=tts-1 # 语音风格 spring.ai.openai.audio.speech.options.voice=alloy # 响应的数据格式 spring.ai.openai.audio.speech.options.response-format=mp3 # 语音速度 spring.ai.openai.audio.speech.options.speed=1.0 要使用 OpenAI API,必须设置 OpenAI API Key。同时还需要指定 文本转语音(TTS) 的模型 名称、语音风格、响应格式以及 音频 速度。
3、构建文本转语音应用 现在,构建文本转语音应用。
首先,创建 TextToSpeechService Service 类:
@Service public class TextToSpeechService { private OpenAiAudioSpeechModel openAiAudioSpeechModel; // 构造函数注入 @Autowired public TextToSpeechService(OpenAiAudioSpeechModel openAiAudioSpeechModel) { this.
API 网关在微服务架构中至关重要,负责路由、负载均衡、安全防护和可观测性。Java 生态中有两大主流方案:
Spring Cloud Gateway(SCG)—— Spring 团队提供的现代化响应式方案。 Netflix Zuul 2 —— Zuul 的升级版,专为异步非阻塞 I/O 设计。 但 2025 年哪种更胜一筹?本文将从性能、功能特性和实际适用性进行对比,助你决策。
1、性能对比 基准测试结果(延迟与吞吐量) 指标 Spring Cloud Gateway Netflix Zuul 2 平均延迟(毫秒) 12 25 最大吞吐量(请求数/秒) 15,000 8,000 CPU 使用率 更低(响应式技术栈) 更高(基于 Servlet) 🔹 为何 Spring Cloud Gateway 胜出?
基于 Project Reactor(非阻塞式)。 无 Servlet 容器开销(与 Zuul 2 不同)。 专为 云原生负载 优化。 🔹 何时 Zuul 2 更合适?
若已深度集成 Netflix OSS 生态。 需更精细的过滤器(Zuul 2 内置过滤器更丰富)。 2、功能特性对比 功能特性 Spring Cloud Gateway Netflix Zuul 2 协议支持 HTTP/2、WebSockets HTTP/1.
1、概览 本文将带你了解如何通过标准 Spring 应用及 Spring Boot 应用发送邮件。前者基于 JavaMail 库实现,后者则使用 spring-boot-starter-mail 依赖。
2、Maven 依赖 首先需在 pom.xml 中添加依赖。
2.1、Spring 以下是标准 Spring 框架所需的依赖配置:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>6.1.5</version> </dependency> 最新版本可在 此处 获取。
2.2、Spring Boot 而 Spring Boot 则需要添加:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> <version>3.1.5</version> </dependency> 最新版本可在 Maven 中央仓库 获取。
3、邮件服务器配置属性 Spring 框架中邮件支持的接口与类按以下结构组织:
MailSender 接口:顶层接口,提供发送简单邮件的基础功能。 JavaMailSender 接口:MailSender 的子接口,支持 MIME 消息,通常与。MimeMessageHelper 类配合创建 MimeMessage。建议通过 MimeMessagePreparator 机制使用该接口。 JavaMailSenderImpl 类:实现 JavaMailSender 接口,支持 MimeMessage 和 SimpleMailMessage。 SimpleMailMessage 类:用于创建包含发件人、收件人、抄送、主题和文本内容的简单邮件。 MimeMessagePreparator 接口:为 MIME 消息提供准备机制的回调接口。 MimeMessageHelper 类:创建 MIME 消息的辅助类,支持图片、典型邮件附件及 HTML 格式的文本内容。 以下章节将演示如何使用这些接口与类。
1、简介 当使用 Java 的 Scanner 类读取 System.in(标准输入)输入时,部分 IDE 会提示可能存在资源泄漏。
例如,若未显式关闭 Scanner,可能收到警告:“Resource leak: ‘scanner’ is never closed”。但关闭关联 System.in 的 Scanner 需谨慎处理,以避免意外问题。
本文将带你了解关闭 Scanner 的重要性及在 Java 中的正确操作方式。
2、理解 IDE 提示的异常 在 Java 中,使用文件、网络连接(Socket)和输入流等资源后应关闭资源以释放系统内存。Scanner 类从文件或 System.in 等源读取原始值和字符串输入,由于实现了 Closeable 接口,因此它持有的资源需要在不使用时及时释放。
部分 IDE(如 Eclipse 和 Visual Studio Code)若检测到未正确关闭 Scanner 对象,会显示如下资源泄漏警告:
3、通过 close() 方法关闭 Scanner 在 Java 中,可通过 close() 方法关闭 Scanner 以释放系统资源,这在读取文件或 System.in 时尤为重要。
建议在 finally 代码块中关闭 Scanner,确保即使发生异常也能正确释放资源,避免泄漏:
@Test void givenUserName_whenGetGreetingMessage_thenReturnsWelcomeMessage() { String input = "Anees\n"; ByteArrayInputStream inputStream = new ByteArrayInputStream(input.
1、简介 本文将带你了解使用 Spring Boot 实现邮件功能时遇到 “Could not autowire org.springframework.mail.javamail.JavaMailSender” 异常的原因以及解决办法。
2、理解异常 首先解释该错误的含义。JavaMailSender 是 Spring 提供的接口,用于抽象邮件发送过程。它继承自 MailSender 接口(提供简单文本邮件的基础功能),特别支持 MIME 消息、附件和 HTML 内容等高级特性。
Spring 的依赖注入机制会自动装配所需 Bean。当遇到 @Autowired 注解或更推荐的构造器注入时,它会从应用上下文(Application Context)中查找匹配的 Bean:
@Service public class EmailService { private final JavaMailSender javaMailSender; public EmailService(final JavaMailSender javaMailSender) { this.javaMailSender = javaMailSender; } } 当我们注入 Spring 无法找到的 JavaMailSender Bean 并运行应用时,会抛出以下错误:
Field javaMailSender in com.baeldung.email.EmailService required a bean of type 'org.springframework.mail.javamail.JavaMailSender' that could not be found. 或者:
Parameter 0 of constructor in com.
1、简介 Gson 是 Google 开发的开源 Java 库,用于简化对象与 JSON 之间的转换。它提供高效的序列化与反序列化技术,并支持复杂对象处理。
像 Gson 这样的库支持将 JSON 直接映射到 POJO。但某些场景下需要排除特定属性的序列化与反序列化。
本文将带你了解 Gson 库中两个关键注解:@Expose 和 @SerializedName。尽管二者均涉及属性的序列化控制,但适用场景不同。
2、Gson 设置 要使用 Gson,需在 pom.xml 中添加其 Maven 依赖:
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.10.1</version> </dependency> 3、@Expose 注解 Gson 默认会序列化和反序列化 POJO 类的所有字段,除非另有指定。@Expose 注解可覆盖此行为,控制特定字段是否参与序列化或反序列化。
若字段的 serialize 和 deserialize 属性设为 true,Gson 仅会处理带有 @Expose 注解的字段。这两个属性的默认值均为 true。
以下示例展示了一个包含 id、name、age 和 email 的 User 类。由于 email 是敏感信息,我们将其从输出的 JSON 中排除:
public class User { @Expose String name; @Expose int age; @Expose(serialize = true, deserialize = false) long id; @Expose(serialize = false, deserialize = false) private String email; // 构造函数、Getter、Setter 省略 } 在上述代码片段中,我们用 @Expose 标注了 name 和 age 字段。未显式设置 serialize 和 deserialize 属性意味着它们默认为 true。