Spring

检测 Spring 事务是否处于活动状态

1、概览 本文将带你了解在代码中检测 Spring 事务的几种方法。 2、事务配置 要在 Spring 中运行事务,必须启用事务管理。如果使用的是Spring Boot 项目,并且依赖了 spring-data- 或 spring-tx,Spring 会默认启用事务管理。否则,必须手动启用事务并明确提供事务管理器(Transaction Manager)。 首先,需要在 @Configuration 类中添加 @EnableTransactionManagement 注解。这样,在项目中就可以使用 Spring 注解驱动的事务管理了。 接下来,必须提供 PlatformTransactionManager 或 ReactiveTransactionManager Bean。该 Bean 需要一个数据源。可以选择使用一些常用库,如 H2 或 MySQL 库。这不是本文的重点。 启用事务后,就可以使用 @Transactional 注解来开启事务。 3、TransactionSynchronizationManager Spring 提供了一个名为 TransactionSychronizationManager 的类。该类有一个名为 isActualTransactionActive() 的静态方法可以让我们知道自己是否处于事务。 测试如下,用 @Transactional 注解一个测试方法。在方法中断言 isActualTransactionActive() 返回 true: @Test @Transactional public void givenTransactional_whenCheckingForActiveTransaction_thenReceiveTrue() { assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); } 同样,删除 @Transactional 注解时,测试应断言返回 false: @Test public void givenNoTransactional_whenCheckingForActiveTransaction_thenReceiveFalse() { assertFalse(TransactionSynchronizationManager.isActualTransactionActive()); } 4、Spring 事务日志 也许你并不需要以编程式的方式来检测事务,可能只是想在应用的日志中查看事务发生的时间,可以在 properties 文件中启用 Spring 的事务日志:

Spring 加载时织入(Load-Time Weaving)

简介 本文将带你了解 Spring 加载时织入(Load-Time Weaving)是如何工作的,以便在运行时应用 Hibernate 字节码增强机制。 一般来说,字节码增强机制是在使用 Maven 或 Gradle 插件构建项目时应用的。 Domain Model 假设有以下 Attachment 实体,如下: @Entity @Table(name = "attachment") public class Attachment { @Id private Long id; private String name; @Enumerated @Column(name = "media_type") private MediaType mediaType; @Lob @Column(columnDefinition="BLOB") @Basic(fetch = FetchType.LAZY) private byte[] content; // get、set 和其他方法省略 } content 属性使用的是 FetchType.LAZY 抓取策略,但在 POJO 实体上无法懒加载实体属性,因此需要 Hibernate 字节码增强机制来实现这一目标。 Hibernate 字节码增强机制 Hibernate 字节码增强机制允许我们更改 JPA 实体的字节码,这样就可以拦截 getter 和 setter 方法调用,从而达到以下目的 懒加载属性 记录实体的修改 如上所述,字节码增强机制是通过 Maven 或 Gradle 插件配置的,该插件会在项目构建时增强实体类。

CDS(Class Data Sharing)在 Spring 6.1 中的应用

正如 官方文档 所述,类数据共享(CDS)通过将类元数据缓存在 Archive(归档/存档) 文件中,使其可以快速预加载到新启动的 JVM 中,从而帮助缩短 JVM 的启动时间和内存占用。这加快了类加载速度,而类加载速度是启动时间的一个重要因素。大多数最新的 JDK 发行版中预先打包了默认的 CDS 归档,其中包含了常见 JDK 类的元数据。你也可以创建自定义的 CDS 归档,以加快类在自己应用中的加载速度。 GraalVM 原生镜像 和 Project CRaC 都能让 Spring Boot 应用在几十毫秒内启动。那么,为什么要关注 CDS 呢? 主要有三个原因: 它是 OpenJDK 主线中成熟且可用于生产的技术,与 GraalVM 和 Project CRaC 相比,它更易于使用,因为它具有较少的限制和副作用。 正如 Brian Goetz 在他在 Devoxx 上的 Project Leyden 演讲 中提到的:“大多数人今天不使用 CDS,但可能应该使用,因为他们可以通过相对较少的工作获得合理的启动性能提升。” 在每一个新的 JVM 版本中,这项技术都会变得越来越好,Project Leyden 的目标是在不久的将来增加更多的优势。 接下来,让我们一起探究 CDS 能为你的 Spring 应用带来什么? 在 Spring 6.1 中引入 CDS 初始支持 Spring 6.1 带来了一个新的 “类数据共享” 文档章节,解释了优化应用的两个步骤: 使用新增的 -Dspring.

Spring MVC 教程

1、概览 这是一个简单的 Spring MVC 教程,介绍如何通过基于 Java 的配置和 XML 配置来建立 Spring MVC 项目。 Spring MVC 依赖: <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework.version}</version> </dependency> 2、Spring MVC 是啥? 顾名思义,它是 Spring 框架中处理模型(Model)- 视图(View)- 控制器(Controller)或 MVC 模式的一个模块。它结合了 MVC 模式的所有优点和 Spring 的便利性。 Spring 使用其 DispatcherServlet 前控制器模式实现 MVC。 简而言之,DispatcherServlet 是将请求路由到预定目的地的主要控制器。Model 只是应用的数据,而视图则由各种模板引擎来表示。 3、使用 Java 配置的 Spring MVC 要通过 Java 配置类启用 Spring MVC 支持,只需添加 @EnableWebMvc 注解即可: @EnableWebMvc @Configuration public class WebConfig { /// ... } 这将设置 MVC 项目所需的基本支持,如注册处理器、映射器、类型转换器、验证支持、消息转换器和异常处理。

基于 XML 配置的 Spring AOP 教程

1、简介 本文将带你了解 Spring 中的 AOP(面向切面编程),并学习如何在实际场景中使用这一强大工具。 在使用 Spring AOP 开发时,还可以利用 @AspectJ 的注解,但本文重点介绍 Spring AOP 基于 XML 的核心配置。 2、概览 AOP 是一种编程范式,旨在通过分离横切关注点来提高模块化程度。它通过在不修改代码本身的情况下为现有代码添加额外的行为来实现这一目标。 Spring 的 AOP 框架 可以帮助我们实现这些切面关注点。 3、Maven 依赖 首先,在 pom.xml 中添加 Spring 的 AOP 依赖: <!-- Spring Boot 应用 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> </dependencies> <!-- Spring 应用 --> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>6.1.1</version> </dependency> </dependencies> 可以在 Maven 仓库中查询到最新的版本。 4、AOP 概念和术语 简要回顾一下 AOP 的特定概念和术语: 4.1、业务对象 业务对象是一个具有正常业务逻辑的普通类。 来看一个简单的业务对象示例,只需将两个数字相加:

Spring WebClient 教程

1、概览 本文将带你了解如何使用 WebClient 和 WebTestClient,前者是一个 Spring 5 中引入的响应式 HTTP 客户端,而后者是一种用于测试的 WebClient。 2、WebClient 是啥? 简而言之,WebClient 是一个接口,表示执行 Web 请求的主要入口点。 它是 Spring Web Reactive 模块的一部分,用于取代经典的 RestTemplate。此外,这个新的客户端是一个基于 HTTP/1.1 协议的响应式、非阻塞解决方案。 尽管它实际上是一个非阻塞客户端,而且属于 spring-webflux 库,但该解决方案同时支持 同步 和 异步 操作,因此也适用于在 Servlet 技术栈上运行的应用,通过阻塞操作来获得结果。当然,如果使用的是响应式技术栈,则不建议采用这种做法。 该接口只有一个实现,即我们将要使用的 DefaultWebClient 类。 3、依赖 在 Spring Boot 应用中,只需要添加 spring-boot-starter-webflux 依赖即可获得响应式 Web 的支持。 3.1、使用 Maven 构建 在 pom.xml 中添加以下依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> 3.2、使用 Gradle 构建 build.gradle 文件中添加以下条目: dependencies { compile 'org.springframework.boot:spring-boot-starter-webflux' } 4、使用 WebClient 要使用 WebClient,我们需要了解如何:

Spring 中的控制反转(IoC)和依赖注入(DI)

1、概览 本文将带你了解 IoC(控制反转)和 DI(依赖注入)的概念,以及如何在 Spring 中实现这些概念。 2、控制反转(IoC)是什么? 控制反转(Inversion of Control)是软件工程中的一项原则,它将对象或程序部分的控制权转移到容器或框架中。在面向对象的编程中经常使用。 也有人叫 “反转控制”。 在传统编程中,我们使用自定义代码来调用库,而 IoC 则使框架能够控制程序的流程,并调用我们的自定义代码。框架使用了带有内置附加行为的抽象类来实现这一点。如果我们想添加自己的行为,就需要继承框架的类或插入自己的类。 这种架构的优势在于: 将任务的执行与任务的实现分离开来 更容易在不同的实现之间切换 程序的模块化程度更高 通过隔离组件或模拟其依赖,并允许组件通过 “约定” 进行通信,从而更轻松地测试程序 我们可以通过各种机制实现控制反转,例如:策略模式、服务定位模式、工厂模式和依赖注入(DI)。 3、依赖注入(DI)是什么? 依赖注入是可以用来实现 IoC 的一种模式,其中被反转的控制是 设置对象的依赖。 将对象与其他对象 “装配” 起来,或将对象 “注入” 到其他对象中是由组装器(Assembler)而不是对象本身来完成的。 下面是我们在传统编程中创建依赖对象的方法: public class Store { private Item item; public Store() { item = new ItemImpl1(); // 实例化所需的依赖 } } 重写示例,通过使用 DI,而无需指定 Item 的实现: public class Store { private Item item; public Store(Item item) { this.item = item; } } 在接下来的章节中,将带你了解如何通过元数据(Metadata)来实现 Item。

Java 加载 PEM 格式的 RSA 证书和私钥

在 上一篇文章 中,我们介绍了如何使用 Java 生成 RSA 密钥对,以及如何使用 RSA 进行加密、解密和签名验签。 在实际情况中,RSA 加密、解密所使用的密钥对往往是已经生成好的,通常以 PEM(Privacy Enhanced Mail)格式存储。 PEM 是一种常见的文件格式,用于存储和传输加密的 证书、私钥 和其他安全相关的数据。 证书(Certificate):用于存储公钥证书,通常以 .pem 或 .crt 为扩展名。 私钥(Private Key):用于存储私钥,通常以 .pem 或 .key 为扩展名。 PEM 格式的文件通常以.pem为扩展名,它使用标头和尾部标记来界定不同类型的数据,并使用 Base64 编码将二进制数据转换为 ASCII 文本。 本文将带你了解如何在 Java 中使用 Spring 的 PemContent 工具类加载 PEM 格式的 RSA 证书和私钥为 PublicKey 和 PrivateKey 对象。 使用 OpenSSL 生成 RSA 私钥和证书 我们使用 OpenSSL 来生成示例所用的 RSA 私钥和证书。首先需要确保你在本机安装了 OpenSSL,并且正确地配置到了 PATH 环境变量。 OpenSSL 是一个开源的密码学工具库,被广泛应用于网络安全领域,用于创建和管理 SSL/TLS 连接、生成自签名证书、签发数字证书、进行加密通信等。 生成 2048 位的 RSA 私钥:

Spring 整合 Thymeleaf 模板引擎

1、概览 Thymeleaf 是一个 Java 模板引擎,用于处理和创建 HTML、XML、JavaScript、CSS 和文本。 本文将带你了解如何在 Spring 和 Spring Boot 应用中整合、使用 Thymeleaf。 该库具有极高的可扩展性,其天然的模板功能可以确保在没有后端的情况下制作模板原型。与其他流行的模板引擎(如 JSP)相比,这使得开发速度非常快。 2、Spring 整合 Thymeleaf 首先,来看看与 Spring 整合所需的配置。这需要使用 thymeleaf-spring 库。 在 Maven POM 文件中添加以下依赖: <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>3.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> <version>3.1.2.RELEASE</version> </dependency> 注意,对于 Spring 4,必须使用 thymeleaf-spring4,而不是 thymeleaf-spring5。 通过 SpringTemplateEngine 类执行所有配置步骤。 可以在 Java 配置中将该类配置为 bean: @Bean @Description("Thymeleaf Template Resolver") public ServletContextTemplateResolver templateResolver() { ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(); templateResolver.setPrefix("/WEB-INF/views/"); templateResolver.setSuffix(".html"); templateResolver.setTemplateMode("HTML5"); return templateResolver; } @Bean @Description("Thymeleaf Template Engine") public SpringTemplateEngine templateEngine() { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.

RestTemplate 教程

1、概览 本文将带你了解如何使用 Spring REST 客户端 RestTemplate 发起各种类型的 HTTP 请求。 2、废弃警告 从 Spring Framework 5 开始,除了 WebFlux,Spring 还引入了一个名为 WebClient 的新 HTTP 客户端。 WebClient 是一种替代 RestTemplate 的现代 HTTP 客户端。它不仅提供传统的同步 API,还支持高效的非阻塞和异步方法。 如果要开发新的应用或迁移旧的应用,最好还是使用 WebClient。在未来版本中,RestTemplate 将被弃用。 3、使用 GET 检索资源 3.1、获取纯 JSON 格式 使用 getForEntity() API 发起 GET 请求: RestTemplate restTemplate = new RestTemplate(); String fooResourceUrl = "http://localhost:8080/spring-rest/foos"; ResponseEntity<String> response = restTemplate.getForEntity(fooResourceUrl + "/1", String.class); Assertions.assertEquals(response.getStatusCode(), HttpStatus.OK); 可以访问完整的 HTTP 响应,因此可以检查 HTTP 状态码是否成功,或者处理响应体: ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.