教程

Spring 重新加载 Properties 属性

1、概览 本文将带你了解如何在 Spring 中重新加载 Properties 配置属性。 2、Spring 读取 Properties Spring 有几种不同的方式来访问 Properties: Environment - 可以注入 Environment,然后使用 Environment#getProperty 来读取给定的属性。Environment 包含不同的属性源,如系统属性(System Properties)、-D 参数和 application.properties(或者 .yml) 等。还可以使用 @PropertySource 将额外的属性源添加到 Environment 中。 Properties - 可以将 properties 文件加载到 Properties 实例中,然后在 Bean 中通过调用 properties.get("property") 使用它。 @Value - 可以使用 @Value(${'property'}) 注解在 Bean 中注入特定属性。 @ConfigurationProperties - 可以使用 @ConfigurationProperties 在 Bean 中加载层次化的属性。。 3、重新加载外部属性文件 要在运行时更改文件中的属性(Properties),应该将该文件放在 Jar 之外的某个地方。然后使用命令行参数 -spring.config.location=file://{文件路径} 告诉 Spring 文件的位置。或者,也可以将其放在 application.properties 中。 对于基于磁盘文件的 Properties,可以开发一个端点或定时任务来读取文件并更新 Properties。 Apache 的 commons-configuration 是一个用于重新加载属性文件的库。可以使用 PropertiesConfiguration 和不同的 ReloadingStrategy 。

自定义 Spring Cloud Gateway 过滤器(Filter)

1、概览 上一篇文章《Spring Cloud Gateway 教程》中介绍了 Spring Cloud Gateway 网关框架。本文将带你了解如何在 Spring Cloud Gateway 中自定义 Filter。以及如何在 Filter 中修改请求和响应数据。 2、项目设置 创建一个基本应用,并将其用作 API 网关。 2.1、Maven 配置 在使用 Spring Cloud 时,往往通过 <dependencyManagement> 来管理组件的版本: <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 添加 Spring Cloud Gateway,无需指定使用的实际版本: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> 最新的 Spring Cloud 版本可通过 Maven Central 中找到。当然,需要注意使用的 Spring Cloud 版本需要与 Spring Boot 版本兼容。 2.2、API 网关配置 假设 API 服务在本地 8081 端口运行,在 /resource 端点暴露了一个简单的字符串资源。 接下来,配置网关,把请求代理到该服务。简而言之,当请求网关的 URI 路径中带有 /service 前缀的请求时,网关将把请求转发给该服务。

Reactor WebFlux 与虚拟线程(Virtual Thread)的对比

