上一教程 中介绍了如何使用 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 查询获取关联数据,如下所示:
在 上一教程 中,介绍了如何使用 testcontainers-jooq-codegen-maven-plugin 生成 jOOQ 代码,以及如何使用 jOOQ DSL 执行 SQL 查询。
本文将带你了解如何使用 jOOQ 对 USERS 表执行基本的 CRUD(创建、读取、更新、删除)操作。
你可以在 Github 上获取到完整的源码。
findAllUsers() 首先,从 USERS 表中获取所有用户。假设只检索 USERS 表中的 id、name、email 和 password 列。
创建 User record,如下:
package com.sivalabs.bookmarks.models; public record User(Long id, String name, String email, String password) { } 在 UserRepository 类中实现 findAllUsers() 方法,如下:
package com.sivalabs.bookmarks.repositories; import com.sivalabs.bookmarks.models.User; import org.jooq.DSLContext; import org.jooq.impl.SQLDataType; import org.springframework.stereotype.Repository; import java.util.List; import static com.sivalabs.bookmarks.jooq.tables.Users.USERS; import static org.
jOOQ 是一个 Java 持久库,提供用于编写类型安全 SQL 查询的 SQL DSL。它支持大多数流行的数据库,如 MySQL、PostgreSQL、Oracle、SQL Server 等。
本文将带你了解如何在 Spring Boot 中使用 jOOQ 实现持久层。JOOQ 也可以在 Kotlin、Scala 等其他基于 JVM 的语言中使用。
本系列教程中,将带你学习如何在 Spring Boot 中使用 JOOQ 实现:
基本的 CRUD 操作 一对一关系检索 一对多关系检索 多对多关系检索 你可以在 Github 获取完整的源码。
前提条件 安装 JDK 17 或更高版本 安装任何容器运行时,如 Docker Desktop、OrbStack 等。 注意:jOOQ 不需要 Docker。只是使用 Testcontainers 进行 jOOQ 代码生成和测试需要一个容器运行时。
示例数据库 本教程使用下列示例数据库。
创建 Spring Boot 应用 使用 Spring Initializr 创建一个 Spring Boot 项目。选择 JOOQ Access Layer、Flyway Migration、PostgreSQL Driver 和 Testcontainers。
Spring Boot 微服务需要对用户进行身份认证,其中一种方式是使用 JSON Web Token (JWT)。JWT 是一种开放标准(RFC 7519),它定义了一种紧凑的机制,用于在各方之间安全地传输信息。
本文将会带你了解如何在 Spring Boot 微服务项目中使用 JWT 进行身份认证。
JWT Token 概览 JWT 的体积相对较小。因此,它可以通过 URL 发送:
POST 参数 HTTP 请求头 通过 HTTP Header 发送 Token 是最常见的方式。
JWT Token 包含一个实体(可以是用户或服务)的所有必要信息。
下图显示了使用 JWT 进行身份认证的典型用例。
示例应用 创建两个服务:
AuthenticatorService:负责验证用户名和密码。验证成功后,该服务会生成并返回一个 JWT Token。 BlogService:受保护的服务。该服务包含一个 Filter,用于验证客户端发送的 JWT Token。验证成功后,该服务会返回业务数据。 下图显示了客户端与上述服务之间的交互。
AuthenticatorService Maven 依赖 添加 jjwt 依赖,用于生成 JWT Token。
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <!-- 其他依赖忽略 --> 实体 AuthenticatorService 包含一个 User 实体,用于表示用户凭证。如下:
package com.
Fastjson2 是 Fastjson 的一个重大升级版本。
以下摘自官方的介绍:
FASTJSON 2是一个性能极致并且简单易用的Java JSON库。
FASTJSON 2是FASTJSON项目的重要升级,和FASTJSON 1相比,性能有非常大的提升,解决了autoType功能因为兼容和白名单的安全性问题。 性能极致,性能远超过其他流行 JSON 库,包括 jackson/gson/org.json,性能数据: https://github.com/alibaba/fastjson2/wiki/fastjson_benchmark 支持JDK新特性,包括JDK 11/JDK 17,针对compact string优化,支持Record,支持GraalVM Native-Image 完善的JSONPath支持,支持 SQL:2016 的 JSONPath 语法 支持Android 8+,客户端和服务器一套 API 支持Kotlin https://alibaba.github.io/fastjson2/kotlin_cn 支持JSON Schema https://alibaba.github.io/fastjson2/json_schema_cn 新增加支持二进制格式 JSONB https://alibaba.github.io/fastjson2/jsonb_format_cn 总得来说,提高了性能(拳打 Gson,脚踢 Jackson)和饱解决了饱受诟病的安全问题(因为 Fastjson 屡次爆出反序列化安全问题,在国内被戏称为 Bugjson)。
Fastjson2 确实一个款性能很高的 Json 库,API 也设计得比较简单、易用。本文将带你了解如何在 Spring 中使用 Fastjson2。
1、依赖 Fastjson2 采用 多模块 的结构设计,对 Spring 等框架的支持现独立在 extension 包中。
2.0.23 版本之后为了兼容 Spring 5.x / 6.x,将不同的版本独立出来了。
使用 Maven:
<!-- Sring 5 --> <dependency> <groupId>com.
1、简介 Spring 5.0 至 5.0.4、4.3 至 4.3.14 以及其他旧版本在 Windows 系统上存在目录或路径遍历安全漏洞。
静态资源配置错误会导致恶意用户访问服务器的文件系统。例如,在 Windows 上使用 file: 协议配置静态资源,可能导致用户非法访问文件系统。
Spring 承认存在该 漏洞,并在后续版本中对其进行了修复。
此修复可防止应用遭受路径遍历攻击。不过,在修复后,一些之前的 URL 现在会抛出 org.springframework.security.web.firewall.RequestRejectedException 异常。
本文先带你了解什么是 “路径遍历攻击”,在这个知识背景下再带你了解 org.springframework.security.web.firewall.RequestRejectedException 和 StrictHttpFirewall 的相关知识。
2、路径遍历漏洞 路径遍历或目录遍历漏洞可非法访问 Web 文档根目录以外的内容。例如,篡改 URL 可对文档根目录以外的文件进行未经授权的访问。
虽然大多数最新和流行的 Web 服务器都能抵消大部分攻击,但攻击者仍可使用特殊字符(如 ./、../)的 URL 编码来规避 Web 服务器的安全设置并获取非法访问权限。
OWASP 介绍了路径遍历漏洞和解决方法。
3、Spring 的漏洞 先尝试复现这个漏洞,然后再介绍如何进行修复。
首先,克隆 Spring Framework MVC 示例。然后,修改 pom.xml,用一个易受攻击的版本替换现有的 Spring Framework 版本。
克隆仓库:
git clone git@github.com:spring-projects/spring-mvc-showcase.git 在克隆目录中,编辑 pom.xml,修改 Spring Framework 的版本为 5.0.0.RELEASE:
<org.springframework-version>5.0.0.RELEASE</org.springframework-version> 接下来,编辑 Web 配置类 WebMvcConfig,修改 addResourceHandlers 方法,使用 file: 将资源映射到本地文件目录:
1、概览 本文将带你了解 Spring Boot 2.5 中的一个新特性:为系统环境变量指定前缀。通过该特性,就可以在同一环境中运行多个不同的 Spring Boot 应用,只要所有属性都使用带前缀的版本。
2、环境变量前缀 有时,我们可能需要在同一个环境中运行多个 Spring Boot 应用,并且经常会面临环境变量名称分配的问题。现在,我们可以在应用级别设置一个 “前缀”,不同应用加载不同前缀的环境变量即可。
以一个简单的 Spring Boot 应用为例,通过设置前缀来修改应用属性,例如 tomcat 服务器端口。
关于 Spring Boot 中属性属性的优先级,你可以参阅 中文文档。
2.1、Spring Boot 应用示例 创建一个 Spring Boot 应用。
首先,为应用设置一个前缀。为了简单起见,称之为 prefix:
@SpringBootApplication public class PrefixApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(PrefixApplication.class); // 设置环境变量前缀 application.setEnvironmentPrefix("prefix"); application.run(args); } } 不能使用已经包含下划线字符(_)的单词作为前缀。否则,抛出异常。
再创建一个 API 端点,返回应用正在监听的端口:
@Controller public class PrefixController { @Autowired private Environment environment; @GetMapping("/prefix") public String getServerPortInfo(final Model model) { model.
1、简介 Spring Boot 为大多数常用的依赖、第三方库都定义好了最兼容的版本号(如 JPA、MySQL 驱动、Redis 客户端)。得益于此,我们可以快速地创建一个新应用。
但,有时出于特殊原因,我们需要修改这些预定义的依赖版本号。
2、Spring Boot 依赖清单(BOM) Spring Boot 使用 Bill of Materials (BOM) 来定义依赖和版本。
大多数 Spring Boot 项目都继承自 spring-boot-starter-parent,而 spring-boot-starter-parent 本身又继承自 spring-boot-dependencies 。后者就是 Spring Boot BOM,它只是一个 Maven POM 文件,其中有一个很大的 ependencyManagement 节点:
<dependencyManagement> <dependencies> <dependency> ... </dependency> <dependency> ... </dependency> </dependencies> </dependencyManagement> 通过使用 Maven 的 dependencyManagement,BOM 可以指定依赖的默认版本(如果应用使用了这个依赖)。
Spring Boot BOM 中的一个依赖如下:
<dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-amqp</artifactId> <version>${activemq.version}</version> </dependency> 这意味着,在项目中依赖了 ActiveMQ,就会使用这个默认的版本。
另外,注意。版本是使用属性占位符指定的。这是 Spring Boot BOM 中的常见做法,它在自己的 properties 部分中提供了该属性和其他属性的值。
3、覆盖 Spring Boot 管理的依赖版本 既然已经了解了 Spring Boot 如何管理依赖版本,那就来看看如何覆盖它们。
Spring Boot 3.2.0 为嵌入式 Web 服务器添加了热加载 SSL 证书和密钥的功能。这意味着无需重启应用就能替换 SSL 配置。Tomcat 和 Netty 嵌入式 Web 服务器支持热重载。
首先,使用 OpenSSL 创建 SSL 私钥和匹配证书:
mkdir certs cd certs openssl req -x509 -subj "/CN=demo-cert-1" -keyout demo.key -out demo.crt -sha256 -days 365 -nodes -newkey ed25519 这会创建一个私钥,存储在 certs/demo.key 中,和一个与之匹配的(自签名)证书,通用名称为 demo-cert-1,存储在 certs/demo.crt 中。
现在创建一个新的 Spring Boot 3.2.0 应用,添加 Spring Web 依赖,默认情况下使用 Tomcat Web 服务器。你可以通过 start.springboot.io 快速创建。
在 application.yaml 配置文件中,添加如下配置:
spring.ssl.bundle.pem: demo: reload-on-update: true keystore: certificate: "certs/demo.crt" private-key: "certs/demo.key" 这配置了一个 SSL Bundle,名称为 demo,并配置上文生成的证书和私钥。