一些使用小细节就是在不断的源码探索中逐步发现的,今天就来和大家研究一下通过 beanName 的设置,可以让一个 bean 拒绝被代理的问题!
1. 代码实践 假设我有如下一个切面:
@Aspect @EnableAspectJAutoProxy @Component public class LogAspect { @Pointcut("execution(* org.javaboy.demo.service.*.*(..))") public void pc() { } @Before("pc()") public void before(JoinPoint jp) { String name = jp.getSignature().getName(); System.out.println(name + " 方法开始执行了..."); } } 这个切面要拦截的方法是 org.javaboy.demo.service 包下的所有类的所有方法,现在,这个包下有一个 BookService 类,内容如下:
@Service("org.javaboy.demo.service.BookService.ORIGINAL") public class BookService { public void hello() { System.out.println("hello bs"); } } 这个 BookService 的 beanName 我没有使用默认的 beanName,而是自己配置了一个 beanName,这个 beanName 的配置方式是 类名的完整路径 + .ORIGINAL。
当我们按照这样的规则给 bean 取名之后,那么即使当前 bean 已经包含在切点所定义的范围内,这个 bean 也不会被代理了。
1、简介 本文将带你了解如何在 Spring Cloud Gateway 中读取、修改响应体,然后再响应给客户端。
2、Spring Cloud Gateway 快速回顾 Spring Cloud Gateway(简称 SCG)是 Spring Cloud 系列中的一个子项目,它提供了一个构建在响应式 Web 栈之上的 API 网关。关于它的更多详细信息和用法,你可以参考 官方文档。
设计 API Gateway 解决方案时经常出现的一种特殊使用场景:如何在将后端响应的 Body 发送回客户端之前对其进行处理?
下面列出了一些可能会用到这种功能的场景:
保持与现有客户端的兼容性,同时允许后台不断迭代 需要屏蔽响应中的某些敏感字段(脱敏) 实现这个需求,只需要实现一个 Filter 来处理后台响应即可。Filter 是 SCG 的核心概念。
Filter 组件创建后就可以将其应用于任何已声明的路由(Route)。
3、实现数据过滤 Filter 创建一个简单的 Filter 来屏蔽 JSON 响应中的某些值。
例如,给定的 JSON 有一个名为 “ssn” 的字段:
{ "name" : "John Doe", "ssn" : "123-45-9999", "account" : "9999888877770000" } 我们希望用一个固定的值进行替换,从而防止数据泄漏:
{ "name" : "John Doe", "ssn" : "****", "account" : "9999888877770000" } 3.
1、概览 Spring IoC 容器创建和管理 Spring Bean,这些 Bean 是应用的核心。创建一个 Bean 实例与从普通的 Java 类创建对象相同。然而,生成多个相同类的 Bean 可能会比较麻烦一点。
本文将带你了解如何在 Spring 中使用注解创建同一个类的多个 Bean。
2、使用 Java 配置 这是使用注解创建多个同类 Bean 的最简单易行的方法。
举一个简单的例子。我们有一个 Person 类,它有两个字段:firstName 和 lastName:
public class Person { private String firstName; private String lastName; public Person(String firstName, String secondName) { super(); this.firstName = firstName; this.lastName = secondName; } @Override public String toString() { return "Person [firstName=" + firstName + ", secondName=" + lastName + "]"; } } 接下来,构建一个名为 PersonConfig 的配置类,并在其中定义 Person 类的多个 Bean:
1、概览 Testcontainers 是一个用于创建临时 Docker 容器进行单元测试的 Java 库。当我们想要避免使用实际服务器进行测试时,它非常有用。
本文将会带你了解如何在 Spring Boot 中使用 Testcontainers 测试 Redis。
2、项目设置 使用任何测试容器的首要前提是在运行测试的机器上安装 Docker。
安装好 Docker 后,就可以开始设置 Spring Boot 应用了。
在此应用中,我们将设置一个 Redis Hash、一个 Repository 和一个使用 Repository 与 Redis 交互的 Service。
2.1、依赖 添加所需的 spring-boot-starter-test 和 spring-boot-starter-data-redis 依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 接着,还要添加 Testcontainers 依赖:
<dependency> <groupId>org.testcontainers</groupId> <artifactId>testcontainers</artifactId> <version>1.17.2</version> <scope>test</scope> </dependency> 2.2、配置 在 application.properties 文件中添加 Redis 连接的详细信息:
spring.redis.host=127.0.0.1 spring.redis.port=6379 3、应用设置 我们要创建一个小型应用,向 Redis 数据库读写 Product(产品)。
3.1、Entity 创建 Product 类。
1、简介 通常我们会通过集成测试来验证应用功能是否正常。集成测试至关重要,特别是对于认证这种敏感且重要的功能。Testcontainers 允许在测试阶段启动 Docker 容器,以便对实际的技术栈运行测试。
本文将带你了解如何使用 Testcontainers 针对实际的 Keycloak 实例设置集成测试。
2、配置 Spring Security 和 Keycloak 我们需要配置 Spring Security、Keycloak 和 Testcontainers。
2.1、整合 Spring Boot 和 Spring Security 在 pom.xml 中添加 spring-boot-starter-security 依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> 接着,创建一个示例 Controller,它返回一个 User。
@RestController @RequestMapping("/users") public class UserController { @GetMapping("me") public UserDto getMe() { return new UserDto(1L, "janedoe", "Doe", "Jane", "jane.doe@baeldung.com"); } } 至此,我们有了一个受保护的 Controller,用于处理对 /users/me 端点的请求。启动应用时,Spring Security 会为用户 user 生成一个密码,该密码在控制台输出的日志中。
2.配置 Keycloak 启动本地 Keycloak 的最简单方法是使用 Docker。
1、概览 空指针异常 NullPointerException 是一个常见问题,避免这种问题的方法之一是在方法参数上添加 @NotNull 等校验注解。
给方法参数添加了 @NotNull 注解后,还需要其他的一些设置才能自动对参数进行非空校验。
2、给方法参数添加 @NotNull 注解 创建一个类,其中包含一个返回 String 长度的方法。
在 String 参数上添加 @NotNull 注解:
public class NotNullMethodParameter { public int validateNotNull(@NotNull String data) { return data.length(); } } 注意,有多个包下都有 @NotNull 注解,我们使用的应该是 jakarta.validation.constraints 包。
创建 NotNullMethodParameter 实例,然后使用 null 参数调用方法。
NotNullMethodParameter notNullMethodParameter = new NotNullMethodParameter(); notNullMethodParameter.doesNotValidate(null); 尽管在参数上使用了 @NotNull,但还是出现了空指针异常:NullPointerException。
注解未生效,因为没有 Validator 来执行它。
3、添加 Validator 添加 Hibernate Validator(jakarta.validation 的实现)来识别 @NotNull。
<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>8.0.0.Final</version> </dependency> 使用默认的 ValidatorFactory 创建 validator。
Spring Boot 对静态资源提供了支持。默认情况下,以下目录为默认的静态资源目录。其中的静态资源可以被直接访问:
classpath:/META-INF/resources/ classpath:/resources/ classpath:/static/ classpath:/public/ ${user.dir}/public/ (程序运行目录下的 public 目录) 优先级从上往下,当多个静态资源目录中出现同名文件时,越靠上的目录权重越高。
静态资源的处理类是 ResourceHttpRequestHandler,它会正确地处理资源的 Last-Modified 响应和 Range 请求。
静态资源和 RequestMapping 冲突 如果静态资源路径和 @RequestMapping 路径冲突,则 @RequestMapping 优先。
例如,有如下 Controller:
@RestController @RequestMapping public class DemoController { @GetMapping("/foo") public ResponseEntity<String> foo () { // 返回字符串 “controller” return ResponseEntity.ok("controller"); } } 在 src/main/resources/public 目录下有一个名为 foo 的文本文件,内容如下:
public 启动应用,访问 http://localhost:8080/foo:
$ curl http://localhost:8080/foo controller 你可以看到,响应的内容是 controller,说明 controller 的 @RequestMapping 优先。
另外,对于这种没有后缀、未知类型的静态资源,Spring Boot 会以 “下载” 的形式响应给客户端(添加了 Content-Disposition 响应头)。
1、概览 本文将带你了解如何在 Spring MVC Web 应用中使用 springdoc-openapi 配置默认的全局 Security Scheme,并将其应用为 API 的默认安全配置,以及如何覆盖这些默认的安全配置。
OpenAPI 规范 允许为 API 定义一套 Security Scheme。可以配置 API 全局的安全配置,也可以按端点应用/删除安全配置。
2、设置 构建一个 Spring Boot Web 项目,使用 Maven。
2.1、依赖 该示例有两个依赖。第一个是 spring-boot-starter-web,用于构建 Web 应用。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.7.1</version> </dependency> 另一个依赖是 springdoc-openapi-ui,它用于输出 HTML、JSON 或 YAML 格式的 API 文档:
<dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.6.9</version> </dependency> 2.2、启动类 使用 @SpringBootApplication 注解来定义启动类,通过 SpringApplication 类来启动应用:
@SpringBootApplication public class DefaultGlobalSecuritySchemeApplication { public static void main(String[] args) { SpringApplication.run(DefaultGlobalSecuritySchemeApplication.class, args); } } 3、springdoc-openapi 基础配置 配置好 Spring MVC 后,来看看 API 语义信息。
1、概览 本文将会带你了解在 Java 响应式编程中如何将 Flux<DataBuffer> 读取到 InputStream。
2、请求设置 首先,使用 Spring Reactive WebClient 发起 GET 请求。使用由 gorest.co.in 托管的公共 API 端点来进行测试:
String REQUEST_ENDPOINT = "https://gorest.co.in/public/v2/users"; 接下来,定义 getWebClient() 方法,用于获取 WebClient 类的新实例:
static WebClient getWebClient() { WebClient.Builder webClientBuilder = WebClient.builder(); return webClientBuilder.build(); } 至此,我们就可以向 /public/v2/users 端点发出 GET 请求了。注意,必须以 Flux<DataBuffer> 对象的形式获取响应体。
3、BodyExtractors 和 DataBufferUtils 我们可以使用 spring-webflux 中 BodyExtractors 类的 toDataBuffers() 方法将响应体提取到 Flux<DataBuffer> 中。
将 body 构建为 Flux<DataBuffer> 类型的实例:
Flux<DataBuffer> body = client .get( .uri(REQUEST_ENDPOINT) .exchangeToFlux( clientResponse -> { return clientResponse.
1、简介 GraalVM 使用其 Ahead-Of-Time(AOT)编译器将 Java 应用程序编译为机器可执行文件。这些可执行文件直接在目标机器上执行,而无需使用即时编译器 (JIT)。GraalVM生成的二进制文件体积较小,启动速度快,并且在没有任何预热的情况下提供最佳性能。此外,这些可执行文件相比在 JVM 上运行的应用程序而言,内存占用和 CPU 使用率较低。
通过 Docker,我们可以将软件组件打包成 Docker Image,并作为 Docker 容器运行。Docker 容器包含应用程序运行所需的一切,包括应用程序代码、运行时、系统工具和库。
在本教程中,我们将了解如何创建 Java 应用程序的 GraalVM 原生(native)镜像,以及如何将该原生镜像用作 Docker 镜像,并将其作为 Docker 容器运行。
2、原生镜像是什么? 原生镜像(Native Image)是一种将 Java 代码提前编译成原生可执行文件的技术。该原生可执行文件只包含运行时需要执行的代码。这包括应用程序类、标准库类、语言运行时和 JDK 中静态链接的本地代码。
原生镜像生成器(Native Image Builder)会扫描应用程序类和其他元数据,以创建一个特定于操作系统和体系结构的二进制文件。本地镜像工具会执行静态应用程序代码分析,以确定应用程序运行时可访问的类和方法。然后,它将所需的类、方法和资源编译成二进制可执行文件。
3、原生镜像的优点 原生镜像可执行文件有几个好处:
由于原生镜像生成器只编译运行时所需的资源,因此可执行文件的体积很小 本地可执行文件的启动时间极短,因为它们是在目标机器中直接执行的,无需使用 JIT 编译器 由于只打包所需的应用程序资源,暴漏的攻击面较小 将其打包为轻量级容器镜像(如 Docker Image),有助于快速高效地部署 4、构建 GraalVM 原生镜像 在本节中,我们将为 Spring Boot 应用构建 GraalVM 原生镜像。首先,需要安装 GraalVM 并设置 JAVA_HOME 环境变量。其次,创建一个包含 Spring Web 和 GraalVM Native Support 依赖的 Spring Boot 应用: