教程

在 Spring Boot Properties/Yaml 文件中使用环境变量

1、概览 本文介绍了如何在 Spring Boot 的 application.properties 和 application.yml 中使用环境变量,以及如何在代码中使用这些属性。 2、在 application.properties 文件中使用环境变量 定义一个名为 JAVA_HOME 的全局环境变量,其值为 C:\Program Files\Java\jdk-11.0.14。 要在 Spring Boot 的 application.properties 中使用该变量,需要用大括号将其包裹起来: java.home=${JAVA_HOME} 也可以以同样的方式使用系统属性(System Properties)。例如,在 Windows 系统中,默认情况下会定义操作系统属性: environment.name=${OS} 还可以组合多个变量值。定义另一个环境变量 HELLO_BAELDUNG,其值为 Hello Baeldung。现在可以将两个变量连接起来: baeldung.presentation=${HELLO_BAELDUNG}. Java is installed in the folder: ${JAVA_HOME} baeldung.presentation 属性值现在为:Hello Baeldung. Java is installed in the folder: C:\Program Files\Java\jdk-11.0.14. 3、在代码中使用特定环境属性 启动 Spring Context 后,就可以在代码中注入属性值。 3.1、使用 @Value 注入属性值 可以使用 @Value 注解在 setter 方法、构造器和字段上进行注入: @Value("${baeldung.presentation}") private String baeldungPresentation; 3.2、从 Spring Environment 获取值 还可以通过 Spring 的 Environment 获取属性值。

Spring Boot 3 和 Spring Framework 6.0 - 新功能

1、概览 本文简单地介绍了 Spring Boot 3 和 Spring Framework 6.0 中的新特性。 2、Java 17 之前已经支持Java 17,现在这个 LTS 版本成为基线版本。 由于 Java 本身不是本文的主题,这里只会列举对 Spring Boot 开发人员最重要的新特性。 2.1、Record Java Record(JEP 395),是一种快速创建数据类(Data Class)方式,即那些目的仅仅是包含数据并在模块之间传递数据的类,也被称为 POJO(Plain Old Java Objects,简单Java对象)和 DTO(Data Transfer Objects,数据传输对象)。 使用 Record 可以轻松创建不可变的 DTO: public record Person (String name, String address) {} 目前,在将它们与 Bean Validation 结合使用时,需要小心,因为构造函数参数不支持验证约束,例如在 Controller 方法中的 JSON 对象。 2.2、字符块 通过 JEP 378,现在就可以创建多行文本块,而无需在换行时连接字符串: String textBlock = """ Hello, this is a multi-line text block. """; 2.

Spring Boot 整合 Redisson

Redisson 是一个功能十分强大的 Redis Java 客户端,它提供了丰富的功能和API,支持同步和异步操作,以及 RxJava 和响应式编程模型。Redisson 提供了50多个基于 Redis 的 Java 对象和服务,包括 分布式锁、原子计数器、分布式集合(Set、Map、List、Queue) 等高级功能。它还还支持本地缓存和 RPC 调用等功能,是开发分布式应用和使用 Redis 的理想选择。 总之,Redisson 所提供的功能已经远远超出了一个 Redis 客户端的范畴,Redis 官方也 推荐使用它 作为 Java 的 Redis 客户端。 之前我们介绍过 如何在 Spring Boot 中整合、使用 Redis。我们用到了 Spring Data Redis 组件,这是由 Spring 提供的抽象,可以使用 Jedis、Lettuce 等客户端作为实现。 Redisson 官方提供了一个 redisson-spring-boot-starter 组件,它正是 Spring Data Redis 抽象的实现,也就是说,我们可以直接使用 redisson-spring-boot-starter 无缝替换 spring-boot-starter-data-redis。 本文将会带你了解如何在 Spring Boot 中通过 redisson-spring-boot-starter 整合、使用 Redisson。 整合 Redisson 添加依赖 添加 redisson-spring-boot-starter 依赖即可。 <!-- https://mvnrepository.com/artifact/org.redisson/redisson-spring-boot-starter --> <dependency> <groupId>org.

Spring OpenFeign 的异常处理

1、概览 微服务间的 HTTP API 调用可能会出现异常。在 Spring Boot 中使用 OpenFeign 时,默认会把下游服务的 “Not Found” 等异常全部当做 “Internal Server Error” 响应给客户端。这并不是异常的最佳处理方式,幸而,Spring 和 OpenFeign 都提供了一些机制,允许我们自定义异常处理。 本文将带你了解,Spring Boot 和 OpenFeign 默认的异常传播、处理机制,以及如何实现自定义的异常处理。 2、默认的异常传播策略 2.1、Feign 中默认的异常传播 Feign 使用 ErrorDecoder.Default 内部实现类进行异常处理。每当 Feign 收到任何非 2xx 状态码时,都会将其传递给 ErrorDecoder 的 decode 方法。 如果 HTTP 响应有 Retry-After 头信息,decode 方法就会返回 RetryableException,否则就会返回 FeignException。 重试时,如果请求在默认重试次数之后仍然失败,则会返回 FeignException。 decode 方法将 HTTP 方法 key 和响应存储在 FeignException 中。 2.2、Spring Rest Controller 中的默认异常传播 只要 RestController 收到任何未处理的异常,它就会向客户端返回 500 Internal Server Error(内部服务器错误)响应。 该异常响应包含时间戳、HTTP 状态码、异常信息和路径等信息:

构建自己的 Spring Initializr 服务

Spring Initializr 是 Spring 官方提供的一个用于快速创建和初始化 Spring 项目的在线工具。它可以让开发人员选择所需的 Spring 模块、版本、语言(Java、Kotlin 或 Groovy)和构建工具(Maven 或 Gradle),并生成一个基本的项目结构。现在大多数 IDE 都对 Spring Initializr 提供了支持! 官方的 Spring Initializr 服务(start.spring.io)部署在海外,在国内访问经常出现各种连网络接失败的问题。好在 Spring Initializr 是一个开源的项目,我们可以用它来构建自己的 Spring Initializr 服务。 Spring Initializr Github 仓库:https://github.com/spring-io/start.spring.io 构建 Spring Initializr 服务 Clone 项目 需要先在机器上安装 git 软件。 git clone https://github.com/spring-io/start.spring.io.git 该仓库下有三个工程,我们只关心其中2个: start-client 前端工程,使用 React 开发。 start-site 后端工程,是一个 Spring Boot 应用。 执行构建 项目使用 maven 构建,且提供了 mvnw(Maven Wrapper) 脚本,它是一个用于管理和运行 Maven 项目的工具。它的作用是在没有全局安装 Maven 的情况下,通过自动下载和配置特定版本的 Maven 来确保项目的构建和运行环境一致性。也就是说 不需要在本地安装 Maven,通过此脚本即可完成构建。 进入项目根目录,执行如下命令进行自动构建:

Swagger 中的 @Operation 和 @ApiResponse 注解

