Определите различные реализации клиента Feign в зависимости от среды
У меня есть загрузочное приложение Spring, которое использует Feign для вызова внешнего веб-сервиса через Eureka. Я хотел бы иметь возможность запускать приложение, используя макетную реализацию интерфейса Feign, поэтому я могу запускать приложение локально, без необходимости запуска Eureka или внешнего веб-сервиса. Я представлял себе определение конфигурации пробега, которая позволила мне сделать это, но я изо всех сил пытаюсь заставить это работать. Проблема в том, что Spring "magic" определяет bean-компонент для интерфейса Feign, что бы я ни пытался.
Симулировать интерфейс
@FeignClient(name = "http://foo-service")
public interface FooResource {
@RequestMapping(value = "/doSomething", method = GET)
String getResponse();
}
обслуживание
public class MyService {
private FooResource fooResource;
...
public void getFoo() {
String response = this.fooResource.getResponse();
...
}
}
Я попытался добавить класс конфигурации, который условно регистрировал бин, если профиль Spring был "локальным", но он никогда не вызывался, когда я запускал приложение с этим профилем Spring:
@Configuration
public class AppConfig {
@Bean
@ConditionalOnProperty(prefix = "spring.profile", name = "active", havingValue="local")
public FooResource fooResource() {
return new FooResource() {
@Override
public String getResponse() {
return "testing";
}
};
}
}
В момент, когда мой сервис работает, FooResource
переменная-член в MyService
имеет тип
HardCodedTarget (type = FoorResource, url = http://foo-service/)
в соответствии с IntelliJ. Это тип, который автоматически генерируется средой Spring Cloud Netflix и поэтому пытается установить связь с удаленной службой.
Есть ли способ, которым я могу условно переопределить реализацию интерфейса Feign в зависимости от параметра конфигурации?
1 ответ
Решение , как показано ниже:
public interface FeignBase {
@RequestMapping(value = "/get", method = RequestMethod.POST, headers = "Accept=application/json")
Result get(@RequestBody Token common);
}
затем определите свой интерфейс на основе env:
@Profile("prod")
@FeignClient(name = "service.name")
public interface Feign1 extends FeignBase
{}
@Profile("!prod")
@FeignClient(name = "service.name", url = "your url")
public interface Feign2 extends FeignBase
{}
наконец, к вашим услугам:
@Resource
private FeignBase feignBase;
После публикации того же вопроса в github-репозитории Spring Cloud Netflix полезным ответом было использование Spring @Profile
аннотаций.
Я создал альтернативный класс точки входа, который не был аннотирован @EnabledFeignClients
и создал новый класс конфигурации, который определил реализации для моих интерфейсов Feign. Теперь это позволяет мне запускать приложение локально без необходимости запуска Eureka или каких-либо зависимых сервисов.
Я использую более простое решение, чтобы избежать множественных интерфейсов для параметра переменной, такого как url.
@FeignClient(name = "service.name", url = "${app.feign.clients.url}")
public interface YourClient{}
application-{profile}.properties
app.feign.clients.url=http://localhost:9999