Бин передачи Spring Cloud Gateway в настраиваемый фильтр

Мы пытаемся использовать Spring Cloud Gateway для настройки архитектуры на основе микросервисов. В настоящее время мы программно определили маршрут:

@ServletComponentScan
@SpringBootApplication
public class GatewayApplication {
    // to be passed to and used by custom filter
    @Autowired
    RestTemplate restTemplate;

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
        .route("status", r -> r
            .method(HttpMethod.GET)
            .and()
            .path("/status")
            .filters(f -> f.rewritePath("/status", "/v2/status")
                           .filter(new AuthorizationFilter(restTemplate).apply(new Config(""))))
            .uri("http://localhost:8081/"))
        .build();
    }
}

Вышеупомянутое будет направлять входящий запрос /status через GET в другую конечную точку. Мы хотели бы применить специальный фильтр, который мы реализовали в AuthorizationFilter. Этот фильтр, как следует из названия, является еще одной микрослужбой, которая разрешает или отклоняет входящий запрос на основе учетных данных и разрешений.

В настоящее время схема, которой мы следуем, которая работает, заключается в том, чтобы внедрить Spring RestTemplate в класс шлюза, указанный выше, а затем передать это RestTemplate конструктору фильтра.

Однако как это сделать, если мы хотим переключиться на использование файла YAML для определения всех маршрутов? Предположительно в обоих случаях Spring будет создавать новый фильтр для каждого входящего запроса. Но как мы можем передать что-то в конструкторе в случае YAML? Если это невозможно сделать, есть ли другой способ добавить RestTemplate или любой другой ресурс в настраиваемый фильтр шлюза Spring?


person Tim Biegeleisen    schedule 28.03.2019    source источник


Ответы (1)


Вы можете зарегистрировать свой собственный _1 _. Это позволяет вам предоставить индивидуальную конфигурацию, и в этой конфигурации вы можете использовать SpEL для ссылки на bean-компонент.

Например:

@Component
public class AuthenticationGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthenticationGatewayFilterFactory.Config> {
    public AuthenticationGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        // TODO: Implement
    }

    public static class Config {
        private RestTemplate restTemplate;

        // TODO: Getters + Setters
    }
}

Теперь вы можете использовать SpEL для правильной ссылки на bean-компонент RestTemplate:

spring:
  cloud:
    gateway:
      routes:
        - id: status
          uri: http://localhost:8081/
          filters:
            - name: Authentication
              args:
                restTemplate: "#{@nameOfRestTemplateBean}"
          predicates:
            - Path=/status

В качестве альтернативы вы можете вставить bean-компонент RestTemplate в фильтр вашего шлюза. Например:

@Component
public class AuthenticationGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthenticationGatewayFilterFactory.Config> {
    private RestTemplate restTemplate;

    public AuthenticationGatewayFilterFactory(RestTemplate restTemplate) {
        super(Config.class);
        this.restTemplate = restTemplate;
    }

    @Override
    public GatewayFilter apply(Config config) {
        // TODO: Implement
    }

    public static class Config {
        // TODO: Implement
    }
}

Код / конфигурация, необходимые для внедрения, менее сложны, но они также усложняют задачу, если вы когда-нибудь решите поместить AuthenticationGatewayFilterFactory в отдельную библиотеку, поскольку «потребители» этой библиотеки не будут иметь никакого контроля над тем, какой RestTemplate является вводится.

person g00glen00b    schedule 28.03.2019
comment
Ваше точное решение не сработало для меня, но я смог использовать EL в маршруте YAML для передачи ссылки bean-компонента RestTemplate конструктору настраиваемого фильтра. - person Tim Biegeleisen; 29.03.2019
comment
@TimBiegeleisen Рад узнать, что это вам помогло. Сам код не работал (есть ли что-то, что я могу исправить) или это больше не сработало для вашего сценария? Я сам вчера попробовал (используя простые фиктивные бобы), и он, похоже, работал, но, возможно, я что-то пропустил. - person g00glen00b; 29.03.2019