教程

Feign 客户端设置 Oauth2 Token

1、概览 OpenFeign 是一个可以在 Spring Boot 中使用的声明式 REST 客户端。 假如想通过 OpenFeign 来调用使用 OAuth2 的 REST API,那么就需要给 OpenFeign 设置 Access Token。 本文将会带你了解如何为 OpenFeign 客户端添加 OAuth2 支持。 2、服务之间的认证 服务之间的认证 API 安全中的一个热门话题。我们可以使用 mTLS 或 JWT 为 REST API 提供认证机制。不过,OAuth2 协议是保护 API 的事实解决方案。假设我们想使用另一个服务(客户端)调用一个受保护的服务(服务器)。在这种情况下,使用 “客户端凭证(client credential)” 授权方式。这种授权方式通常用于在两个没有终端用户的 API 或系统之间进行身份认证。 下图显示了这种授权模式中的的主要角色关系: 在客户端凭证模式中,客户端通过 Token Endpoint 从授权服务器(Authorization Server)获取 Access Token。然后,客户端使用 Access Token 访问源服务器(Resource Server)上受资保护的资源。资源服务器会验证 Access Token,如果有效,则为请求提供服务。 2.1、授权服务器 创建一个授权服务器来发放 Access Token。为了方便,我们在 Spring Boot 中使用嵌入式 Keycloak。假设我们使用 GitHub 上的 授权服务器 项目。 首先,在嵌入式 Keycloak 服务器的 realm 管理中定义 Payment-app 客户端:

Swagger 记录包含枚举(Enum)参数的文档

1、概览 本文将带你了解如何使用 swagger-maven-plugin 来在 Swagger 中记录枚举,并在 Swagger 编辑器中验证生成的 JSON 文档。 2、Swagger 是啥? Swagger 是一种开源工具,用于定义基于 REST 的 API。在当今世界,大多数组织都在向微服务和 API 优先的方向发展。Swagger 在设计和记录 API 方面非常方便。它还提供了 Swagger 编辑器、Swagger UI 和 Swagger CodeGen 等各种工具来协助 API 开发。 此外,Swagger 是 OpenAPI 规范或 OAS 的一种实现,OAS 定义了一套用于开发 REST API 的标准,有助于全球各地的组织将编写 API 的过程标准化。 我们应用生成的 JSON 文件也将遵循 OpenAPI 规范。 在 Swagger 中使用 Enum 是个有必要的,有些 API 需要用户只能使用一组特定的预定义值。这些预定义的常量值被称为枚举(Enum)。同样,当 Swagger 公开 API 时,需要要确保用户从这组预定义值中选择一个值,而不是任意的值。 换句话说,需要在 swagger.json 文件中记录枚举,让用户知道可选的选项。 3、实现 实现一个 POST API,用于为组织招聘特定角色的员工(Employee)。角色只能是以下角色之一:Engineer、Clerk、Driver 或 Janitor。 创建 Role 枚举,其中包含 Employee 角色的所有可能值,然后创建一个 Employee 类,将角色作为其属性之一。

Spring Data JPA 对共享锁和独占锁的支持

简介 本文将会带你了解 Spring Data JPA 对锁的支持,以及如何在检索时使用共享锁或者独占锁。 JPA LockModeType JPA 提供了几种加锁的选项,可以在获取实体时通过 LockModeType 枚举来指定。 如下: LockModeType.PESSIMISTIC_READ 可对相关表记录加共享锁或读锁。 LockModeType.PESSIMISTIC_WRITE 可对相关表记录加速独占锁或写锁。 如果底层数据库不支持共享锁,那么 PESSIMISTIC_READ 策略将退回到 PESSIMISTIC_WRITE,因为该选项已被广泛支持。 根据 ID 获取实体时加锁 JPA EntityManager 提供了一个 find 方法的重载,可以传递 LockModeType 采参数。用于在获取实体时上锁: Post post = entityManager.find(Post.class, id, lockMode); Spring Data JpaRepository 未提供此选项,但我们可以使用自定义 Spring Data Repository 来实现。 例如,可以让 PostRepository 继承 JpaRepository,CustomPostRepository: @Repository public interface PostRepository extends JpaRepository<Post, Long>, CustomPostRepository { } In the CustomPostRepository interface, we can define a lockById method like this:

在 Spring Boot 中整合 MyBatis Plus

