我们正在尝试使用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();
}
}
以上内容将通过GET将传入请求/status
路由到另一个端点。我们想应用一个自定义过滤器,该过滤器已在AuthorizationFilter
中实现。顾名思义,该过滤器是另一个微服务,它将基于凭据和权限来允许或拒绝传入的请求。
当前,我们遵循的模式有效,是将Spring RestTemplate
注入上述网关类,然后将此RestTemplate
传递给过滤器的构造函数。
但是,如果我们想切换到使用YAML文件来定义所有路由,该怎么办?大概在两种情况下,Spring都会为每个传入的请求构造一个新的过滤器。但是对于YAML,我们如何在构造函数中传递某些内容?如果无法做到这一点,是否还有其他方法可以将RestTemplate
或任何其他资源注入到自定义的Spring网关过滤器中?
答案 0 :(得分:1)
您可以register your own custom GatewayFilterFactory
。这样就可以提供自定义配置,并且在该配置中,可以使用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正确引用RestTemplate
bean:
spring:
cloud:
gateway:
routes:
- id: status
uri: http://localhost:8081/
filters:
- name: Authentication
args:
restTemplate: "#{@nameOfRestTemplateBean}"
predicates:
- Path=/status
或者,您可以在网关过滤器中注入RestTemplate
bean。例如:
@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
。