Allow multiple endpoint PathMapper beans
Update `WebEndpointDiscoverer` and related classes to that multiple `PathMapper` beans can be registered. Mappers are now tried in order until one returns a non-null value. Closes gh-14841
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.actuate.autoconfigure.cloudfoundry;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.OperationInvokerAdvisor;
|
||||
@@ -45,17 +46,17 @@ public class CloudFoundryWebEndpointDiscoverer extends WebEndpointDiscoverer {
|
||||
* @param applicationContext the source application context
|
||||
* @param parameterValueMapper the parameter value mapper
|
||||
* @param endpointMediaTypes the endpoint media types
|
||||
* @param endpointPathMapper the endpoint path mapper
|
||||
* @param endpointPathMappers the endpoint path mappers
|
||||
* @param invokerAdvisors invoker advisors to apply
|
||||
* @param filters filters to apply
|
||||
*/
|
||||
public CloudFoundryWebEndpointDiscoverer(ApplicationContext applicationContext,
|
||||
ParameterValueMapper parameterValueMapper,
|
||||
EndpointMediaTypes endpointMediaTypes, PathMapper endpointPathMapper,
|
||||
EndpointMediaTypes endpointMediaTypes, List<PathMapper> endpointPathMappers,
|
||||
Collection<OperationInvokerAdvisor> invokerAdvisors,
|
||||
Collection<EndpointFilter<ExposableWebEndpoint>> filters) {
|
||||
super(applicationContext, parameterValueMapper, endpointMediaTypes,
|
||||
endpointPathMapper, invokerAdvisors, filters);
|
||||
endpointPathMappers, invokerAdvisors, filters);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
|
||||
import org.springframework.boot.actuate.health.HealthEndpoint;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension;
|
||||
@@ -95,9 +94,8 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
||||
WebClient.Builder webClientBuilder,
|
||||
ControllerEndpointsSupplier controllerEndpointsSupplier) {
|
||||
CloudFoundryWebEndpointDiscoverer endpointDiscoverer = new CloudFoundryWebEndpointDiscoverer(
|
||||
this.applicationContext, parameterMapper, endpointMediaTypes,
|
||||
PathMapper.useEndpointId(), Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
this.applicationContext, parameterMapper, endpointMediaTypes, null,
|
||||
Collections.emptyList(), Collections.emptyList());
|
||||
CloudFoundrySecurityInterceptor securityInterceptor = getSecurityInterceptor(
|
||||
webClientBuilder, this.applicationContext.getEnvironment());
|
||||
Collection<ExposableWebEndpoint> webEndpoints = endpointDiscoverer.getEndpoints();
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
|
||||
import org.springframework.boot.actuate.health.HealthEndpoint;
|
||||
@@ -99,9 +98,8 @@ public class CloudFoundryActuatorAutoConfiguration {
|
||||
ServletEndpointsSupplier servletEndpointsSupplier,
|
||||
ControllerEndpointsSupplier controllerEndpointsSupplier) {
|
||||
CloudFoundryWebEndpointDiscoverer discoverer = new CloudFoundryWebEndpointDiscoverer(
|
||||
this.applicationContext, parameterMapper, endpointMediaTypes,
|
||||
PathMapper.useEndpointId(), Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
this.applicationContext, parameterMapper, endpointMediaTypes, null,
|
||||
Collections.emptyList(), Collections.emptyList());
|
||||
CloudFoundrySecurityInterceptor securityInterceptor = getSecurityInterceptor(
|
||||
restTemplateBuilder, this.applicationContext.getEnvironment());
|
||||
Collection<ExposableWebEndpoint> webEndpoints = discoverer.getEndpoints();
|
||||
|
||||
@@ -21,6 +21,8 @@ import java.util.Map;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.EndpointId;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -29,6 +31,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
class MappingWebEndpointPathMapper implements PathMapper {
|
||||
|
||||
private final Map<EndpointId, String> pathMapping;
|
||||
@@ -42,8 +45,7 @@ class MappingWebEndpointPathMapper implements PathMapper {
|
||||
@Override
|
||||
public String getRootPath(EndpointId endpointId) {
|
||||
String path = this.pathMapping.get(endpointId);
|
||||
return StringUtils.hasText(path) ? path
|
||||
: PathMapper.useEndpointId().getRootPath(endpointId);
|
||||
return StringUtils.hasText(path) ? path : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -80,7 +80,6 @@ public class WebEndpointAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public PathMapper webEndpointPathMapper() {
|
||||
return new MappingWebEndpointPathMapper(this.properties.getPathMapping());
|
||||
}
|
||||
@@ -95,11 +94,13 @@ public class WebEndpointAutoConfiguration {
|
||||
@ConditionalOnMissingBean(WebEndpointsSupplier.class)
|
||||
public WebEndpointDiscoverer webEndpointDiscoverer(
|
||||
ParameterValueMapper parameterValueMapper,
|
||||
EndpointMediaTypes endpointMediaTypes, PathMapper webEndpointPathMapper,
|
||||
EndpointMediaTypes endpointMediaTypes,
|
||||
ObjectProvider<PathMapper> endpointPathMappers,
|
||||
ObjectProvider<OperationInvokerAdvisor> invokerAdvisors,
|
||||
ObjectProvider<EndpointFilter<ExposableWebEndpoint>> filters) {
|
||||
return new WebEndpointDiscoverer(this.applicationContext, parameterValueMapper,
|
||||
endpointMediaTypes, webEndpointPathMapper,
|
||||
endpointMediaTypes,
|
||||
endpointPathMappers.orderedStream().collect(Collectors.toList()),
|
||||
invokerAdvisors.orderedStream().collect(Collectors.toList()),
|
||||
filters.orderedStream().collect(Collectors.toList()));
|
||||
}
|
||||
@@ -107,10 +108,11 @@ public class WebEndpointAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ControllerEndpointsSupplier.class)
|
||||
public ControllerEndpointDiscoverer controllerEndpointDiscoverer(
|
||||
PathMapper webEndpointPathMapper,
|
||||
ObjectProvider<PathMapper> endpointPathMappers,
|
||||
ObjectProvider<Collection<EndpointFilter<ExposableControllerEndpoint>>> filters) {
|
||||
return new ControllerEndpointDiscoverer(this.applicationContext,
|
||||
webEndpointPathMapper, filters.getIfAvailable(Collections::emptyList));
|
||||
endpointPathMappers.orderedStream().collect(Collectors.toList()),
|
||||
filters.getIfAvailable(Collections::emptyList));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -144,10 +146,11 @@ public class WebEndpointAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ServletEndpointsSupplier.class)
|
||||
public ServletEndpointDiscoverer servletEndpointDiscoverer(
|
||||
ApplicationContext applicationContext, PathMapper webEndpointPathMapper,
|
||||
ApplicationContext applicationContext,
|
||||
ObjectProvider<PathMapper> endpointPathMappers,
|
||||
ObjectProvider<EndpointFilter<ExposableServletEndpoint>> filters) {
|
||||
return new ServletEndpointDiscoverer(applicationContext,
|
||||
webEndpointPathMapper,
|
||||
endpointPathMappers.orderedStream().collect(Collectors.toList()),
|
||||
filters.orderedStream().collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,8 @@ public class CloudFoundryWebEndpointDiscovererTests {
|
||||
Collections.singletonList("application/json"),
|
||||
Collections.singletonList("application/json"));
|
||||
CloudFoundryWebEndpointDiscoverer discoverer = new CloudFoundryWebEndpointDiscoverer(
|
||||
context, parameterMapper, mediaTypes, endpointPathMapper,
|
||||
context, parameterMapper, mediaTypes,
|
||||
Collections.singletonList(endpointPathMapper),
|
||||
Collections.singleton(new CachingOperationInvokerAdvisor(timeToLive)),
|
||||
Collections.emptyList());
|
||||
consumer.accept(discoverer);
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServic
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
|
||||
@@ -220,8 +219,8 @@ public class CloudFoundryWebFluxEndpointIntegrationTests {
|
||||
ParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
|
||||
DefaultConversionService.getSharedInstance());
|
||||
return new WebEndpointDiscoverer(applicationContext, parameterMapper,
|
||||
endpointMediaTypes, PathMapper.useEndpointId(),
|
||||
Collections.emptyList(), Collections.emptyList());
|
||||
endpointMediaTypes, null, Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServic
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
|
||||
@@ -219,8 +218,8 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
ParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
|
||||
DefaultConversionService.getSharedInstance());
|
||||
return new WebEndpointDiscoverer(applicationContext, parameterMapper,
|
||||
endpointMediaTypes, PathMapper.useEndpointId(),
|
||||
Collections.emptyList(), Collections.emptyList());
|
||||
endpointMediaTypes, null, Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Collections;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.EndpointId;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -35,29 +36,32 @@ public class MappingWebEndpointPathMapperTests {
|
||||
public void defaultConfiguration() {
|
||||
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
|
||||
Collections.emptyMap());
|
||||
assertThat(mapper.getRootPath(EndpointId.of("test"))).isEqualTo("test");
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
|
||||
EndpointId.of("test"))).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userConfiguration() {
|
||||
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
|
||||
Collections.singletonMap("test", "custom"));
|
||||
assertThat(mapper.getRootPath(EndpointId.of("test"))).isEqualTo("custom");
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
|
||||
EndpointId.of("test"))).isEqualTo("custom");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mixedCaseDefaultConfiguration() {
|
||||
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
|
||||
Collections.emptyMap());
|
||||
assertThat(mapper.getRootPath(EndpointId.of("testEndpoint")))
|
||||
.isEqualTo("testEndpoint");
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
|
||||
EndpointId.of("testEndpoint"))).isEqualTo("testEndpoint");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mixedCaseUserConfiguration() {
|
||||
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
|
||||
Collections.singletonMap("test-endpoint", "custom"));
|
||||
assertThat(mapper.getRootPath(EndpointId.of("testEndpoint"))).isEqualTo("custom");
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
|
||||
EndpointId.of("testEndpoint"))).isEqualTo("custom");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,13 +16,21 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.ExposeExcludePropertyEndpointFilter;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointId;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointDiscoverer;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointDiscoverer;
|
||||
@@ -30,6 +38,7 @@ import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDisco
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -71,6 +80,27 @@ public class WebEndpointAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void webApplicationSupportCustomPathMatcher() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*",
|
||||
"management.endpoints.web.path-mapping.testanotherone=foo")
|
||||
.withUserConfiguration(TestPathMatcher.class, TestOneEndpoint.class,
|
||||
TestAnotherOneEndpoint.class, TestTwoEndpoint.class)
|
||||
.run((context) -> {
|
||||
WebEndpointDiscoverer discoverer = context
|
||||
.getBean(WebEndpointDiscoverer.class);
|
||||
Collection<ExposableWebEndpoint> endpoints = discoverer
|
||||
.getEndpoints();
|
||||
ExposableWebEndpoint[] webEndpoints = endpoints
|
||||
.toArray(new ExposableWebEndpoint[0]);
|
||||
List<String> paths = Arrays.stream(webEndpoints)
|
||||
.map(PathMappedEndpoint::getRootPath)
|
||||
.collect(Collectors.toList());
|
||||
assertThat(paths).containsOnly("1/testone", "foo", "testtwo");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void webApplicationConfiguresEndpointDiscoverer() {
|
||||
this.contextRunner.run((context) -> {
|
||||
@@ -100,4 +130,35 @@ public class WebEndpointAutoConfigurationTests {
|
||||
.doesNotHaveBean(ServletEndpointDiscoverer.class));
|
||||
}
|
||||
|
||||
@Component
|
||||
private static class TestPathMatcher implements PathMapper {
|
||||
|
||||
@Override
|
||||
public String getRootPath(EndpointId endpointId) {
|
||||
if (endpointId.toString().endsWith("one")) {
|
||||
return "1/" + endpointId.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
@Endpoint(id = "testone")
|
||||
private static class TestOneEndpoint {
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
@Endpoint(id = "testanotherone")
|
||||
private static class TestAnotherOneEndpoint {
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
@Endpoint(id = "testtwo")
|
||||
private static class TestTwoEndpoint {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpoi
|
||||
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
|
||||
import org.springframework.boot.actuate.endpoint.web.ExposableServletEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointDiscoverer;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
@@ -102,8 +101,8 @@ public class JolokiaEndpointAutoConfigurationTests {
|
||||
@Bean
|
||||
public ServletEndpointDiscoverer servletEndpointDiscoverer(
|
||||
ApplicationContext applicationContext) {
|
||||
return new ServletEndpointDiscoverer(applicationContext,
|
||||
PathMapper.useEndpointId(), Collections.emptyList());
|
||||
return new ServletEndpointDiscoverer(applicationContext, null,
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.web;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.EndpointId;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Strategy interface used to provide a mapping between an endpoint ID and the root path
|
||||
@@ -30,18 +34,42 @@ import org.springframework.boot.actuate.endpoint.EndpointId;
|
||||
public interface PathMapper {
|
||||
|
||||
/**
|
||||
* Resolve the root path for the endpoint with the specified {@code endpointId}.
|
||||
* Resolve the root path for the specified {@code endpointId}.
|
||||
* @param endpointId the id of an endpoint
|
||||
* @return the path of the endpoint
|
||||
* @return the path of the endpoint or {@code null} if this mapper doesn't support the
|
||||
* given endpoint ID
|
||||
*/
|
||||
String getRootPath(EndpointId endpointId);
|
||||
|
||||
/**
|
||||
* Returns an {@link PathMapper} that uses the endpoint ID as the path.
|
||||
* @return an {@link PathMapper} that uses the lowercase endpoint ID as the path
|
||||
* @deprecated since 2.1.0 in favor of {@link #getRootPath(List, EndpointId)} with a
|
||||
* {@code null} list
|
||||
*/
|
||||
@Deprecated
|
||||
static PathMapper useEndpointId() {
|
||||
return (id) -> id.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the root path for the specified {@code endpointId} from the given path
|
||||
* mappers. If no mapper matches then the ID itself is returned.
|
||||
* @param pathMappers the path mappers (may be {@code null})
|
||||
* @param endpointId the id of an endpoint
|
||||
* @return the path of the endpoint
|
||||
*/
|
||||
static String getRootPath(List<PathMapper> pathMappers, EndpointId endpointId) {
|
||||
Assert.notNull(endpointId, "EndpointId must not be null");
|
||||
if (pathMappers != null) {
|
||||
for (PathMapper mapper : pathMappers) {
|
||||
String path = mapper.getRootPath(endpointId);
|
||||
if (StringUtils.hasText(path)) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
return endpointId.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.boot.actuate.endpoint.web.annotation;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointId;
|
||||
@@ -29,7 +30,6 @@ import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -43,21 +43,20 @@ public class ControllerEndpointDiscoverer
|
||||
extends EndpointDiscoverer<ExposableControllerEndpoint, Operation>
|
||||
implements ControllerEndpointsSupplier {
|
||||
|
||||
private final PathMapper endpointPathMapper;
|
||||
private final List<PathMapper> endpointPathMappers;
|
||||
|
||||
/**
|
||||
* Create a new {@link ControllerEndpointDiscoverer} instance.
|
||||
* @param applicationContext the source application context
|
||||
* @param endpointPathMapper the endpoint path mapper
|
||||
* @param endpointPathMappers the endpoint path mappers
|
||||
* @param filters filters to apply
|
||||
*/
|
||||
public ControllerEndpointDiscoverer(ApplicationContext applicationContext,
|
||||
PathMapper endpointPathMapper,
|
||||
List<PathMapper> endpointPathMappers,
|
||||
Collection<EndpointFilter<ExposableControllerEndpoint>> filters) {
|
||||
super(applicationContext, ParameterValueMapper.NONE, Collections.emptyList(),
|
||||
filters);
|
||||
Assert.notNull(endpointPathMapper, "EndpointPathMapper must not be null");
|
||||
this.endpointPathMapper = endpointPathMapper;
|
||||
this.endpointPathMappers = endpointPathMappers;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,7 +69,7 @@ public class ControllerEndpointDiscoverer
|
||||
@Override
|
||||
protected ExposableControllerEndpoint createEndpoint(Object endpointBean,
|
||||
EndpointId id, boolean enabledByDefault, Collection<Operation> operations) {
|
||||
String rootPath = this.endpointPathMapper.getRootPath(id);
|
||||
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, id);
|
||||
return new DiscoveredControllerEndpoint(this, endpointBean, id, rootPath,
|
||||
enabledByDefault);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.boot.actuate.endpoint.web.annotation;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointId;
|
||||
@@ -30,7 +31,6 @@ import org.springframework.boot.actuate.endpoint.web.ExposableServletEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -43,21 +43,20 @@ public class ServletEndpointDiscoverer
|
||||
extends EndpointDiscoverer<ExposableServletEndpoint, Operation>
|
||||
implements ServletEndpointsSupplier {
|
||||
|
||||
private final PathMapper endpointPathMapper;
|
||||
private final List<PathMapper> endpointPathMappers;
|
||||
|
||||
/**
|
||||
* Create a new {@link ServletEndpointDiscoverer} instance.
|
||||
* @param applicationContext the source application context
|
||||
* @param endpointPathMapper the endpoint path mapper
|
||||
* @param endpointPathMappers the endpoint path mappers
|
||||
* @param filters filters to apply
|
||||
*/
|
||||
public ServletEndpointDiscoverer(ApplicationContext applicationContext,
|
||||
PathMapper endpointPathMapper,
|
||||
List<PathMapper> endpointPathMappers,
|
||||
Collection<EndpointFilter<ExposableServletEndpoint>> filters) {
|
||||
super(applicationContext, ParameterValueMapper.NONE, Collections.emptyList(),
|
||||
filters);
|
||||
Assert.notNull(endpointPathMapper, "EndpointPathMapper must not be null");
|
||||
this.endpointPathMapper = endpointPathMapper;
|
||||
this.endpointPathMappers = endpointPathMappers;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,7 +68,7 @@ public class ServletEndpointDiscoverer
|
||||
@Override
|
||||
protected ExposableServletEndpoint createEndpoint(Object endpointBean, EndpointId id,
|
||||
boolean enabledByDefault, Collection<Operation> operations) {
|
||||
String rootPath = this.endpointPathMapper.getRootPath(id);
|
||||
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, id);
|
||||
return new DiscoveredServletEndpoint(this, endpointBean, id, rootPath,
|
||||
enabledByDefault);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.actuate.endpoint.web.annotation;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointId;
|
||||
@@ -32,7 +33,6 @@ import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier;
|
||||
import org.springframework.boot.actuate.endpoint.web.WebOperation;
|
||||
import org.springframework.boot.actuate.endpoint.web.WebOperationRequestPredicate;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link EndpointDiscoverer} for {@link ExposableWebEndpoint web endpoints}.
|
||||
@@ -44,7 +44,7 @@ public class WebEndpointDiscoverer
|
||||
extends EndpointDiscoverer<ExposableWebEndpoint, WebOperation>
|
||||
implements WebEndpointsSupplier {
|
||||
|
||||
private final PathMapper endpointPathMapper;
|
||||
private final List<PathMapper> endpointPathMappers;
|
||||
|
||||
private final RequestPredicateFactory requestPredicateFactory;
|
||||
|
||||
@@ -53,25 +53,24 @@ public class WebEndpointDiscoverer
|
||||
* @param applicationContext the source application context
|
||||
* @param parameterValueMapper the parameter value mapper
|
||||
* @param endpointMediaTypes the endpoint media types
|
||||
* @param endpointPathMapper the endpoint path mapper
|
||||
* @param endpointPathMappers the endpoint path mappers
|
||||
* @param invokerAdvisors invoker advisors to apply
|
||||
* @param filters filters to apply
|
||||
*/
|
||||
public WebEndpointDiscoverer(ApplicationContext applicationContext,
|
||||
ParameterValueMapper parameterValueMapper,
|
||||
EndpointMediaTypes endpointMediaTypes, PathMapper endpointPathMapper,
|
||||
EndpointMediaTypes endpointMediaTypes, List<PathMapper> endpointPathMappers,
|
||||
Collection<OperationInvokerAdvisor> invokerAdvisors,
|
||||
Collection<EndpointFilter<ExposableWebEndpoint>> filters) {
|
||||
super(applicationContext, parameterValueMapper, invokerAdvisors, filters);
|
||||
Assert.notNull(endpointPathMapper, "EndpointPathMapper must not be null");
|
||||
this.endpointPathMapper = endpointPathMapper;
|
||||
this.endpointPathMappers = endpointPathMappers;
|
||||
this.requestPredicateFactory = new RequestPredicateFactory(endpointMediaTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExposableWebEndpoint createEndpoint(Object endpointBean, EndpointId id,
|
||||
boolean enabledByDefault, Collection<WebOperation> operations) {
|
||||
String rootPath = this.endpointPathMapper.getRootPath(id);
|
||||
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, id);
|
||||
return new DiscoveredWebEndpoint(this, endpointBean, id, rootPath,
|
||||
enabledByDefault, operations);
|
||||
}
|
||||
@@ -79,7 +78,7 @@ public class WebEndpointDiscoverer
|
||||
@Override
|
||||
protected WebOperation createOperation(EndpointId endpointId,
|
||||
DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
|
||||
String rootPath = this.endpointPathMapper.getRootPath(endpointId);
|
||||
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, endpointId);
|
||||
WebOperationRequestPredicate requestPredicate = this.requestPredicateFactory
|
||||
.getRequestPredicate(endpointId, rootPath, operationMethod);
|
||||
return new DiscoveredWebOperation(endpointId, operationMethod, invoker,
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServiceParameterValueMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -68,7 +67,7 @@ class BaseConfiguration {
|
||||
ParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
|
||||
DefaultConversionService.getSharedInstance());
|
||||
return new WebEndpointDiscoverer(applicationContext, parameterMapper,
|
||||
endpointMediaTypes(), PathMapper.useEndpointId(), Collections.emptyList(),
|
||||
endpointMediaTypes(), null, Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
|
||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||
@@ -153,7 +152,7 @@ public class ControllerEndpointDiscovererTests {
|
||||
Consumer<ControllerEndpointDiscoverer> consumer) {
|
||||
return (context) -> {
|
||||
ControllerEndpointDiscoverer discoverer = new ControllerEndpointDiscoverer(
|
||||
context, PathMapper.useEndpointId(), Collections.emptyList());
|
||||
context, null, Collections.emptyList());
|
||||
consumer.accept(discoverer);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointServlet;
|
||||
import org.springframework.boot.actuate.endpoint.web.ExposableServletEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
|
||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||
@@ -152,7 +151,7 @@ public class ServletEndpointDiscovererTests {
|
||||
Consumer<ServletEndpointDiscoverer> consumer) {
|
||||
return (context) -> {
|
||||
ServletEndpointDiscoverer discoverer = new ServletEndpointDiscoverer(context,
|
||||
PathMapper.useEndpointId(), Collections.emptyList());
|
||||
null, Collections.emptyList());
|
||||
consumer.accept(discoverer);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -261,7 +261,8 @@ public class WebEndpointDiscovererTests {
|
||||
Collections.singletonList("application/json"),
|
||||
Collections.singletonList("application/json"));
|
||||
WebEndpointDiscoverer discoverer = new WebEndpointDiscoverer(context,
|
||||
parameterMapper, mediaTypes, endpointPathMapper,
|
||||
parameterMapper, mediaTypes,
|
||||
Collections.singletonList(endpointPathMapper),
|
||||
Collections.singleton(new CachingOperationInvokerAdvisor(timeToLive)),
|
||||
Collections.emptyList());
|
||||
consumer.accept(discoverer);
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.util.function.Consumer;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointDiscoverer;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint;
|
||||
@@ -128,8 +127,8 @@ public class ControllerEndpointHandlerMappingIntegrationTests {
|
||||
@Bean
|
||||
public ControllerEndpointDiscoverer webEndpointDiscoverer(
|
||||
ApplicationContext applicationContext) {
|
||||
return new ControllerEndpointDiscoverer(applicationContext,
|
||||
PathMapper.useEndpointId(), Collections.emptyList());
|
||||
return new ControllerEndpointDiscoverer(applicationContext, null,
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.util.function.Consumer;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointDiscoverer;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint;
|
||||
@@ -122,8 +121,8 @@ public class ControllerEndpointHandlerMappingIntegrationTests {
|
||||
@Bean
|
||||
public ControllerEndpointDiscoverer webEndpointDiscoverer(
|
||||
ApplicationContext applicationContext) {
|
||||
return new ControllerEndpointDiscoverer(applicationContext,
|
||||
PathMapper.useEndpointId(), Collections.emptyList());
|
||||
return new ControllerEndpointDiscoverer(applicationContext, null,
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -34,7 +34,6 @@ import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServic
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
|
||||
import org.springframework.boot.actuate.endpoint.web.jersey.JerseyEndpointResourceFactory;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
@@ -102,8 +101,8 @@ class JerseyEndpointsRunner extends AbstractWebEndpointRunner {
|
||||
mediaTypes);
|
||||
WebEndpointDiscoverer discoverer = new WebEndpointDiscoverer(
|
||||
this.applicationContext, new ConversionServiceParameterValueMapper(),
|
||||
endpointMediaTypes, PathMapper.useEndpointId(),
|
||||
Collections.emptyList(), Collections.emptyList());
|
||||
endpointMediaTypes, null, Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
Collection<Resource> resources = new JerseyEndpointResourceFactory()
|
||||
.createEndpointResources(new EndpointMapping("/actuator"),
|
||||
discoverer.getEndpoints(), endpointMediaTypes,
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServic
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
|
||||
import org.springframework.boot.actuate.endpoint.web.reactive.WebFluxEndpointHandlerMapping;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
@@ -108,8 +107,8 @@ class WebFluxEndpointsRunner extends AbstractWebEndpointRunner {
|
||||
mediaTypes);
|
||||
WebEndpointDiscoverer discoverer = new WebEndpointDiscoverer(
|
||||
this.applicationContext, new ConversionServiceParameterValueMapper(),
|
||||
endpointMediaTypes, PathMapper.useEndpointId(),
|
||||
Collections.emptyList(), Collections.emptyList());
|
||||
endpointMediaTypes, null, Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
return new WebFluxEndpointHandlerMapping(new EndpointMapping("/actuator"),
|
||||
discoverer.getEndpoints(), endpointMediaTypes,
|
||||
new CorsConfiguration(),
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServic
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
|
||||
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
@@ -91,8 +90,8 @@ class WebMvcEndpointRunner extends AbstractWebEndpointRunner {
|
||||
mediaTypes);
|
||||
WebEndpointDiscoverer discoverer = new WebEndpointDiscoverer(
|
||||
this.applicationContext, new ConversionServiceParameterValueMapper(),
|
||||
endpointMediaTypes, PathMapper.useEndpointId(),
|
||||
Collections.emptyList(), Collections.emptyList());
|
||||
endpointMediaTypes, null, Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
return new WebMvcEndpointHandlerMapping(new EndpointMapping("/actuator"),
|
||||
discoverer.getEndpoints(), endpointMediaTypes,
|
||||
new CorsConfiguration(),
|
||||
|
||||
Reference in New Issue
Block a user