MyBatis Plus 是 MyBatis 框架的一个增强。除了基本的 MyBatis 功能外,它还提供了快速的 CURD 方法,以及投影查询、分页查询、动态条件等等功能,极大的提高了开发效率。 本文将会通过案例教你如何在 Spring Boot 中整合 MyBatis Plus。 文中使用的软件版本如下: Spring Boot:3.0.3 MySQL:8.0.0 MyBatis Plus:3.5.4 初始化演示数据 首先在本地数据库执行以下 SQL 脚本,创建一张名为 t_user 的数据表: CREATE TABLE `t_user` ( `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `enabled` tinyint unsigned NOT NULL COMMENT '是否启用。0:禁用,1:启用', `name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '名字', PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户'; 然后再执行如下脚本,创建初始记录:

Spring Security 配置不同 URL 的认证和授权规则

1、概览 本文将带你了解如何在 Spring Security 中针对不同的 URL 进行不同的安全配置。 2、设置 创建应用,在 pom.xml 中添加 Web 和 Security 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> 3、创建 API 创建一个包含两个 API 的 RESTful 服务:Product(产品) API 和 Customer(客户) API。 3.1、Product API 创建 ProductController。它包含一个 getProducts 方法,该方法返回产品列表: @RestController("/products") public class ProductController { @GetMapping public List<Product> getProducts() { return new ArrayList<>(Arrays.asList( new Product("Product 1", "Description 1", 1.0), new Product("Product 2", "Description 2", 2.0) )); } } 3.2、Customer API 同样,定义 CustomerController:

Spring Cloud Gateway 重写 URL

1、简介 Spring Cloud Gateway 的常见用例是作为一个网关,代理一个或多个服务,从而为客户端提供更简单的消费方式。 本文将带你了解如何在将请求发送到后端之前,通过重写 URL 来自定义暴露的 API 的不同方式。 2、Spring Cloud Gateway 快速回顾 Spring Cloud Gateway 项目是在流行的 Spring Boot 2 和 Project Reactor 的基础上构建的,因此继承了其主要特性: 响应式,资源占用低 支持 Spring Cloud 生态系统的所有功能(服务发现、配置等) 使用标准 Spring 模式轻松扩展和/或定制 这里只列出它的主要概念,更多详细信息请参阅 中文文档: Route:路由,在网关中,匹配的传入请求会经历一系列的处理步骤。 Predicate:针对 ServerWebExchange 进行评估的 Java 8 Predicate。 Filters:可以检查、更改 ServerWebExchange 的 GatewayFilter 实例。网关支持全局 Filter 和按路由的 Filter。 简而言之,接收请求的处理顺序如下: 网关使用与每条路由相关的 Predicate 来查找哪条路由可以处理请求。 一旦找到路由,请求(ServerWebExchange 实例)就会通过每个配置的 Filter,直到最终发送到后端。 当后端发送回响应或出现错误(例如超时或连接重置)时,Filter 可以再次处理响应,然后再将其发送回客户端。 3、基于配置的 URL 重写 回到本文的主题,让我们看看如何定义一个路由,在将请求发送到后端之前重写传入的 URL。例如,假设输入的请求格式为 /api/v1/customer/*,后端 URL 应为 http://v1.customers/api/*。这里,使用 “*” 来表示 “在此之后的任何内容”。

修改 Spring Security 的日志级别

1、概览 使用 Spring Security 时,可能需要把日志级别设置得更高一些。例如,可能需要检查用户的角色或端点的安全配置。或者,可能还需要更多关于身份认证或授权的信息,例如查看为什么用户无法访问某个端点。 本文将带你了解如何修改 Spring Security 日志级别。 2、配置 Spring Security 日志 与其他 Spring 或 Java 应用一样,可以使用日志库,并为 Spring Security 模块定义日志级别。 通常,可以进行如下配置: <logger name="org.springframework.security" level="DEBUG" /> 如果运行的是 Spring Boot 应用,则可以在 application.properties 文件中对此进行配置: logging.level.org.springframework.security=DEBUG 同样,也可以使用 yaml: logging: level: org: springframework: security: DEBUG 这样,就可以查看有关身份认证或 Filter Chain 的日志。此外,还可以使用 trace 级别进行更深入的 debug。 Spring Security 还能记录有关请求和应用的 Filter 的特定信息: @EnableWebSecurity public class SecurityConfig { @Value("${spring.websecurity.debug:false}") boolean webSecurityDebug; @Bean public WebSecurityCustomizer webSecurityCustomizer() { return (web) -> web.debug(webSecurityDebug); } // .

OAuth2RestTemplate 简介

1、概览 本文将带你了解如何使用 Spring OAuth2RestTemplate 进行 OAuth2 REST 调用。 创建一个 Spring Web 应用,用于列出 GitHub 账户下的所有仓库。 2、Maven 依赖 首先,需要在 pom.xml 中添加 spring-boot-starter-security 和 spring-security-oauth2-autoconfigure 依赖。由于构建的是 Web 应用,因此还需要包含 spring-boot-starter-web 和 spring-boot-starter-thymeleaf Starter。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.6.8</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> 3、OAuth2 Properties 接下来,在 application.properties 文件中添加 OAuth 配置,以连接到 GitHub 账户: # 替换为你的 CLIENT_ID github.client.clientId=[CLIENT_ID] # 替换为你的 CLIENT_SECRET github.client.clientSecret=[CLIENT_SECRET] github.client.userAuthorizationUri=https://github.com/login/oauth/authorize github.client.accessTokenUri=https://github.com/login/oauth/access_token github.client.clientAuthenticationScheme=form github.resource.userInfoUri=https://api.github.com/user github.resource.repoUri=https://api.github.com/user/repos 注意,需要用 GitHub OAuth App 中的值替换 [CLIENT_ID] 和 [CLIENT_SECRET] 。你可以按照 创建 OAuth App 指南在 GitHub 上注册一个新的应用:

Spring Boot 自动配置的原理

1、什么是 Spring Boot 自动配置 首先介绍一下什么是 Spring Boot,Spring Boost 是基于 Spring 框架开发出来的功能更强大的 Java 程序开发框架,其最主要的特点是:能使程序开发者快速搭建一套开发环境。Spring Boot 能将主流的开发框架(例如 SpringMVC、Dubbo、Mybatis、Redis 等),做到像 Maven 导入 Jar 包一样的简洁快速,做到开箱即用。其中最关键的技术就是 Spring Boot 定制的各种 Starter,通 Maven 引入 Starter 就能快速搭建开发环境。 2、SpringBoot Starter自动装配案例 在以前单独使用 SpringMVC Web 编程框架时,我们需要单独配置 DispatcherServlet 和 Tomcat,使用 Spring Boot 之后,我们只需要引入 spring-boot-Starter-web 就能直接开始编写 Controller 等 Web 相关的代码,这就是 Spring Boot 为们提供的开箱即用的便捷能力,下面就以 spring-boot-Starter-web 来说明 Spring Boot自动配置的关键原理。 3、SpringBoot 自动装配案例源码解析 3.1、DispatcherServlet 的自动配置原理 首先我们定位到 Spring Boot 自动配置的 Maven 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>${spring-boot.version}</version> </dependency> 在依赖的 Jar 包中我们可以在 META-INF/spring.

使用 WebFlux 开发一个 CURD 应用

WebFlux 最为人所诟病的是数据库的支持问题,毕竟数据是一个应用的生命,我们接触的大部分应用程序都是有数据库的,而 WebFlux 在这一方面的支持行一直比较弱,这也是大家总是吐槽它的原因。 不过从 Spring 5 开始,这一问题得到了一定程度的缓解。 Spring 官方在 Spring5 发布了响应式 Web 框架 Spring WebFlux 之后急需能够满足异步响应的数据库交互 API,不过由于缺乏标准和驱动,Pivotal 团队开始自己研究响应式关系型数据库连接 Reactive Relational Database Connectivity,并提出了 R2DBC 规范 API 用来评估可行性并讨论数据库厂商是否有兴趣支持响应式的异步非阻塞驱动程序。最早只有 PostgreSQL 、H2、MSSQL 三家数据库厂商,不过现在 MySQL 也加入进来了,这是一个极大的利好。目前 R2DBC 的最新版本是 0.9.0.RELEASE。 本系列接下来的文章中将会和大家演示 R2DBC 的用法,但是今天我们还是先来看看 WebFlux + MongoDB 的用法,毕竟这是 WebFlux 较早支持的数据库之一,各种 API 都比较成熟,我们一步一步来。 1、项目创建 方便起见,我们这里就直接创建 Spring Boot 项目,首先创建一个 Spring Boot 项目,引入 MongoDB 依赖和 WebFlux 依赖,如下: 注意我们这里选择的 MongoDB 依赖是 Spring Data Reactive MongoDB,千万别选错了。 项目创建完成后,我们先在 application.properties 中对 MongoDB 进行简单配置,如下: