咸鱼

咸鱼是以盐腌渍后,晒干的鱼

0%

SpringBoot记录一次FeignClient升级问题

问题

在维护一个长时间没更新的项目时,仅升级了 spring-boot-starter-parent 版本至 2.6.x,导致部分服务调用第三方API(用 openfeign 实现)失效。

项目创建时,以下版本都是最新的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/>
</parent>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

声明 FeignClient 服务,这个第三方接口是要求表单是 x-www-form-urlencoded 编码的。
这个版本的 Feign 默认并不支持 x-www-form-urlencoded,通过 LinkedMultiValueMap 将参数放到Body来解决。

1
2
3
4
5
6
7
@Component
@FeignClient(name = "TestService",url = "http://192.168.0.666:8080/oauth2/v2/")
public interface TestOAuthAPIServer {

@PostMapping(value = "/token",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
String getAccessToken(@RequestBody LinkedMultiValueMap<String, String> body);
}

调用服务

1
2
3
4
5
LinkedMultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("grant_type","xxxxxxxxxxx");
body.add("client_id","xxxxxxxxxxx");
body.add("client_secret","xxxxxxxxxxx");
testOAuthAPIServer.getAccessToken(body);

由于 log4j2 的漏洞,紧急将spring-boot-starter-parent 升级到 2.6.x
后来发现 openfeign 提交 application/x-www-form-urlencoded 表单的 body 是空的。

解决

查询文档: spring-cloud-openfeign/docs 发现 openfeign 已经更新了很多内容,详细请查看官方文档。

注意:
spring-boot-starter-parentspring-cloud-dependencies 这两个组件的版本最后按照官方的依赖来,请参考:【Table 1. Release train Spring Boot compatibility】

2022年,这里更新所有的组件版本到最新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/>
</parent>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.1.3</version>
</dependency>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

声明 FeignClient 服务的Body直接用一个Bean类提交。

1
2
3
4
5
6
7
@Component
@FeignClient(name = "TestService",url = "http://192.168.0.666:8080/oauth2/v2/")
public interface TestOAuthAPIServer {

@PostMapping(value = "/token",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
String getAccessToken(@RequestBody MyBody body);
}

现在的版本已经支持 application/x-www-form-urlencoded 表单,所以声明 Bean类作为表单参数即可。

1
2
3
4
5
6
@Data
public class MyBody {
private String grant_type;
private String client_id;
private String client_secret;
}