简体   繁体   English

Spring 引导启动器 - RestTemplate

[英]Spring Boot starter - RestTemplate

I'm currently trying to write a Spring Boot starter that would automatically authenticate our microservices with an API gateway and include the access token in the headers for all outgoing requests (towards the gateway).我目前正在尝试编写 Spring 启动启动器,它将使用 API 网关自动验证我们的微服务,并将访问令牌包含在所有传出请求的标头中(朝向网关)。
I'm creating a RestTemplate bean and giving it our custom interceptor, but my problem is, by doing this, I prevent other teams (who would be using this starter) to use their own RestTemplate config, since they would have to define the same bean leading to multiple beans existing.我正在创建一个 RestTemplate bean 并为其提供我们的自定义拦截器,但我的问题是,通过这样做,我阻止其他团队(将使用此启动器)使用他们自己的 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;
}

Is there another way of intercepting all outgoing requests or make the RestTemplate further configurable?是否有另一种方法可以拦截所有传出请求或使 RestTemplate 进一步可配置?

Not tested but it may give you a start point:未经测试,但它可能会给你一个起点:

// 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;
}

Edit: Another hacky approach is to manipulate already defined RestTemplate beans编辑:另一种 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...
      }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM