#java #spring #microservices
#java #spring #микросервисы
Вопрос:
У меня есть 3 микрослужбы, которые все должны использовать «общую» библиотеку. Мне нужно добавить новую конфигурацию Spring в общую библиотеку. Проблема в том, что микросервису A наплевать на новый код и он не хочет, чтобы его заставляли добавлять конфигурацию для запуска приложения. Мне нужен способ программной загрузки конфигурации только для микросервисов B и C.
Новая конфигурация в общей библиотеке:
@Configuration
public class HttpConnectionConfiguration {
@Value("${http.connect.timeout}")
private int httpConnectTimeout;
@Value("${http.connect.request.timeout}")
private int httpConnectRequestTimeout;
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(getClientHttpRequestFactory());
return restTemplate;
}
private ClientHttpRequestFactory getClientHttpRequestFactory() {
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(httpConnectTimeout)
.setConnectionRequestTimeout(httpConnectRequestTimeout)
.build();
CloseableHttpClient client = HttpClientBuilder
.create()
.useSystemProperties()
.setDefaultRequestConfig(config)
.build();
return new HttpComponentsClientHttpRequestFactory(client);
}
}
Конфигурация в микросервисах B и C application.yaml:
http:
connect:
timeout: 5000
request:
timeout: 5000
Микросервисы B и C запускаются нормально, но A выдает эту ошибку: Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'http.connect.timeout' in value "${http.connect.timeout}
Каков наилучший способ решения этой проблемы без предоставления фиктивных значений в микросервисе A?
Ответ №1:
Решение 1: используйте иерархию конфигурации с дополнительным @Configuration
классом, который создает RestTemplate
компонент, и активируйте его только для B и C (или когда свойство доступно):
@Configuration
@ConditionalOnProperty("http.connect.timeout")
public class HttpConnectionConfiguration {
// rest of code ...
Решение 2: используйте значения по умолчанию. Поскольку время ожидания по умолчанию равно -1
, используйте это:
@Value("${http.connect.timeout:-1}")
private int httpConnectTimeout;
@Value("${http.connect.request.timeout:-1}")
private int httpConnectRequestTimeout;
Комментарии:
1. пара вопросов, касающихся решения 1: как вы добавляете несколько ConditionalOnProperty, поскольку есть несколько свойств, которые я, вероятно, должен включить. Кроме того, после включения предложенной аннотации он теперь выдает: ` Метод компонента ‘RestTemplate’ в ‘HttpConnectionConfiguration’ не загружен, потому что @ConditionalOnProperty (http.connect.timeout) не нашел свойство ‘http.connect.timeout»
2. Очевидно, что вам не следует автоматически подключать или иным образом обращаться к компоненту RestTemplate в конфигурации A. Вы можете добиться этого, не создавая экземпляры B и C в конфигурации A (например, выполните более детальное сканирование компонентов).
Ответ №2:
Вы можете указать значения по умолчанию внутри @Value
, используя выражение SpEL, подобное приведенному ниже.
@Value("${http.connect.timeout:10}")
private int httpConnectTimeout;
@Value("${http.connect.request.timeout:10}")
private int httpConnectRequestTimeout;