1、概览 本文将带你了解 Swagger 中 @Operation 和 @ApiResponse 注解的主要区别和应用场景。 2、用 Swagger 生成文档 Swagger 是一套围绕 OpenAPI 规范构建的开源工具,用于描述整个 API,如暴露的端点、操作、参数、验证方法等。 Swagger 提供了 @Operation 和 @ApiResponse 注解,用于描述 REST API,以及 REST API 的响应。 定义一个示例 Controller: @RestController @RequestMapping("/customers") class CustomerController { private final CustomerService customerService; public CustomerController(CustomerService customerService) { this.customerService = customerService; } @GetMapping("/{id}") public ResponseEntity<CustomerResponse> getCustomer(@PathVariable("id") Long id) { return ResponseEntity.ok(customerService.getById(id)); } } 3、@Operation @Operation 注解用于描述单个操作。 @Operation(summary = "Gets customer by ID", description= "Customer must exist") @GetMapping("/{id}") public ResponseEntity<CustomerResponse> getCustomer(@PathVariable("id") Long id) { return ResponseEntity.

Spring Security 中 permitAll() 和 anonymous() 的区别

1、概览 Web 应用中,有些资源只能被已登录(认证)的的用户访问。有些资源,可以被匿名用户访问。而有些资源,甚至只能被匿名用户访问,已登录的用户不能访问。 本文将带你了解 Spring Security 中 HttpSecurity 的 permitAll() 和 anonymous() 方法之间的区别以及如何通过这两个方法实现上述的权限设计。 2、权限设计 假如,我们有一个电商网站,权限设计如下: 匿名用户和已登录的用户均可查看网站上的商品。 需要审计匿名用户和已登录用户请求。 匿名用户可以访问用户注册页面,已经登录的用户则不能访问。 只有已登录的用户才能查看其购物车。 3、Controller 和 WebSecurity 配置 定义 Controller: @RestController public class EcommerceController { @GetMapping("/private/showCart") public @ResponseBody String showCart() { return "Show Cart"; } @GetMapping("/public/showProducts") public @ResponseBody String listProducts() { return "List Products"; } @GetMapping("/public/registerUser") public @ResponseBody String registerUser() { return "Register User"; } } 接下来在 EcommerceWebSecruityConfig 类中实现上述权限设计: @Configuration @EnableWebSecurity public class EcommerceWebSecurityConfig { @Bean public InMemoryUserDetailsManager userDetailsService(PasswordEncoder passwordEncoder) { UserDetails user = User.

在 Spring Boot 中整合、使用 Redis

Redis 是一款开源的,使用 C 开发的高性能内存 Key/Value 数据库,支持 String、Set、Hash、List、Stream 等等数据类型。它被广泛用于缓存、消息队列、实时分析、计数器和排行榜等场景。基本上是当代应用中必不可少的软件! Spring Boot 对 Redis 提供了开箱即用的组件:spring-boot-starter-data-redis。通过这个 starter,我们只需要几行简单的配置就可以快速地在 Spring Boot 中整合、使用 Redis。 Spring Boot 整合 Redis Maven 依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> 除了 spring-boot-starter-data-redis 外,还添加了 commons-pool2 依赖,是因为我们需要使用到连接池。 配置属性 只需要在 application.yaml | properties 中配置如下常用的基本属性即可: spring: data: redis: # 连接地址 host: "localhost" # 端口 port: 6379 # 数据库 database: 0 # 用户名,如果有 # username: # 密码,如果有 # password: # 连接超时 connect-timeout: 5s # 读超时 timeout: 5s # Lettuce 客户端的配置 lettuce: # 连接池配置 pool: # 最小空闲连接 min-idle: 0 # 最大空闲连接 max-idle: 8 # 最大活跃连接 max-active: 8 # 从连接池获取连接 最大超时时间,小于等于0则表示不会超时 max-wait: -1ms 注意,如果你使用的是 spring boot 2.

Swagger:同一状态码返回不同的 Response 对象

1、概览 本文介绍了如何在 API 规范中,为同一个响应定义多个不同的对象,以及如何使用该规范生成 Java 代码和 Swagger 文档。 2、问题陈述 定义两个对象(object)。 Car 对象的属性是 owner 和 plate,两者都是 String。 Bike 对象的属性是 owner 和 speed,speed 是一个 Integer。 它们在 OpenAPI 中的描述如下: Car: type: object properties: owner: type: string plate: type: string Bike: type: object properties: owner: type: string speed: type: integer 我们想描述一个 /vehicle 端点,它将接受 GET 请求,并能返回一个 Car 或一个 Bike。 类似于如下描述: paths: /vehicle: get: responses: '200': # 返回 Car 或 Bike 接下来介绍在 OpenAPI 2 和 3 规范中的不同实现方式。

Feign Client 异常处理

1、概览 在 Feign 客户端 中,可以使用 ErrorDecoder 或者 FallbackFactory 来处理异常。 2、Maven 依赖 创建一个 Spring Boot 项目,添加 spring-cloud-starter-openfeign 依赖,该 starter 已经包含了 feign-core 依赖。 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>3.1.3</version> </dependency> 如果你想自定义要使用的 feign-core 的版本,你也可以手动在 pom.xml 文件中添加 feign-core 依赖: <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-core</artifactId> <version>11.9.1</version> </dependency> 3、使用 ErrorDecoder 处理异常 通过自定义 ErrorDecoder 来处理异常,可以在出现异常时返回自定义的异常。 如下: public class RetreiveMessageErrorDecoder implements ErrorDecoder { private final ErrorDecoder errorDecoder = new Default(); @Override public Exception decode(String methodKey, Response response) { ExceptionMessage message = null; try (InputStream bodyIs = response.