Remove ugly depednency on Environment
You can bind to a Map<String,String> with application.yml, so there's no need to work so hard to extract the zuul routes.
This commit is contained in:
@@ -4,127 +4,95 @@ import java.lang.reflect.Field;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.boot.bind.PropertySourceUtils;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.CompositePropertySource;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Slf4j
|
||||
public class RouteLocator implements ApplicationListener<EnvironmentChangeEvent>, EnvironmentAware {
|
||||
public class RouteLocator implements ApplicationListener<EnvironmentChangeEvent> {
|
||||
|
||||
public static final String DEFAULT_ROUTE = "/";
|
||||
public static final String DEFAULT_ROUTE = "/";
|
||||
|
||||
private ConfigurableEnvironment env = new StandardEnvironment();
|
||||
private DiscoveryClient discovery;
|
||||
|
||||
private DiscoveryClient discovery;
|
||||
private ZuulProperties properties;
|
||||
|
||||
private ZuulProperties properties;
|
||||
private Field propertySourcesField;
|
||||
private AtomicReference<LinkedHashMap<String, String>> routes = new AtomicReference<>();
|
||||
|
||||
private Field propertySourcesField;
|
||||
private AtomicReference<LinkedHashMap<String, String>> routes = new AtomicReference<>();
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
env = (ConfigurableEnvironment) environment;
|
||||
}
|
||||
|
||||
public RouteLocator(DiscoveryClient discovery, ZuulProperties properties) {
|
||||
this.discovery = discovery;
|
||||
public RouteLocator(DiscoveryClient discovery, ZuulProperties properties) {
|
||||
this.discovery = discovery;
|
||||
this.properties = properties;
|
||||
initField();
|
||||
}
|
||||
}
|
||||
|
||||
private void initField() {
|
||||
propertySourcesField = ReflectionUtils.findField(CompositePropertySource.class, "propertySources");
|
||||
propertySourcesField.setAccessible(true);
|
||||
}
|
||||
private void initField() {
|
||||
propertySourcesField = ReflectionUtils.findField(CompositePropertySource.class,
|
||||
"propertySources");
|
||||
propertySourcesField.setAccessible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(EnvironmentChangeEvent event) {
|
||||
for (String key : event.getKeys()) {
|
||||
if (key.startsWith(properties.getRoutePrefix())) {
|
||||
routes.set(locateRoutes());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onApplicationEvent(EnvironmentChangeEvent event) {
|
||||
for (String key : event.getKeys()) {
|
||||
if (key.startsWith(properties.getMapping())) {
|
||||
routes.set(locateRoutes());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: respond to changes in eureka
|
||||
public Map<String, String> getRoutes() {
|
||||
if (routes.get() == null) {
|
||||
routes.set(locateRoutes());
|
||||
}
|
||||
public Map<String, String> getRoutes() {
|
||||
if (routes.get() == null) {
|
||||
routes.set(locateRoutes());
|
||||
}
|
||||
|
||||
return routes.get();
|
||||
}
|
||||
return routes.get();
|
||||
}
|
||||
|
||||
protected LinkedHashMap<String, String> locateRoutes() {
|
||||
LinkedHashMap<String, String> routesMap = new LinkedHashMap<>();
|
||||
protected LinkedHashMap<String, String> locateRoutes() {
|
||||
LinkedHashMap<String, String> routesMap = new LinkedHashMap<>();
|
||||
|
||||
//Add routes for discovery services by default
|
||||
List<String> services = discovery.getServices();
|
||||
for (String serviceId : services) {
|
||||
//Ignore specified services
|
||||
if (!properties.getIgnoredServices().contains(serviceId))
|
||||
routesMap.put("/" + serviceId + "/**", serviceId);
|
||||
}
|
||||
// Add routes for discovery services by default
|
||||
List<String> services = discovery.getServices();
|
||||
for (String serviceId : services) {
|
||||
// Ignore specified services
|
||||
if (!properties.getIgnoredServices().contains(serviceId))
|
||||
routesMap.put("/" + serviceId + "/**", serviceId);
|
||||
}
|
||||
|
||||
MutablePropertySources propertySources = env.getPropertySources();
|
||||
for (PropertySource<?> propertySource : propertySources) {
|
||||
getRoutes(propertySource, routesMap);
|
||||
}
|
||||
addConfiguredRoutes(routesMap);
|
||||
|
||||
String defaultServiceId = routesMap.get(DEFAULT_ROUTE);
|
||||
String defaultServiceId = routesMap.get(DEFAULT_ROUTE);
|
||||
|
||||
if (defaultServiceId != null) {
|
||||
//move the defaultServiceId to the end
|
||||
routesMap.remove(DEFAULT_ROUTE);
|
||||
routesMap.put(DEFAULT_ROUTE, defaultServiceId);
|
||||
}
|
||||
return routesMap;
|
||||
}
|
||||
if (defaultServiceId != null) {
|
||||
// move the defaultServiceId to the end
|
||||
routesMap.remove(DEFAULT_ROUTE);
|
||||
routesMap.put(DEFAULT_ROUTE, defaultServiceId);
|
||||
}
|
||||
return routesMap;
|
||||
}
|
||||
|
||||
protected void getRoutes(PropertySource<?> propertySource, Map<String, String> routes) {
|
||||
if (propertySource instanceof CompositePropertySource) {
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<PropertySource<?>> sources = (Set<PropertySource<?>>) propertySourcesField.get(propertySource);
|
||||
for (PropertySource<?> source : sources) {
|
||||
getRoutes(source, routes);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
//EnumerablePropertySource enumerable = (EnumerablePropertySource) propertySource;
|
||||
MutablePropertySources propertySources = new MutablePropertySources();
|
||||
propertySources.addLast(propertySource);
|
||||
Map<String, Object> routeEntries = PropertySourceUtils.getSubProperties(propertySources, properties.getRoutePrefix());
|
||||
for (Map.Entry<String, Object> entry : routeEntries.entrySet()) {
|
||||
String serviceId = entry.getKey();
|
||||
String route = entry.getValue().toString();
|
||||
protected void addConfiguredRoutes(Map<String, String> routes) {
|
||||
Map<String, String> routeEntries = properties.getRoute();
|
||||
for (Map.Entry<String, String> entry : routeEntries.entrySet()) {
|
||||
String serviceId = entry.getKey();
|
||||
String route = entry.getValue() ;
|
||||
|
||||
if (routes.containsKey(route)) {
|
||||
log.warn("Overwriting route {}: already defined by {}", route, routes.get(route));
|
||||
}
|
||||
routes.put(route, serviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (routes.containsKey(route)) {
|
||||
log.warn("Overwriting route {}: already defined by {}", route,
|
||||
routes.get(route));
|
||||
}
|
||||
routes.put(route, serviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping implements
|
||||
url = "/" + url;
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(properties.getRoutePrefix())) {
|
||||
if (StringUtils.hasText(properties.getMapping())) {
|
||||
url = properties.getMapping() + url;
|
||||
if (!url.startsWith("/")) {
|
||||
url = "/" + url;
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package org.springframework.cloud.netflix.zuul;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
@@ -14,7 +17,7 @@ import java.util.List;
|
||||
public class ZuulProperties {
|
||||
private String mapping = "";
|
||||
private boolean stripMapping = false;
|
||||
private String routePrefix = "zuul.route.";
|
||||
private Map<String,String> route = new HashMap<String, String>();
|
||||
private boolean addProxyHeaders = true;
|
||||
private List<String> ignoredServices = Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package org.springframework.cloud.netflix.zuul;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
@@ -23,6 +25,7 @@ public class RouteLocatorTests {
|
||||
public static final String IGNOREDSERVICE = "ignoredservice";
|
||||
public static final String ASERVICE = "aservice";
|
||||
public static final String MYSERVICE = "myservice";
|
||||
|
||||
@Mock
|
||||
ConfigurableEnvironment env;
|
||||
|
||||
@@ -39,12 +42,8 @@ public class RouteLocatorTests {
|
||||
ZuulProperties properties = new ZuulProperties();
|
||||
RouteLocator routeLocator = new RouteLocator(this.discovery, properties);
|
||||
properties.setIgnoredServices(Lists.newArrayList(IGNOREDSERVICE));
|
||||
routeLocator.setEnvironment(this.env);
|
||||
properties.getRoute().put(ASERVICE, "/"+ASERVICE + "/**");
|
||||
|
||||
MutablePropertySources propertySources = new MutablePropertySources();
|
||||
propertySources.addFirst(new MockPropertySource().withProperty("zuul.route."
|
||||
+ ASERVICE, getMapping(ASERVICE)));
|
||||
when(env.getPropertySources()).thenReturn(propertySources);
|
||||
when(discovery.getServices()).thenReturn(
|
||||
Lists.newArrayList(MYSERVICE, IGNOREDSERVICE));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user