Spring Cloud Gateway 将 bean 传递给自定义过滤器
Spring Cloud Gateway pass bean to custom filter
我们正在尝试使用 Spring 云网关来设置基于微服务的架构。目前,我们已经以编程方式定义了一条路线:
@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
注入上面的网关 class,然后传递此 RestTemplate
到过滤器的构造函数。
但是,如果我们想切换到使用 YAML 文件来定义所有路由,该怎么做呢?大概在这两种情况下 Spring 都会为每个传入请求构建一个新的过滤器。但是在 YAML 的情况下,我们如何在构造函数中传递一些东西?如果无法做到这一点,是否有任何其他方法可以将 RestTemplate
或任何其他资源注入自定义 Spring 网关过滤器?
您可以register your own custom GatewayFilterFactory
. This allows you to provide a custom configuration, and within that configuration, you can use 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
}
}
注入所需的 code/configuration 不那么复杂,但如果您决定将 AuthenticationGatewayFilterFactory
放在单独的库中,它也会变得更加困难,因为 "consumers"这个库的将无法控制正在注入的RestTemplate
。
我们正在尝试使用 Spring 云网关来设置基于微服务的架构。目前,我们已经以编程方式定义了一条路线:
@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
注入上面的网关 class,然后传递此 RestTemplate
到过滤器的构造函数。
但是,如果我们想切换到使用 YAML 文件来定义所有路由,该怎么做呢?大概在这两种情况下 Spring 都会为每个传入请求构建一个新的过滤器。但是在 YAML 的情况下,我们如何在构造函数中传递一些东西?如果无法做到这一点,是否有任何其他方法可以将 RestTemplate
或任何其他资源注入自定义 Spring 网关过滤器?
您可以register your own custom GatewayFilterFactory
. This allows you to provide a custom configuration, and within that configuration, you can use 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
}
}
注入所需的 code/configuration 不那么复杂,但如果您决定将 AuthenticationGatewayFilterFactory
放在单独的库中,它也会变得更加困难,因为 "consumers"这个库的将无法控制正在注入的RestTemplate
。