限制 Webclient 的并发请求数量

1、简介 本文介绍了一些限制 WebClient 并发请求数量的方式。 2、服务端 限制 WebClient 并发请求数量是为了避免服务器因大量并发请求而宕机。有些服务自身也提供了一些限制策略。 2.1、一个简单的 Controller 为了演示,先定义一个简单的 @RestController,它返回固定范围的随机数字: @RestController @RequestMapping("/random") public class RandomController { @GetMapping Integer getRandom() { return new Random().nextInt(50); } } 接下来,我们将模拟一些耗时的操作,并限制并发请求的数量。 2.2、服务器限制并发请求数 修改服务,模拟一个更真实的场景。 首先,限制服务器可接受的并发请求数,并在达到限制时抛出异常。 其次,增加处理响应的延迟,模拟耗时的操作。 创建 Concurrency 用于限制并发数量: public class Concurrency { public static final int MAX_CONCURRENT = 5; static final AtomicInteger CONCURRENT_REQUESTS = new AtomicInteger(); public static int protect(IntSupplier supplier) { try { if (CONCURRENT_REQUESTS.incrementAndGet() > MAX_CONCURRENT) { throw new UnsupportedOperationException("max concurrent requests reached"); } TimeUnit.

在 Spring 中使用 Groovy

1、概览 Groovy 是一种功能强大的动态 JVM 语言,具有众多特性。在 Spring 中使用 Groovy 可以大大提高应用程序的灵活性和可读性。从 Spring 4 开始 支持基于 Groovy 的配置。 在本教程中,我们将了解 Groovy 与 Spring 结合使用的各种方法。首先介绍了如何使用 Spring 提供的多个选项来创建 Groovy Bean 定义。接下来,了解如何使用 Groovy 脚本加载 Application Context。最后,学习如何使用 XML 和 GroovyScriptEngine 类将 Groovy 作为脚本执行(无需编译)。 2、Maven 依赖 首先,在 pom.xml 中定义 Groovy 依赖: <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy</artifactId> <version>3.0.12</version> </dependency> 此外,还需要添加 GMavenPlus 插件来编译 Groovy 文件: <build> <plugins> <plugin> <groupId>org.codehaus.gmavenplus</groupId> <artifactId>gmavenplus-plugin</artifactId> <version>1.9.0</version> <executions> <execution> <goals> <goal>addSources</goal> <goal>addTestSources</goal> <goal>generateStubs</goal> <goal>compile</goal> <goal>generateTestStubs</goal> <goal>compileTests</goal> <goal>removeStubs</goal> <goal>removeTestStubs</goal> </goals> </execution> </executions> </plugin> </plugins> </build> 3、Bean 定义 传统上,开发人员通过 XML 配置来声明 Bean。这种方式后来被通过 Java 注解以编程方式定义 Bean 所取代。另一种声明 Bean 的方式是通过 Groovy 脚本。

获取 Spring Boot 应用的 PID

PID 是进程标识符(Process Identifier)的缩写。在操作系统中,每个运行的进程都被分配一个唯一的 PID,用于标识进程。PID 通常是一个整数值,可以用来跟踪和管理进程的状态、资源分配以及进程间的通信。 本文将会介绍几种获取 Spring Boot 应用 PID 的方法。 ApplicationPidFileWriter ApplicationPidFileWriter 是 Spring Boot 提供的一个 Listener,它可以在应用启动后把 PID 写入到指定的文件。 它需要在启动前,通过编程式配置到应用中,并且需要在配置文件中指定要写入 PID 的文件。 application.yaml 配置如下: spring: pid: # 写入 PID 的文件,可以是相对路径或绝对路径 file: app.pid # 如果 PID 无法写入,是否抛出异常 fail-on-write-error: true 在启动前,配置 ApplicationPidFileWriter 监听器: import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.ApplicationPidFileWriter; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication springApplication = new SpringApplicationBuilder() .listeners(new ApplicationPidFileWriter()) // PID 监听 .

在 Spring Boot 中使用 SSL Bundle 配置 SSL

安全套接字层(SSL)和传输层安全(TLS)是在分层或面向服务的架构中保护系统之间通信的关键组件。在这样的架构中,Spring Boot 应用程序通常接受传入的网络连接或创建传出连接,开发人员的任务是配置应用程序以在这样的安全环境中工作。 如果你曾经使用过 Java 的 Security 和 SSL API,你可能意识到这不是一项特别简单的任务。你可能会在网上复制各种代码片段。有几个因素使得与 SSL 工作变得痛苦。 首先,你可能会收到用于生产环境的 SSL 资源文件,如证书和私钥。你可能需要为预生产测试生成不同的证书(通常使用自签名证书颁发机构)。这些证书通常以 Java Keystore 文件的形式存在,可以是 JKS 或 PKCS #12 格式,或者它们可能是 PEM 编码的文本文件。每种文件类型都需要不同的处理方式。 一旦你有了证书,你需要将其转换为可以传递给 Java Connection API 的形式。麻烦点就在这里,因为 Connection API 可以以多种方式进行配置: 有的要你提供 java.security.KeyStore(Keystore 和 Truststore) 实例。 有的要你提供 javax.net.ssl.KeyManager 和 javax.net.ssl.TrustManager 实例。 有的要你提供 javax.net.ssl.SSLContext 实例。 SSL 也是相当底层的,因此通常需要逐层解除抽象,以使用 java.security 或 java.net.ssl 包中的对象进行配置。例如,如果你想在 Spring RestTemplate 上配置SSL,你需要深入到支持它的 ClientHttpRequestFactory。对于典型的 Spring Boot 应用程序,可能是一个 HttpComponentsClientHttpRequestFactory、OkHttp3ClientHttpRequestFactory 或 SimpleClientHttpRequestFactory。每个 Factory 都提供了不同的配置API。 Spring Boot 配置 SSL 或 TLS 并不是什么新鲜事,但团队决定全面审视当前对 SSL 的支持,寻找改进和扩展支持的机会。我们希望 Spring Boot 3.

@EnableMethodSecurity 注解

1、概览 使用 Spring Security,可以为应用配置身份认证和授权,以控制方法(如端点)的访问权限。 在 5.6 之前,使用 @EnableGlobalMethodSecurity 注解是标准的做法,在 5.6 之后,@EnableMethodSecurity 引入了一种更灵活的方法来配置方法安全授权(Method Security)。 在本教程中,我们将通过示例代码了解 @EnableMethodSecurity 如何代替 @EnableGlobalMethodSecurity,以及他们之间的区别。 2、@EnableMethodSecurity 和 @EnableGlobalMethodSecurity 让我们来看看方法授权如何与 @EnableMethodSecurity 和 @EnableGlobalMethodSecurity 配合使用。 2.1、@EnableMethodSecurity 通过 @EnableMethodSecurity,可以看到 Spring Security 为授权类型(Authorization Type)采用基于 Bean 的配置。 我们现在为每种类型都设置了一个配置,而不是全局配置。例如,Jsr250MethodSecurityConfiguration: @Configuration(proxyBeanMethods = false) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) class Jsr250MethodSecurityConfiguration { // ... @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) Advisor jsr250AuthorizationMethodInterceptor() { return AuthorizationManagerBeforeMethodInterceptor.jsr250(this.jsr250AuthorizationManager); } @Autowired(required = false) void setGrantedAuthorityDefaults(GrantedAuthorityDefaults grantedAuthorityDefaults) { this.jsr250AuthorizationManager.setRolePrefix(grantedAuthorityDefaults.getRolePrefix()); } } MethodInterceptor 主要包含一个 AuthorizationManager,它现在将 “检查和返回最终决策的 AuthorizationDecision 对象” 的责任委托给适当的实现,这里是 AuthenticatedAuthorizationManager。

Spring Boot 在运行时启用和禁用端点

1、概览 在 Spring Boot 运行时,出于一些维护目的,我们可能需要动态地启用、禁用某些端点。 在本教程中,我们将学习如何使用 Spring Cloud、Spring Actuator 和 Apache 的 Commons Configuration 等几个常用库在运行时启用和禁用 Spring Boot 端点。 2、项目设置 以下是 Spring Boot 项目的关键设置。 2.1、Maven 依赖 首先,在 pom.xml 文件中添加 spring-boot-starter-actuator 依赖,用于暴露 /refresh 端点: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>2.7.5</version> </dependency> 接下来,添加 spring-cloud-starter 依赖,因为稍后需要使用其 @RefreshScope 注解来重载 Environment 中的属性源: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> <version>3.1.5</version> </dependency> 还必须在项目 pom.xml 文件的 <dependencyManagement> 中添加 Spring Cloud 的 BOM,以便 Maven 使用兼容版本的 spring-cloud-starter: <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2021.0.5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 最后,由于我们需要在运行时重新加载文件的功能,所以还要添加 commons-configuration 依赖:

在 Spring Boot 中使用 Gson 替换 Jackson

GSON 是由谷歌开源的一款 Java JSON 库。特点是轻量,只有一个 JAR,无任何其他依赖。高性能,支持以流式进行序列化/反序列化。并且抽象了基本的 JsonElement、JsonObject、JsonArray、JsonPrimitive 和 JsonNull,可以在无自定义 Java 对象的情况下构建、解析 JSON 对象。 本文将会指导你如何在 Spring Boot 中使用 Gson 代替默认的 Jackson 作为 JSON 序列化/反序列化框架。 添加依赖 在 pom.xml 中添加依赖。 gson 的版本已经被 Spring Boot 管理,所以不需要声明版本号。 <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> </dependency> 由于 Spring Boot 默认使用 Jackson,所以很多 Spring Boot 的组件、框架默认也会选择用 Jackson 作为 JSON 库。如果你确认项目中,没有其他地方使用到了 Jackson,那么可以从依赖中排除它。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> </exclusion> </exclusions> </dependency> 并且,在 @SpringBootApplication 注解中,排除掉 Jackson 的自动装配。 @SpringBootApplication(exclude = { JacksonAutoConfiguration.class }) 配置属性 在 application.

给 RestTemplate 配置 SSL 证书来访问 HTTPS REST 服务

1、概览 在本教程中,我们将学习如何给 RestTemplate 配置 SSL 证书来访问 HTTPS 加密的 REST 服务。 2、设置 要确保 REST 服务的安全,我们需要使用证书和由证书生成的 Keystore。 证书可以从 CA 获取,在本文的示例中,使用的是自签名证书。 我们将使用 Spring 的 RestTemplate 来访问 HTTPS REST 服务。 首先,让我们创建一个 Controller 类 WelcomeController 和一个 /welcome 端点(返回一个简单的字符串响应): @RestController public class WelcomeController { @GetMapping(value = "/welcome") public String welcome() { return "Welcome To Secured REST Service"; } } 然后,在 src/main/resources 文件夹中添加我们的 keystore: src/main/resources |-keystore |-baeldung.p12 接下来,在 application.properties 文件中添加与 Keystore 相关的属性: server.port=8443 server.servlet.context-path=/ # keystore 的格式 server.

Spring Boot 中的枚举(Enum)映射

1、概览 在本教程中,我们将学习如何在 Spring Boot 中实现不区分大小写的枚举映射。 2、Spring 默认的枚举映射 在处理请求参数时,Spring 依靠几个内置 Converter 来处理字符串转换。 通常情况下,将枚举作为请求参数时,默认会使用 StringToEnumConverterFactory 将传递的字符串转换为枚举。 该 Converter 会调用 Enum.valueOf(Class, String),这意味着给定的字符串必须要完全匹配枚举中的常量实例。 例如,让我们来看看 Level 枚举: public enum Level { LOW, MEDIUM, HIGH } 接下来,创建一个使用枚举作为参数的 Handler Method: @RestController @RequestMapping("enummapping") public class EnumMappingController { @GetMapping("/get") public String getByLevel(@RequestParam(required = false) Level level){ return level.name(); } } 使用 CURL 向 http://localhost:8080/enummapping/get?level=MEDIUM 发送一个请求: curl http://localhost:8080/enummapping/get?level=MEDIUM Handler Method 会返回 MEDIUM,即枚举实例 MEDIUM 的名称(name())。 现在,让我们传递 medium,看看会发生什么: curl http://localhost:8080/enummapping/get?level=medium {"timestamp":"2022-11-18T18:41:11.440+00:00","status":400,"error":"Bad Request","path":"/enummapping/get"} 如你所见,返回了无效请求异常:

覆盖 Spring Cloud Config 中的远程属性值

1、概览 Spring Cloud Config 是 Spring Cloud 全家桶的一个子项目。它通过集中式独立的服务来管理各个服务的配置。Spring Cloud Config 拥有自己的属性管理库,但也可以集成 Git、Consul 和 Eureka 等开源项目。 在本文中,我们将了解在 Spring Cloud Config 中覆盖远程属性值的不同方法,以及 Spring 从 2.4 版本开始强制实施的限制,以及 3.0 版本中的变化。在本教程中,我们使用 Spring Boot 2.7.2。 2、创建 Spring Config Server 使用 Spring Cloud Config 创建外部化的配置服务器。 2.1、创建配置文件 在 application.properties 文件中定义的配置与所有客户端应用共享。也可以为指定应用或指定 Profile 定义特定配置。 首先,创建一个配置文件,其中包含为客户端应用提供的属性。 客户端应用命名为 baeldung,在 /resources/config 文件夹中创建 baeldung.properties 文件。 2.2、添加属性 在 baeldung.properties 文件中添加一些属性,然后在客户端应用中使用这些属性: hello=Hello Jane Doe! welcome=Welcome Jane Doe! 还要在 resources/config/application.properties 文件中添加一个共享属性,Spring 将在所有客户端中共享该属性: shared-property=This property is shared accross all client applications 2.