1、概览 Logbook 是一个可扩展的 Java 库,可为不同的客户端和服务器端提供完整的请求和响应日志。它允许开发人员记录应用接收或发送的任何 HTTP 流量。这可用于日志分析、审计或分析流量问题。
本文将带了解如何在 Spring Boot 中整合 Logbook,以及如何使用 Logbook 记录 HTTP 请求和响应。
2、依赖 在 Spring Boot 中添加 logbook-spring-boot-starter 依赖:
<dependency> <groupId>org.zalando</groupId> <artifactId>logbook-spring-boot-starter</artifactId> <version>3.9.0</version> </dependency> 你可以在 Maven Central 中找到最新版本的 Logbook。
3、配置 Logbook 与 Spring Boot 应用中的 logback 日志配合使用。
我们需要在 logback-spring.xml 和 application.properties 文件中添加配置。
在 pom.xml 中添加 Logbook 库后,Spring Boot 就会自动配置 Logbook 库,我们需要做的就是在 application.properties 文件中添加日志级别:
logging.level.org.zalando.logbook.Logbook=TRACE 启用 TRACE 日志级别,即可记录 HTTP 请求和响应。
此外,还要在 logback-spring.xml 文件中添加了 Logbook 配置:
<logger name="org.zalando.logbook" level="INFO" additivity="false"> <appender-ref ref="RollingFile"/> </logger> 添加完成后,就可运行应用了。每次 HTTP 请求调用后,Logbook 都会将请求和响应记录到 logback-spring.
1、简介 本文将带你了解如何使用 Spring Data JPA 检索数据列中的最大值(Max Value)。
2、示例 首先,添加 spring-boot-starter-data-jpa 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> 然后,定义一个简单的 Employee 实体表示员工:
@Entity public class Employee { @Id @GeneratedValue private Integer id; private String name; private Long salary; // 工资 // 构造函数、Getter、Setter 方法省略 } 接下来,看看有哪些方法可以检索出所有员工中薪水(salary)列的最大值。
3、使用 Repository 的派生查询 Spring Data JPA 提供了一个强大的机制,可以使用 Repository 方法来定义自定义查询。其中之一是派生查询,它允许我们通过声明方法名来实现SQL查询。
创建 Employee 实体类的 Repository 接口:
public interface EmployeeRepository extends JpaRepository<Employee, Integer> { Optional<Employee> findTopByOrderBySalaryDesc(); } 如上,我们实现了一个方法 findTopByOrderBySalaryDesc,该方法使用查询派生机制生成相应的 SQL。根据方法名,它将按照工资(salary)降序对所有员工进行排序,然后返回第一个员工,即工资最高的员工。
该方法会返回一个加载了所有属性的实体。如果我们只想检索一个工资(salary)值,可以使用投影查询:
创建 EmployeeSalary 投影接口:
事务(TRANSACTION),是指一组操作的集合,这些操作要么全部成功,要么全部失败。其目的是在出现错误、系统崩溃或其他意外情况下,保证数据的一致性和完整性。
事务通常具有以下四个重要的特性,这些特性被统称为 ACID 属性:
Atomicity(原子性): 定义: 事务中的所有操作要么全部完成,要么全部不完成,任何一个操作失败都会导致整个事务的失败,并且事务的所有操作都会被回滚(撤销)。 示例: 银行转账操作,如果从一个账户扣款后无法在另一个账户中存款,那么整个操作将回滚,不会执行任何更改。 Consistency(一致性): 定义: 事务只能把数据库从一种一致状态转换到另一种一致状态。在事务开始之前和结束之后,数据库的完整性约束没有被破坏。 示例: 在一个事务中插入数据时,如果插入的数据违反了数据库的完整性约束(例如唯一约束),那么这个事务将失败,数据库将保持一致状态。 Isolation(隔离性): 定义: 事务的执行是隔离的,多个事务并发执行时,一个事务的执行不会受到其他事务的干扰。隔离性确保了并发事务的执行结果与按顺序执行的结果相同。 示例: 两个用户同时购买同一件商品,隔离性确保每个用户看到的库存是正确的,避免超卖的情况。 Durability(持久性): 定义: 一旦事务提交,其结果将永久保存在数据库中,即使系统崩溃也不会丢失。 示例: 即使在事务提交后立即发生系统崩溃,事务的结果也会保存在数据库中,重启系统后数据依然存在。 以 MYSQL 关系型数据库为例,事务的使用如下:
-- 开始事务 BEGIN TRANSACTION; -- TODO 执行业务 1 -- TODO 执行业务 2 -- TODO 执行业务 3 -- .... -- 提交事务 COMMIT; -- 或者,回滚事务 ROLLBACK; 其中,BEGIN TRANSACTION、COMMIT 以及 ROLLBACK 都是事务固定的模板代码,当代的大多数框架都会自动帮我们进行处理。
Spring 对事务的支持 Spring 对关系型数据库中的事务提供强大的支持,包括声明式事务、TransactionTemplate 模板事务等等。
@Transactional 声明式事务 实际开发中,最常用的就是通过 @Transactional 注解来声明事务方法。事务方法会在执行开始前自动开始事务,在方法结束后自动提交事务,在执行过程中如果遇到异常则自动回滚事务。
import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @Transactional // 为 public 方法开启事务 public class FooService { public void service () { // TODO 在事务中执行业务 } } 在类上注解 @Transactional,则会为当前类中所有 public 方法开启声明式事务。也可以单独注解在方法上,则会覆盖类上的 @Transactional 定义。
Spring Boot v3.3.1 发布了,这是 Spring Boot v3.3 的第一个 BUG 修复版本。
🐞 Bug 修复 添加 org.springframework.boot.jdbc.parameters 标签后,SQL Server JDBC URL 出现格式错误 #41169 git-commit-id Maven 插件升级后,无法强制转换 Git instant 属性 #41152 将 status code 排除在 DefaultErrorAttributes 之外会引发 NPE(控指针异常)#41141 使用 devtools 进行 Spring Boot 远程重启时,在使用 java -jar 运行时会导致 Tomcat 错误 “factory already defined” #41107 MongoHealthIndicator 在严格设置下不符合 Mongo 稳定(Stable) API #41104 Bitnami MongoDB 服务连接失败 #41097 构建镜像时需要 Builder 指定一个栈(Stack)#41091 如果未包含 java.sql 模块,DataSourceProperties 绑定失败 #41084 使用 include 时,AOT 导致 Logback 配置错误 #41081 配置了 Builder 和 Buildpack 时,镜像构建挂起 #41049 尝试使用 Spring Boot 配置的 SSL 时,使用 Tomcat 的 HttpNio2Protocol 会抛出 IllegalArgumentException #41010 当包含 Multi-Release: true 的依赖项且 META-INF/versions 中存在意外文件条目时,Uber jar 启动失败 #41006 使用 Jetty 时,可执行 war 文件中可能找不到 JSP 相关资源 #40996 无论配置的最大线程数是多少,tomcat.
1、简介 了解如何处理 Java 类型层次结构中的对象对于编写灵活和可维护的代码至关重要。在这个领域中,两个基本概念是向上转型(Upcasting)和向下转型(Downcasting)。
本文将带你深入了解这些概念,探索它们之间的区别,以及它们在 Java 中的原理。
2、Java 中的类型转换 Java 是一种面向对象的编程语言(Object Oriented Programming,OOP),允许在其类型系统中将一种类型转换为另一种类型。转换是将一种类类型的引用转换为另一种类类型的过程。具体来说,Java 中主要有两种类型的转换:向上转型(Upcasting)和向下转型(Downcasting)。
假设我们有一个类的层次结构,其中 Dog 是 Animal 的子类。下图显示了向上转型(Upcasting)和向下转型(Downcasting)在这个层次结构中的工作原理:
向上转型(Upcasting)箭头从 Dog 类移动到 Animal 类,显示了子类引用(Dog)如何泛化为父类引用(Animal)。而,向下转型(Downcasting)箭头从 Animal 类返回 Dog 类,显示父类引用(Animal)如何再次被指定为子类引用(Dog)。
但是,如果尝试使用 Animal 引用实例化 Dog 对象,则会因类型不兼容而导致编译错误。
Dog dog = new Animal(); //异常 ClassCastException 3、Java 向上转型 向上转型(Upcasting)是指将子类引用转换为父类引用。这种类型的转换是隐式的,在处理多态性时经常使用它。
向上转型(Upcasting)允许我们将一个子类的对象当作一个父类的对象来处理:
class Animal { public void makeSound() { System.out.println("Animal sound"); } } class Dog extends Animal { public void makeSound() { System.out.println("Bark"); } public void fetch() { System.
1、简介 本文将带你了解如何使用 Jackson 序列化和反序列化 java.sql.Blob 对象。
java.sql.Blob 表示 Java 中的二进制大对象(Binary Large Object,Blob),可以存储大量二进制数据。在使用 Jackson 处理 JSON 序列化和反序列化时,处理 Blob 对象可能比较棘手,因为 Jackson 并不直接支持它们。不过,我们可以创建自定义的序列化器(Serializer)和反序列化器(Deserializer)来处理 Blob 对象。
2、依赖和示例项目 首先,在 pom.xml 中添加 jackson-databind 依赖:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.3</version> </dependency> 然后,创建一个简单的 User POJO,其中包含 id、name 和 Blob 类型的 profilePicture(图片数据):
public class User { private int id; private String name; private Blob profilePicture; // 构造函数,Getter/Setter 省略 } 3、定义 Blob 序列化器 定义一个序列化器(Serializer),将 User 的 profilePicture 属性转换为 Base64 编码的二进制字符串:
@JacksonStdImpl public class SqlBlobSerializer extends JsonSerializer<Blob> { @Override public void serialize(Blob value, JsonGenerator gen, SerializerProvider serializers) throws IOException { try { byte[] blobBytes = value.
1、简介 Spring WebClient 是一款非阻塞、响应式的 HTTP 客户端,而 WireMock 是一个强大的用于模拟基于 HTTP 的 API 的工具。
2、依赖和示例 首先,需要在 Spring Boot 项目中添加必要的依赖。
在 pom.xml 中添加 spring-boot-starter-flux(WebClient) 和 spring-cloud-starter-wiremock(WireMock Server)依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-contract-wiremock</artifactId> <version>4.1.2</version> <scope>test</scope> </dependency> 假设,我们的应用需要调用外部天气 API,以获取给定城市的天气数据。
定义 WeatherData POJO:
public class WeatherData { private String city; private int temperature; private String description; // 构造函数、Getter/Setter 方法省略 我们要使用 WebClient 和 WireMock 进行集成测试,以测试这个功能。
3、使用 WireMock API 进行集成测试 首先用 WireMock 和 WebClient 设置 Spring Boot 测试类:
1、概览 在构建处理敏感数据的 Web 应用时,确保用户密码的安全性非常重要。密码安全的一个重要方面是检查密码是否泄露,这通常是由于密码出现在 数据泄露事件 中。
Spring Security 6.3 引入了一项新功能,让我们可以轻松检查密码是否被已泄露。
本文将带你了解 Spring Security 中新的 CompromisedPasswordChecker API 以及如何将其集成到 Spring Boot 应用中。
2、密码泄露 密码泄露是指在数据泄露事件中暴露的密码,使其容易受到未经授权的访问。攻击者通常在凭证填充和密码填充攻击中使用这些泄露的密码,在多个网站上使用泄露的用户名-密码对,或在多个账户上使用通用密码。
要降低这种风险,关键是要在创建账户前检查用户密码是否泄露。
同样重要的是要注意,以前有效的密码可能会随着时间的推移而泄露,因此建议不仅在创建账户时,而且在登录过程中或任何允许用户更改密码的过程中都要检查密码是否泄露。如果登录尝试因检测到密码泄露而失败,可以提示用户重设密码。
3、CompromisedPasswordChecker Spring Security 提供了一个简单的 CompromisedPasswordChecker 接口,用于检查密码是否被泄露:
public interface CompromisedPasswordChecker { CompromisedPasswordDecision check(String password); } 该接口只暴露了一个 check() 方法,该方法将密码作为输入,并返回一个 CompromisedPasswordDecision 的实例,表明密码是否已被破解/泄露。
check() 方法需要明文密码,因此必须在使用 PasswordEncoder 加密密码之前调用该方法。
3.1、配置 CompromisedPasswordChecker Bean 要在应用中启用密码泄露检查,需要声明 CompromisedPasswordChecker 类型的 Bean:
@Bean public CompromisedPasswordChecker compromisedPasswordChecker() { return new HaveIBeenPwnedRestApiPasswordChecker(); } HaveIBeenPwnedRestApiPasswordChecker 是 Spring Security 提供的 CompromisedPasswordChecker 的默认实现。
Open AI 和 Spring AI 简介 当 OpenAI 发布 ChatGPT 时,它在全球掀起了一场风暴。这是第一次有语言模型能够根据提示生成类似人类的回答。此后,OpenAI 又发布了其他几个模型,包括可以根据文字提示生成图像的 DALL-E。
Spring AI 是一个 Java 库,为与 LLM 模型交互提供了一个简单易用的接口。Spring AI 提供了与各种 LLM(如 Open AI、Azure Open AI、Hugging Face、Google Vertex、Ollama、Amazon Bedrock 等)交互的高级抽象。
本文将带你了解如何使用 Spring AI 与 Open AI 能进行交互。
首先,需要在 OpenAI 上创建账户并获取 API Key。
访问 OpenAI Platform 并创建账户。 在控制面板中,点击左侧导航菜单中的 API Keys,创建一个新的 API Key。 如果你是新用户,你可能会获得一些免费点数来使用 OpenAI API。否则,你需要购买点数才能使用 OpenAI API。
获得 API KEY 后,把它添加到环境变量 OPENAI_API_KEY 中。
export OPENAI_API_KEY=<your-api-key> 创建 Spring AI 项目 使用 Spring Initializr 创建一个新的 Spring Boot 项目。
1、概览 Apache Tomcat,简称 Tomcat,是 Jakarta Servlet 规范的开源实现。它作为 Web 服务器接收 HTTP 或 WebSocket 请求,并调用负责的 Servlet 来处理请求。
本文将带你了解 Tomcat 中的并行部署(Parallel Deployment),以及如何实现不停机升级 Web 应用。
2、Tomcat 部署模式 我们可以通过两种方式使用 Apache Tomcat 为 Web 应用提供服务。第一种方法是将 Tomcat 程序嵌入 Java 应用本身。或者,可以将 Apache Tomcat 作为一个专用的 Web 服务器进程运行,为一个或多个 Web 应用提供服务。在这种模式下,开发人员会将 Web 应用打包成 WAR (Web Application Archive,Web 应用归档)包。然后,Web 服务器管理员会将 Web 应用部署到 Tomcat Web 服务器上。
独立的 Tomcat 部署模式现在不怎么流行了,但是也有好处。多个不同的 Web 应用使用同一个 Tomcat 服务器会节省一定的资源。
将 Tomcat 作为独立 Web 服务器运行时,需要了解如何对运行中的 Web 应用进行不停机重新部署。与通常将此任务委托给 Kubernetes 等外部协调器的容器化 Web 应用相反,Tomcat 中的部署依赖于 Tomcat 服务器,以最大限度地减少 Web 应用升级的停机时间。