В настоящее время я пытаюсь написать стартер Spring Boot, который автоматически аутентифицирует наши микросервисы с помощью шлюза API и включает токен доступа в заголовки для всех исходящих запросов (к шлюзу).
Я создаю bean-компонент RestTemplate и даю ему наш пользовательский перехватчик, но моя проблема в том, что, делая это, я не позволяю другим командам (которые будут использовать этот стартер) использовать свою собственную конфигурацию 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;
}
Редактировать: Другой хакерский подход заключается в манипулировании уже определенными bean-компонентами RestTemplate.
@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...
}
}
}
Это только позволит им определить свои собственные перехватчики, если я прав. Мой вопрос больше касается создания самого RestTemplate. Допустим, они хотят добавить к нему собственный messageHandler, но стартер уже определил bean-компонент без этого. Я мог бы аннотировать его с помощью @ConditionalOnMissingBean, но тогда, если кто-то его определит, у него не будет установлен перехватчик.
В идеале ваши проекты должны использовать
RestTemplateBuilder
для создания экземпляровRestTEmplate
, это, в свою очередь, автоматически обнаружит все предварительно зарегистрированные перехватчики. Единственное, что должен сделать ваш autp-config, это создать bean-компонент для перехватчика. Или определитеRestTemplateCustomizer
, который добавляет перехватчик. Однако это работает только в том случае, если команды следуют практике использованияRestTemplateBuilder
для создания экземпляров.