1、简介 本文将带你了解在 Spring Boot 中如何配置 SSL 认证以连接到 Apache Kafka Broker。
安全套接字层(SSL)实际上已被弃用,自 2015 年起被传输层安全(TLS)所取代。不过,由于历史原因,Kafka(和 Java)仍然使用 “SSL”。
2、SSL 概览 默认情况下,Apache Kafka 以明文形式发送所有数据,且不进行任何身份认证。
首先,可以为 Broker 和客户端之间的加密配置 SSL。默认情况下,这需要使用公钥加密进行单向身份认证,由客户端验证服务器证书。
此外,服务器还可以使用单独的机制(如 SSL 或 SASL)对客户端进行身份认证,从而实现双向身份认证或相互 TLS(mTLS)。基本上,双向 SSL 认证确保客户端和服务器都使用 SSL 证书来认证对方的身份,并在双向上相互信任。
在本文中,Broker 使用 SSL 对客户端进行身份验证,使用 Keystore 和 Truststore 保存证书和密钥。
每个 Broker 都需要自己的 Keystore,其中包含私钥和公共证书。客户端使用其 Truststore 来验证该证书并信任服务器。同样,每个客户端也需要自己的 Keystore,其中包含私钥和公共证书。服务器使用其 Truststore 来验证和信任客户端的证书,并建立安全连接。
Truststore 可以包含一个可以签署证书的证书颁发机构(CA)。在这种情况下,Broker 或客户端会信任由 Truststore 中的 CA 签发的任何证书。这就简化了证书验证,因为添加新客户端或 Broker 无需更改 Truststore。
3、依赖和设置 创建一个简单的 Spring Boot 示例应用,在 pom.xml 中添加 spring-kafka 依赖:
<dependency> <groupId>org.
1、概览 本文将会带你了解如何使用 spring-websockets 创建一个 Websocket 应用,并且使用 Postman 来进行测试。
2、Java WebSocket WebSocket 是 Web 浏览器和服务器之间的一种双向、全双工、持久连接。一旦建立了 WebSocket 连接,该连接就会一直打开,直到客户端或服务器决定关闭该连接。
WebSocket 协议是实现应用处理实时消息的一种方式之一。最常见的替代方案是长轮询(long polling)和服务器推送事件(server-sent events)。每种解决方案都有其优点和缺点。
在 Spring 中使用 WebSockets 的一种方式是使用 STOMP 子协议。不过,本文使用原始 WebSockets,因为到目前为止,Postman 还不支持 STOMP。
3、Postman Postman 是一个用于构建和使用 API 的 API 平台。使用 Postman 时,无需为了测试而编写 HTTP 客户端基础设施代码。相反,可以创建称为集合(collections)的测试套件,并让 Postman 与 API 进行交互。
4、WebSocket 应用 创建一个简单的应用,工作流程如下:
服务器向客户端发送一次性消息 服务器定期向客户端发送消息 从客户端接收消息时,通过日志记录消息并将其发送回客户端 客户端向服务器发送非周期性消息 客户端接收来自服务器的消息并将其输出到日志 程图如下:
5、Spring WebSocket 服务器由两部分组成。Spring WebSocket Event Handler(事件处理器)和 Spring WebSocket 配置。
5.1、Spring WebSocket 配置 在配置类上添加 @EnableWebSocket 注解,可以在 Spring 服务器中启用 WebSocket 支持。
1、概览 文件上传是现在应用中很常见的需求,从 Spring 5 开始可以通过响应式上传文件。有了响应式编程的加持,能够使用较少的线程和背压(Backpressure)机制,以非阻塞的方式进行上传。
本文将带你了解使用 WebClient(一种非阻塞、响应式的 HTTP 客户端)通过 BodyInserters 上传文件的两种不同方法。WebClient 是名为 Project Reactor 的响应式编程库的一部分。
2、使用 WebClient 上传文件 首先,在项目中添加 spring-boot-starter-webflux 依赖:
<dependency> <groupId>org.springframework.boot</groupId>. <artifactId>spring-boot-starter-webflux</artifactId> </dependency> 2.1、上传单个文件 首先,声明上传地址的 URL:
URI url = UriComponentsBuilder.fromHttpUrl(EXTERNAL_UPLOAD_URL).build().toUri(); 比方说,在本例中要上传 PDF。因此使用 MediaType.APPLICATION_PDF 作为 ContentType。上传端点会返回一个 HttpStatus。由于只希望得到一个结果,所以将其封装在一个 Mono 中:
Mono<HttpStatus> httpStatusMono = webClient.post() .uri(url) .contentType(MediaType.APPLICATION_PDF) .body(BodyInserters.fromResource(resource)) .exchangeToMono(response -> { if (response.statusCode().equals(HttpStatus.OK)) { return response.bodyToMono(HttpStatus.class).thenReturn(response.statusCode()); } else { throw new ServiceException("Error uploading file"); } }); 调用这个方法的方法也可以返回一个 Mono,可以一直进行下去,直到真正需要访问结果为止。就绪后,可以在 Mono 对象上调用 block() 方法。
1、概览 本文将带你了解如何在 Spring Boot 中根据不同的 Profile 激活不同的 Log4j2 配置。
2、使用不同的配置文件 例如,假设我们有两个文件:log4j2.xml 和 log4j2-dev.xml,一个用于默认配置文件,另一个用于 dev Profile。
创建 application.properties 文件,指定日志配置文件:
logging.config=/path/to/log4j2.xml 接着,为 dev Profile 创建一个名为 application-dev.properties 的新 properties 文件,并添加类似的日志配置:
logging.config=/path/to/log4j2-dev.xml 如果还有其他的 Profile,例如 prod,只需为其创建一个名称相似的 properties 文件 - application-prod.properties。特定 Profile 的属性总是优先于默认属性。
3、编程式配置 可以通过更改 Spring Boot Application 类,以编程方式选择使用哪个 Log4j2 配置文件:
@SpringBootApplication public class Application implements CommandLineRunner { @Autowired private Environment env; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void run(String... param) { if (Arrays.
1、简介 所有 Java Web 框架都建立在 Servlet Api 的基础之上。在基于 Spring 开发的 Java Web 应用中,有三个文件起着至关重要的作用。通常,按以下顺序将它们串联起来:web.xml -> applicationContext.xml -> spring-servlet.xml。
本文将带你了解 applicationContext.xml 和 spring-servlet.xml 之间的区别。
2、applicationContext.xml 反转控制(IoC)是 Spring 的核心。在使用 IoC 的框架中,通常由容器负责实例化、创建和删除对象。在 Spring 中,applicationContext 就扮演着 IoC 容器的角色。
在开发标准 J2EE 应用时,会在 web.xml 文件中声明 ContextLoaderListener。此外,还定义了一个 contextConfigLocation 来指定 XML 配置文件。
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext*.xml</param-value> </context-param> 应用启动时,Spring 会加载该配置文件,并使用它创建 WebApplicationContext 对象。如果没有 contextConfigLocation,默认情况下,系统将查找 /WEB-INF/applicationContext.xml 来加载。
简而言之,applicationContext 是 Spring 的核心接口。它为应用提供配置信息。
在该文件中,提供了与应用相关的配置。通常,这些配置包括基本数据源、属性占位符文件(Property Place Holder)和用于项目本地化的消息源(Message Source),以及其他增强功能。
示例如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xmlns:p="http://www.
简介 本文将带你了解如何使用 Spring 和 Hibernate 实现表分区。
表分区的目标是将一个大型表分割为多个较小的分区表,以便关联的表和索引记录可以放入内存缓冲池,从而实现更高效的查找或扫描操作。
使用 PostgreSQL 进行表分区 PostgreSQL 为 表分区 提供了三种策略:
列表分区(List Partitioning) 范围分区(Range Partitioning) Hash 分区(Hash Partitioning) 本例使用列表分区,按大洲来划分数据表。
例如,users 分区如下:
CREATE TABLE users ( id bigint NOT NULL, first_name varchar(255), last_name varchar(255), registered_on timestamp(6), partition_key varchar(255), PRIMARY KEY (id, partition_key) ) PARTITION BY LIST (partition_key) CREATE TABLE users_asia PARTITION OF users FOR VALUES IN ('Asia') CREATE TABLE users_africa PARTITION OF users FOR VALUES IN ('Africa') CREATE TABLE users_north_america PARTITION OF users FOR VALUES IN ('North America') CREATE TABLE users_south_america PARTITION OF users FOR VALUES IN ('South America') CREATE TABLE users_europe PARTITION OF users FOR VALUES IN ('Europe') CREATE TABLE users_australia PARTITION OF users FOR VALUES IN ('Australia') posts 表分区如下:
概览 有时我们需要在应用中监控本地磁盘上的某个目录,在目录中的文件发生变化时(创建、编辑、删除)进行相应的处理。
在 Java 中有好几种方式可以实现监控目录。
Java WatchService API:在 Java 7 中引入,属于低级 API。 Apache commons io:提供了一个用于监控文件系统事件的组件。 Spring Integration 的文件支持:这是 Spring integration 项目的一部分,该项目支持多种企业集成模式。 Spring Boot Developer Tools 中的 Filewatch: 它可以观察本地文件系统的变化。 本文将带你了解如何通过 Spring Boot Developer Tools 中的 Filewatch 来监控系统目录。它本身就是基于 Spring 构建,所以可以和 Spring Boot 无缝集成。
用例 我们希望通过将 csv 文件复制到特定位置(目录)来在应用中创建新的客户。一旦文件完全传输完成,就对其进行读取。然后,对 csv 文件进行验证、处理并移动到目标目录。以下是csv文件的示例:
name, email, dob, info, vip James Hart,james.hart@gmail.com,12/05/2002,Information for James,No Will Avery,will.avery@gmail.com,23/10/1991,Information for Will,Yes Anne Williams,anne.williams@gmail.com,12/05/1975,Information for Anne,No Julia Norton,julia.norton@gmail.com,23/10/1984,Information for Julia,Yes csv 文件始终包含标题行和按特定顺序排列的 5 列。
上一教程 介绍了如何使用 jOOQ 检索一对多关系的记录。本文将带你了解如何使用 jOOQ 检索多对多关系的记录。
你可以通过 Github 获取到完整的源码。
在示例数据库中,有 bookmarks(书签)表和 tags(标签)表。每个书签可以关联多个标签,反之亦然,因此 bookmarks 表和 tags 表之间存在多对多的关系。
让我们看看如何获取书签列表以及与之关联的标签
首先,创建 BookmarkWithTags record。
package com.sivalabs.bookmarks.models; import java.util.List; public record BookmarkWithTags(Long id, String title, String url, List<TagInfo> tags) { public record TagInfo (Long id, String name){} } 使用 MULTISET Value 构造器获取多对多关系 使用 jOOQ 的 MULTISET Value Constructor 来获取书签列表和标签。
实现获取书签和标签,如下:
package com.sivalabs.bookmarks.repositories; import com.sivalabs.bookmarks.models.BookmarkWithTags; import org.jooq.DSLContext; import org.springframework.stereotype.Repository; import java.util.List; import static com.sivalabs.bookmarks.jooq.Tables.BOOKMARK_TAG; import static com.
上一教程 中介绍了如何使用 jOOQ 检索一对一(*One-to-One)关系的记录。本文将带你了解如何使用 jOOQ 检索一对多(One-to-Many)关系的记录。
你可以在 Github 获取完整的源码。
在示例数据库中,有 users(用户)表和 bookmarks(书签)表。每个用户可以创建多个书签,因此 users 表和 bookmarks 表之间是一对多的关系。
让我们看看如何获取用户详细信息以及用户创建的书签。
首先,创建 UserWithBookmarks Record。
package com.sivalabs.bookmarks.models; import java.util.List; public record UserWithBookmarks(Long id, String name, String email, List<BookmarkInfo> bookmarks) { public record BookmarkInfo (Long id, String title, String url){} } 使用 MULTISET Value 构造器获取一对多关系 使用 jOOQ 的 MULTISET Value 构造函数来获取用户创建的书签列表。有关 MULTISET Value 构造函数的更多详情,请访问:https://www.jooq.org/doc/latest/manual/sql-building/column-expressions/multiset-value-constructor/。
此外,强烈推荐你阅读《jOOQ 3.15 的新 Multiset Operator 将如何改变你对 SQL 的看法》一文。
实现获取用户详细信息以及该用户创建的书签。
@Repository public class UserRepository { .
上一教程 介绍了如何使用 jOOQ 实现基本的 CRUD 操作。本文将带你了解如何使用 jOOQ 检索一对一(One-to-One)关系的记录。
你可以在 Github 上找到完整的源码。
一般来说,在显示记录列表时,只会显示记录的最基本的信息,当点击记录时,才会显示记录的完整信息。
在本示例应用中,用户列表只显示 id、name 和 email 基本信息。当点击详情时,才显示包含用户偏好(Preferences)的完整信息。
更新 findUserById() 方法,以获取用户偏好设置。
首先,创建 UserPreferences record。
public record UserPreferences(Long id, String theme, String language) { } 更新 User 类,使其包含 UserPreferences。
package com.sivalabs.bookmarks.models; public record User ( Long id, String name, String email, String password, UserPreferences preferences ) { public User(Long id, String name, String email, String password) { this(id, name, email, password, null); } public static User create(Long id, String name, String email, String password) { return new User(id, name, email, password, null); } } 在 SQL 中,可以使用 LEFT OUTER JOIN 查询获取关联数据,如下所示: