Spring 启动器 - RestTemplate
Spring Boot starter - RestTemplate
我目前正在尝试编写一个 Spring 引导启动程序,它将自动使用 API 网关验证我们的微服务,并在 headers 中包含所有传出请求的访问令牌(朝向网关)。
我正在创建一个 RestTemplate bean 并为其提供我们的自定义拦截器,但我的问题是,通过这样做,我阻止了其他团队(将使用此 starter)使用他们自己的 RestTemplate 配置,因为他们会必须定义导致存在多个 bean 的相同 bean。
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
if (interceptors.isEmpty()){
interceptors = new ArrayList<>();
}
interceptors.add(clientCredentialsAuthInterceptor());
restTemplate.setInterceptors(interceptors);
return restTemplate;
}
是否有另一种方法可以拦截所有传出请求或使 RestTemplate 进一步可配置?
未经测试,但它可能会给您一个起点:
// Create an interface that users of your dependency
// can implement which provides interceptors
public interface RestTemplateAuthInterceptorProvider {
// This interface provides interceptors, so they can add as many as they want
List<ClientHttpRequestInterceptor> provideInterceptor();
}
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
// define a conditional default implementation of your interceptor provider
@Bean
@ConditionalOnMissingBean(RestTemplateAuthInterceptorProvider.class)
public RestTemplateAuthInterceptorProvider restTemplateAuthInterceptorProvider() {
return () -> ... // implement your auth interceptor and return
}
// In your actual rest template creation use method argument injection
// If other teams implement the RestTemplateAuthInterceptorProvider interface
// conditional case above will be false and your implementation will not interfere
// If they dont implement RestTemplateAuthInterceptorProvider
// your default implementation will be here
@Bean
public RestTemplate restTemplate(RestTemplateAuthInterceptorProvider provider) {
RestTemplate restTemplate = new RestTemplate();
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
if (interceptors == null){
interceptors = new ArrayList<>();
}
interceptors.addAll(provider.provideInterceptor()); // from argument
restTemplate.setInterceptors(interceptors);
return restTemplate;
}
编辑:
另一种 hacky 方法是操作已经定义的 RestTemplate bean
@Component
@ConditionalOnBean(RestTemplate.class)
public class RestTemplateBeanCustomizer {
private List<RestTemplate> restTemplateBeans;
// This injects all restTemplate bean definitions to your bean as a list
@Autowired
public RestTemplateBeanCustomizer(List<RestTemplate> restTemplateBeans) {
this.restTemplateBeans = restTemplateBeans;
}
@PostConstruct
public void customizeRestTemplateBeans() {
for (RestTemplate restTemplate : restTemplateBeans) {
// Add your interceptors message handlers etc
// restTemplate.set...
}
}
}
我目前正在尝试编写一个 Spring 引导启动程序,它将自动使用 API 网关验证我们的微服务,并在 headers 中包含所有传出请求的访问令牌(朝向网关)。
我正在创建一个 RestTemplate bean 并为其提供我们的自定义拦截器,但我的问题是,通过这样做,我阻止了其他团队(将使用此 starter)使用他们自己的 RestTemplate 配置,因为他们会必须定义导致存在多个 bean 的相同 bean。
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
if (interceptors.isEmpty()){
interceptors = new ArrayList<>();
}
interceptors.add(clientCredentialsAuthInterceptor());
restTemplate.setInterceptors(interceptors);
return restTemplate;
}
是否有另一种方法可以拦截所有传出请求或使 RestTemplate 进一步可配置?
未经测试,但它可能会给您一个起点:
// Create an interface that users of your dependency
// can implement which provides interceptors
public interface RestTemplateAuthInterceptorProvider {
// This interface provides interceptors, so they can add as many as they want
List<ClientHttpRequestInterceptor> provideInterceptor();
}
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
// define a conditional default implementation of your interceptor provider
@Bean
@ConditionalOnMissingBean(RestTemplateAuthInterceptorProvider.class)
public RestTemplateAuthInterceptorProvider restTemplateAuthInterceptorProvider() {
return () -> ... // implement your auth interceptor and return
}
// In your actual rest template creation use method argument injection
// If other teams implement the RestTemplateAuthInterceptorProvider interface
// conditional case above will be false and your implementation will not interfere
// If they dont implement RestTemplateAuthInterceptorProvider
// your default implementation will be here
@Bean
public RestTemplate restTemplate(RestTemplateAuthInterceptorProvider provider) {
RestTemplate restTemplate = new RestTemplate();
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
if (interceptors == null){
interceptors = new ArrayList<>();
}
interceptors.addAll(provider.provideInterceptor()); // from argument
restTemplate.setInterceptors(interceptors);
return restTemplate;
}
编辑: 另一种 hacky 方法是操作已经定义的 RestTemplate bean
@Component
@ConditionalOnBean(RestTemplate.class)
public class RestTemplateBeanCustomizer {
private List<RestTemplate> restTemplateBeans;
// This injects all restTemplate bean definitions to your bean as a list
@Autowired
public RestTemplateBeanCustomizer(List<RestTemplate> restTemplateBeans) {
this.restTemplateBeans = restTemplateBeans;
}
@PostConstruct
public void customizeRestTemplateBeans() {
for (RestTemplate restTemplate : restTemplateBeans) {
// Add your interceptors message handlers etc
// restTemplate.set...
}
}
}