Определите различные реализации клиента 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
Другие вопросы по тегам