1、概览 本文将带你了解 Java 19 的 虚拟线程 和 Reactor Webflux 的基本工作原理以及它们的优缺点。 2、代码示例 假如我们开发的是一个电商后台,有如下 “负责计算和发布添加到购物车中的商品价格” 的函数。 class ProductService { private final String PRODUCT_ADDED_TO_CART_TOPIC = "product-added-to-cart"; private final ProductRepository repository; private final DiscountService discountService; private final KafkaTemplate<String, ProductAddedToCartEvent> kafkaTemplate; // 构造函数 public void addProductToCart(String productId, String cartId) { Product product = repository.findById(productId) .orElseThrow(() -> new IllegalArgumentException("not found!")); Price price = product.basePrice(); if (product.category().isEligibleForDiscount()) { BigDecimal discount = discountService.discountForProduct(productId); price.setValue(price.getValue().subtract(discount)); } var event = new ProductAddedToCartEvent(productId, price.

使用 Zuul 作为代理访问 Spring REST 服务

1、概览 本文将带你了解如何在 UI (前端)应用中使用 Zuul 作为代理与 Spring REST 服务通信,使用 Zuul 代理的目的是为了统一处理 CORS 和 Same Origin Policy 问题。 Zuul 是 Netflix 基于 JVM 的路由和服务器端负载均衡器。Spring Cloud 与嵌入式 Zuul 代理进行了很好的集成。 2、Maven 配置 首先,在 UI 应用的 pom.xml 中添加 Spring Cloud Zuul 依赖: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> <version>2.2.0.RELEASE</version> </dependency> 最新版本可在 此处 找到。 3、Zuul Properties 接着,在 application.yml 中对 Zuul 进行配置: zuul: routes: foos: path: /foos/** url: http://localhost:8081/spring-zuul-foos-resource/foos 如上: 代理了资源服务器 Foos UI 应用上所有以 /foos/ 开头的请求都将转发到 Foos 资源服务器 http://loclahost:8081/spring-zuul-foos-resource/foos/ 4、API API 是一个简单的 Spring Boot 应用,监听 8081 端口。

Spring Boot 整合使用 H2 内存数据库

1、概览 本文将带你了解如何在 Spring Boot 中使用 H2 内存数据库。与其他数据库一样,Spring Boot 生态系统对 H2 提供了开箱即用的支持。 2、依赖 添加 h2 和 spring-boot-starter-data-jpa 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> 3、Datasource 配置 默认情况下,Spring Boot 会配置应用使用用户名 sa 和空密码连接到内存数据库。 不过,你也可以通过在 application.properties 文件中添加以下属性来更改这些参数: spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 相应的 YAML 配置如下: spring: datasource: url: jdbc:h2:mem:mydb username: sa password: password driverClassName: org.h2.Driver jpa: spring.jpa.database-platform: org.hibernate.dialect.H2Dialect 内存数据库会在应用重启后会丢失数据,可以通过使用基于文件的存储来改变这种行为。 更新 spring.datasource.url 属性: spring.datasource.url=jdbc:h2:file:/data/demo 相应的 YAML 配置如下: spring: datasource: url: jdbc:h2:file:/data/demo H2 数据库还可以在 其他模式 下运行。

Spring Bean 注解

1、概览 本文将带你了解最常见的 Spring Bean 注解,用于定义不同类型的 Bean。 在 Spring 容器中配置 Bean 有几种方法。可以使用 XML 配置声明,也可以在配置类中使用 @Bean 注解声明 Bean。 最后,还可以使用 org.springframework.stereotype 包中的注解来标记类,然后由组件扫描来处理。 2、组件扫描 如果启用了组件扫描,Spring 就可以自动扫描包中的 Bean。 通过 @ComponentScan 注解配置要扫描的包,以查找带有注解配置的类。可以使用 basePackages 或 value 参数(value 是 basePackages 的别名)指定 base package: @Configuration @ComponentScan(basePackages = "com.baeldung.annotations") class VehicleFactoryConfig {} 还可以使用 basePackageClasses 参数指定 base package 中的类: @Configuration @ComponentScan(basePackageClasses = VehicleFactoryConfig.class) class VehicleFactoryConfig {} 这两个参数都是数组,因此可以为每个参数指定多个 package。 如果没有指定参数,将从 @ComponentScan 注解类所在的同一个包中开始扫描。 @ComponentScan 利用了 Java 8 的重复注解功能,这意味着可以多次使用它来标记一个类: @Configuration @ComponentScan(basePackages = "com.baeldung.annotations") @ComponentScan(basePackageClasses = VehicleFactoryConfig.

Spring Data 注解

1、简介 Spring Data 提供了对数据存储技术的抽象。因此,我们的业务逻辑代码可以更加独立于底层持久化实现。而且,Spring 还简化了处理与数据存储相关的实现细节的过程。 本文将带你了解 Spring Data、Spring Data JPA 和 Spring Data MongoDB 项目中最常见的注解。 2、常见的 Spring Data 注解 2.1、@Transactional @Transactional 用于定义事务方法: @Transactional void pay() {} 如果在类上应用此注解,那么它就会对类中的所有方法起作用。也可以在方法上定义此注解来进行覆盖。 2.2、@NoRepositoryBean 有时我们会通过一个基本的 Repository 接口,定义一些通用的方法。然后,所有的 Repository 来继承这个基本的 Repository 接口。 基本的 Repository 接口不应该被实例化为 Bean,所以可以使用 @NoRepositoryBean 注解进行标注。 例如,如果想在所有 Repository 中使用 Optional<T> findById(ID id) 方法,那么可以创建一个基础 Repository 接口: @NoRepositoryBean interface MyUtilityRepository<T, ID extends Serializable> extends CrudRepository<T, ID> { Optional<T> findById(ID id); } 此注解不会影响子接口,因此 Spring 将会把下面 Repository 接口创建为 Bean:

Spring 定时任务注解

1、概览 本文将带你了解 org.springframework.scheduling.annotation 包中和调度相关的注解。 2、@EnableAsync 注解用于在 Spring 中启用异步功能。 必须与 @Configuration 一起使用: @Configuration @EnableAsync class VehicleFactoryConfig {} 启用了异步调用后,可以使用 @Async 来定义支持异步调用的方法。 3、@EnableScheduling @EnableScheduling 用于启用定时任务调度。同样,必须与 @Configuration 结合使用: @Configuration @EnableScheduling class VehicleFactoryConfig {} 启用了定时调度后,就可以可以使用 @Scheduled 注解来定期运行方法。 4、@Async @Async 用于注解需要异步执行的方法。 @Async void repairCar() { // ... } 如果将此注解应用于一个类,那么所有方法都将被异步调用。 注意,需要通过 @EnableAsync 或 XML 配置来启用异步调用,此注解才会生效。 5、@Scheduled 如果需要定期执行一个方法,可以使用此注解: @Scheduled(fixedRate = 10000) void checkVehicle() { // ... } 可以使用它来按固定间隔执行方法,或者可以使用类似 cron 的表达式进行微调。 @Scheduled 利用了 Java 8 的重复注解功能,这意味着可以多次使用它来标记一个方法: @Scheduled(fixedRate = 10000) @Scheduled(cron = "0 * * * * MON-FRI") void checkVehicle() { // .

Spring Boot 注解

1、概览 Spring Boot 的自动配置功能让配置 Spring 变得更容易。 本文将带你了解 org.springframework.boot.autoconfigure 和 org.springframework.boot.autoconfigure.condition 包中的核心注解。 2、@SpringBootApplication 使用此注解来标记 Spring Boot 应用的 main 类: @SpringBootApplication class VehicleFactoryApplication { public static void main(String[] args) { SpringApplication.run(VehicleFactoryApplication.class, args); } } @SpringBootApplication 封装了 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 注解,均为默认属性。 3、@EnableAutoConfiguration @EnableAutoConfiguration 顾名思义就是启用自动配置。这意味着 Spring Boot 会在其 classpath 上查找自动配置 Bean,并自动应用它们。 注意,必须将此注解与 @Configuration 一起使用: @Configuration @EnableAutoConfiguration class VehicleFactoryConfig {} 4、自动配置的条件注解 通常,在编写自定义自动配置时,我们希望 Spring 有条件地使用它们。这可以通过本节中的注解来实现这一目标。 可以将本节中的注解放在 @Configuration 类或 @Bean 方法上。 4.1、@ConditionalOnClass 和 @ConditionalOnMissingClass 只有注解参数中的类存在/不存在时,Spring 才会使用标记的自动配置 Bean:

Spring Web 注解

1、概览 本文将带你了解 org.springframework.web.bind.annotation 包中的 Spring Web 注解。 2、@RequestMapping 简单地说,@RequestMapping 注解用于标记 @Controller 类中的请求处理方法(Handler),可配置的属性如下: path 或其别名 name 和 value:方法映射到的 URL method:支持的 HTTP 方法 params:内容协商,根据 HTTP 参数的有无或值匹配请求 headers:内容协商,根据 HTTP Header 的存在、缺失或值匹配请求 consumes:支持的请求媒体类型(Content-Type) produces:响应的媒体类型 示例如下: @Controller class VehicleController { @RequestMapping(value = "/vehicles/home", method = RequestMethod.GET) String home() { return "home"; } } 在 @Controller 类的类级应用此注解,就能为类中的所有 Handler 方法提供默认设置。唯一的例外是 URL,Spring 不会在方法级设置覆盖 URL,而是将两个 path 部分拼接在一起。 例如,以下配置与上述配置效果相同: @Controller @RequestMapping(value = "/vehicles", method = RequestMethod.GET) class VehicleController { @RequestMapping("/home") String home() { return "home"; } } 此外,@GetMapping、@PostMapping、@PutMapping、@DeleteMapping 和 @PatchMapping 是 @RequestMapping 的不同变体,其 HTTP 方法已分别设置为 GET、POST、PUT、DELETE 和 PATCH。