From e6faa31c483a45ee7bad48ff72ffedc3e34238e5 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Fri, 17 Feb 2017 17:55:48 -0700 Subject: [PATCH] Use RefreshRoutesEvent to trigger code to clear route caches --- .../gateway/actuate/GatewayEndpoint.java | 21 ++++++++++++------- .../gateway/handler/FilteringWebHandler.java | 12 ++++++++++- .../gateway/support/CachingRouteLocator.java | 6 ++++++ .../gateway/support/RefreshRoutesEvent.java | 18 ++++++++++++++++ 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 src/main/java/org/springframework/cloud/gateway/support/RefreshRoutesEvent.java diff --git a/src/main/java/org/springframework/cloud/gateway/actuate/GatewayEndpoint.java b/src/main/java/org/springframework/cloud/gateway/actuate/GatewayEndpoint.java index 8eda427a..df3ba020 100644 --- a/src/main/java/org/springframework/cloud/gateway/actuate/GatewayEndpoint.java +++ b/src/main/java/org/springframework/cloud/gateway/actuate/GatewayEndpoint.java @@ -14,8 +14,10 @@ import org.springframework.cloud.gateway.api.RouteWriter; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.route.RouteFilter; import org.springframework.cloud.gateway.handler.FilteringWebHandler; -import org.springframework.cloud.gateway.support.CachingRouteLocator; import org.springframework.cloud.gateway.support.NotFoundException; +import org.springframework.cloud.gateway.support.RefreshRoutesEvent; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.core.Ordered; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; @@ -26,7 +28,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** @@ -36,7 +37,7 @@ import reactor.core.publisher.Mono; //@ConfigurationProperties(prefix = "endpoints.gateway") @RestController @RequestMapping("/admin/gateway") -public class GatewayEndpoint {/*extends AbstractEndpoint> {*/ +public class GatewayEndpoint implements ApplicationEventPublisherAware {/*extends AbstractEndpoint> {*/ private static final Log log = LogFactory.getLog(GatewayEndpoint.class); @@ -45,6 +46,7 @@ public class GatewayEndpoint {/*extends AbstractEndpoint> {* private List routeFilters; private FilteringWebHandler filteringWebHandler; private RouteWriter routeWriter; + private ApplicationEventPublisher publisher; public GatewayEndpoint(RouteLocator routeLocator, List globalFilters, List routeFilters, FilteringWebHandler filteringWebHandler, @@ -57,17 +59,20 @@ public class GatewayEndpoint {/*extends AbstractEndpoint> {* this.routeWriter = routeWriter; } + @Override + public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { + this.publisher = publisher; + } + /*@Override public Map invoke() { }*/ //TODO: this should really be a listener that responds to a RefreshEvent @PostMapping("/refresh") - public Flux refresh() { - if (this.routeLocator instanceof CachingRouteLocator) { - return ((CachingRouteLocator)this.routeLocator).refresh(); - } - return Flux.empty(); + public Mono refresh() { + this.publisher.publishEvent(new RefreshRoutesEvent(this)); + return Mono.empty(); } @GetMapping("/globalfilters") diff --git a/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java b/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java index f704d0ab..172b343e 100644 --- a/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java +++ b/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java @@ -24,6 +24,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; import org.apache.commons.logging.Log; @@ -33,6 +35,8 @@ import org.springframework.cloud.gateway.api.Route; import org.springframework.cloud.gateway.config.GatewayProperties; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.route.RouteFilter; +import org.springframework.cloud.gateway.support.RefreshRoutesEvent; +import org.springframework.context.event.EventListener; import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.web.server.ServerWebExchange; @@ -61,7 +65,7 @@ public class FilteringWebHandler extends WebHandlerDecorator { private final List globalFilters; private final Map routeFilters = new HashMap<>(); - private final Map> combinedFiltersForRoute = new HashMap<>(); + private final ConcurrentMap> combinedFiltersForRoute = new ConcurrentHashMap<>(); public FilteringWebHandler(GatewayProperties gatewayProperties, List globalFilters, Map routeFilters) { @@ -91,6 +95,12 @@ public class FilteringWebHandler extends WebHandlerDecorator { return this.globalFilters; } + + @EventListener(RefreshRoutesEvent.class) + /* for testing */ void handleRefresh() { + this.combinedFiltersForRoute.clear(); + } + @Override public Mono handle(ServerWebExchange exchange) { Optional route = exchange.getAttribute(GATEWAY_ROUTE_ATTR); diff --git a/src/main/java/org/springframework/cloud/gateway/support/CachingRouteLocator.java b/src/main/java/org/springframework/cloud/gateway/support/CachingRouteLocator.java index 57ad1141..4ca7a51e 100644 --- a/src/main/java/org/springframework/cloud/gateway/support/CachingRouteLocator.java +++ b/src/main/java/org/springframework/cloud/gateway/support/CachingRouteLocator.java @@ -5,6 +5,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.springframework.cloud.gateway.api.Route; import org.springframework.cloud.gateway.api.RouteLocator; +import org.springframework.context.event.EventListener; import reactor.core.publisher.Flux; /** @@ -37,4 +38,9 @@ public class CachingRouteLocator implements RouteLocator { private List collectRoutes() { return this.delegate.getRoutes().collectList().block(); } + + @EventListener(RefreshRoutesEvent.class) + /* for testing */ void handleRefresh() { + refresh(); + } } diff --git a/src/main/java/org/springframework/cloud/gateway/support/RefreshRoutesEvent.java b/src/main/java/org/springframework/cloud/gateway/support/RefreshRoutesEvent.java new file mode 100644 index 00000000..5252c4ee --- /dev/null +++ b/src/main/java/org/springframework/cloud/gateway/support/RefreshRoutesEvent.java @@ -0,0 +1,18 @@ +package org.springframework.cloud.gateway.support; + +import org.springframework.context.ApplicationEvent; + +/** + * @author Spencer Gibb + */ +public class RefreshRoutesEvent extends ApplicationEvent { + + /** + * Create a new ApplicationEvent. + * + * @param source the object on which the event initially occurred (never {@code null}) + */ + public RefreshRoutesEvent(Object source) { + super(source); + } +}