Spring 中的 @RequestParam 注解

1、概览 本文将带你了解 Spring 中 @RequestParam 注解的用法。 简单地说,可以使用 @RequestParam 从请求中提取查询参数、表单参数甚至是多个参数。 2、示例端点 假设我们有一个端点 /api/foos,它接受一个名为 id 的查询参数: @GetMapping("/api/foos") @ResponseBody public String getFoos(@RequestParam String id) { return "ID: " + id; } 在本例中,使用 @RequestParam 来提取 id 查询参数。 通过 GET 请求来调用 getFoos: http://localhost:8080/spring-mvc-basics/api/foos?id=abc ---- ID: abc 接下来,看看注解的属性:name、value、required 和 defaultValue。 3、指定请求参数名称 在上一个示例中,变量名和参数名都是相同的。 如果变量名称和参数名称不同,可以使用 name 属性配置 @RequestParam 名称: @PostMapping("/api/foos") @ResponseBody public String addFoo(@RequestParam(name = "id") String fooId, @RequestParam String name) { return "ID: " + fooId + " Name: " + name; } 也可以使用 @RequestParam(value = "id") 或直接使用 @RequestParam("id")。

Spring Boot 中的数据校验

1、概览 Spring Boot 通过 Hibernate Validator(Bean Validation 的实现)对数据验证提供了强大的支持。 本文将通过一个实际的 REST 应用带你了解如何在 Spring Boot 中校验数据。 2、Maven 依赖 在 pomx.ml 中添加 spring-boot-starter-web、spring-boot-starter-jpa 和 H2 database 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.1.214</version> <scope>runtime</scope> </dependency> 从 Boot 2.3 开始,还需要明确添加 spring-boot-starter-validation 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> 3、示例 Domain 类 定义一个 JPA 实体类,User: @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @NotBlank(message = "Name is mandatory") private String name; @NotBlank(message = "Email is mandatory") private String email; // 构造函数、Set、Set 方发省略 } User 实体类很简单,它展示了如何使用 Bean Validation 的约束来限制 name 和 email 字段。

Spring Data JPA 获取最后一条记录

1、概览 本文将带你了解使用 Spring Data JPA 获取最后一条记录的多种方式。 2、初始设置 首先,创建并初始化要查询的表。 创建一个 Post 实体类: @Entity public class Post { @Id private Long id; private String title; private LocalDate publicationDate; // get、set 方法 } @Entity 表示注解的类代表数据库中的一个表。@Id 注解定义了主键。 为了简单起见,这里使用的是 H2 内存数据库。 添加一个基本的 SQL 脚本,创建 Post 类对应的 post 表: DROP TABLE IF EXISTS post; CREATE TABLE post( id INT PRIMARY KEY, title VARCHAR(200), publication_date DATE ) 接着,添加一些数据: INSERT INTO post (id, title, publication_date) VALUES(1, 'Facebook post', '2020-11-10'); INSERT INTO post (id, title, publication_date) VALUES(2, 'Instagram post', '2020-12-24'); INSERT INTO post (id, title, publication_date) VALUES(3, 'Twitter post', '2023-01-10'); INSERT INTO post (id, title, publication_date) VALUES(4, 'tiktok post', '2023-03-18'); INSERT INTO post (id, title, publication_date) VALUES(5, 'Pinterest post', '2023-09-09'); 如你所见,最后一条记录的 ID 是 5。

Spring Cloud OpenFeign 入门

1、概览 本文将带你了解 Spring Boot 应用中的声明式 REST 客户端 - Spring Cloud OpenFeign。 Feign 通过可插拔的注解支持(包括 Feign 注解和 JAX-RS 注解)使编写 Web 客户端更加容易。 此外,Spring Cloud 还增加了对 Spring MVC 注解和使用与 Spring Web 中相同的 HttpMessageConverter 的支持。 使用 Feign 的一个好处是,除了接口定义外,无需编写任何调用服务的代码。 2、依赖 首先,创建 Spring Boot Web 项目,并在 pom.xml 文件中添加 spring-cloud-starter-openfeign 依赖: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> 此外,还需要添加 spring-cloud-dependencies 依赖: <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 你可以在 Maven Central 上找到 spring-cloud-starter-openfeign 和 spring-cloud-dependencies 的最新版本。 3、Feign 客户端 接着,需要将 @EnableFeignClients 添加到 main 类中:

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.