一、需求
OpenFeign请求拦截器,注入配置属性类(@ConfigurationProperties),添加配置文件(yml)中的token到请求头
在使用Spring Boot结合OpenFeign进行微服务间调用时,需要在发起HTTP请求时添加一些默认的请求头,比如认证令牌(token)。为了实现这一功能,可以创建一个请求拦截器,并且通过@ConfigurationProperties
来注入从配置文件中读取的属性值。
二、解决方案
1. 定义配置属性类
首先,定义一个Java类来封装配置文件中的属性,并使用 @ConfigurationProperties
注解来将配置文件中的值绑定到该类的实例上。
package com.example.hello_feign_client.core.property;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "security")
public class SecurityProperties {
private String token;
}
在上面的例子中,prefix = "security"
意味着配置文件(如application.properties
或application.yml
)中,所有以 security
开头的键都会映射到这个类的属性上;token
属性位于 security
键下。
2. 在配置文件中定义token
接下来,在application.yml
中定义相应的属性。
security:
token: 123456
3. 请求拦截器-注入配置属性类
创建请求拦截器
,注入配置属性类(SecurityProperties
)的实例,并从中获取token值。
package com.example.hello_feign_client.feign.config;
import com.example.hello_feign_client.core.property.SecurityProperties;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor
public class SecurityRequestInterceptor implements RequestInterceptor {
private final SecurityProperties securityProperties;
@Override
public void apply(RequestTemplate requestTemplate) {
log.info("token={}", securityProperties.getToken());
requestTemplate.header("token", securityProperties.getToken());
}
}
4. 配置Feign客户端
Feign客户端配置对应请求拦截器。
package com.example.hello_feign_client.feign.client;
import com.example.hello_feign_client.feign.config.SecurityRequestInterceptor;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(contextId = "securityFeignClient",
name = "hello-feign-server",
url = "http://localhost:9001",
path = "/security",
configuration = SecurityRequestInterceptor.class
)
public interface SecurityFeignClient {
@GetMapping("/message")
String getMessage();
}
三、测试
运行应用程序,访问客户端 /security/message
接口,验证发送请求时,将token写入请求头;并且服务端也收到了正确的token。
客户端发送请求
客户端通过FeignClient调用接口,发送请求。
package com.example.hello_feign_client.web.security.controller;
import com.example.hello_feign_client.feign.client.SecurityFeignClient;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/security")
@RequiredArgsConstructor
public class SecurityController {
private final SecurityFeignClient securityFeignClient;
@GetMapping("/message")
public String getMessage() {
return securityFeignClient.getMessage();
}
}
服务端接收请求
服务端接受请求,验证请求头中的token。本例中省略验证步骤,仅做日志打印。
package com.example.hello_feign_server.web.controller;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/security")
@RequiredArgsConstructor
public class SecurityController {
@GetMapping("/message")
public String getMessage(@RequestHeader("token") String token) {
log.info("token={}", token);
return "获取到的消息";
}
}
接口调用成功
打印日志
客户端:
2024-09-05T20:42:28.915+08:00 INFO 8024 — [hello-feign-client] [nio-9002-exec-2] c.e.h.f.c.SecurityRequestInterceptor : token=123456
服务端:
2024-09-05T20:42:28.915+08:00 INFO 11188 — [hello-feign-server] [nio-9001-exec-2] c.e.h.web.controller.SecurityController : token=123456