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、业务对象 业务对象是一个具有正常业务逻辑的普通类。
来看一个简单的业务对象示例,只需将两个数字相加:
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,我们需要了解如何:
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 生成 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 私钥:
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.
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.
1、概览 本文将带你了解如何在 Spring WebSockets 中使用 @SendToUser 注解向特定 Session 或特定用户发送消息。
有关上述 Spring WebSockets 的介绍,请参阅 上一篇文章。
2、WebSocket 配置 首先,需要配置 Message Broker 和 WebSocket 应用端点:
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic/", "/queue/"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/greeting"); } } 通过 @EnableWebSocketMessageBroker 注解,启用了在 WebSocket 上使用 STOMP(Streaming Text Oriented Messaging Protocol)的基于 Broker 的消息传递。需要强调的是,这个注解需要与 @Configuration 一起使用。
继承 AbstractWebSocketMessageBrokerConfigurer 并不是必须的,但这可以更容易地自定义导入的配置。
在第一个方法中,建立了一个简单的基于内存的 Message Broker,通过以 /topic 和 /queue 为前缀的目标将消息传回客户端。
1、概览 本文将带你学习如何使用 Spring 4 中引入的 WebSocket 功能来实现一个简单的聊天应用。
WebSockets 是 Web 浏览器和服务器之间的一种双向、全双工、持久连接。一旦建立了 WebSocket 连接,该连接就会一直打开,直到客户端或服务器关闭该连接。
2、Maven 依赖 在 pom.xml 中添加所需的依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>5.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>5.2.2.RELEASE</version> </dependency> 此外,还需要添加 Jackson 依赖,用于序列化/反序列化 JSON 格式的消息。
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.10.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.2</version> </dependency> 3、启用 WebSocket 首先,在配置类上通过 @EnableWebSocketMessageBroker 注解来启用 WebSocket 功能。
配置类需要继承 AbstractWebSocketMessageBrokerConfigurer。
顾名思义,它能在 Message Broker 的支持下处理 WebSocket 消息:
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.
1、概览 在 Spring Boot 应用中,一般使用 RestTemplate 来执行同步 HTTP 请求。数据通常以 JSON 的形式返回,而 RestTemplate 可以进行自动转换。
本文将带你了解,如何在 RestTemplate 中把响应的 JSON 数组转换为 Object 数组、POJO 数组和 POJO 集合。
2. JSON、POJO 和 Service 假设我们有一个端点 http://localhost:8080/users,它返回如下 JSON 格式的用户列表:
[{ "id": 1, "name": "user1", }, { "id": 2, "name": "user2" }] 对应的 User 类如下:
public class User { private int id; private String name; // get/set 方法省略 } 定义 Service 接口实现 UserConsumerServiceImpl,并注入 RestTemplate:
public class UserConsumerServiceImpl implements UserConsumerService { private final RestTemplate restTemplate; public UserConsumerServiceImpl(RestTemplate restTemplate) { this.
1、背景 有好几次线上发布老应用时,遭遇代码启动报错,具体错误如下:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'xxxManageFacadeImpl': Bean with name 'xxxManageFacadeImpl' has been injected into other beans [xxxProductMaintenceFacadeImpl] in its raw version as part of a circular reference, but has eventually been wrap means thff, for expped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesallowEageOfType' with the 'allowEagerInit' flag turned off, for example 咋眼一看,这不就是 Spring Bean 循环依赖报错吗?脑海立马闪过那些年为了进阿里面试时被死亡 N 连问的场景,那时我们都知道 Spring 已经支持 Bean 循环依赖,为啥我们的 Spring Boot 应用启动时还报这个错误?于是,带着这个问题重新温习下 Spring 如何解决 Bean 循环依赖。