Add HandlerMethod and HandlerFunction details to mappings endpoint
Closes gh-11864
This commit is contained in:
parent
7ed4273fc3
commit
2c19257d6d
|
|
@ -40,7 +40,7 @@ When using Spring MVC, the response contains details of any `DispatcherServlet`
|
|||
request mappings beneath `contexts.*.mappings.dispatcherServlets`. The following
|
||||
table describes the structure of this section of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}mappings/response-fields-dispatcher-servlets.adoc[]
|
||||
|
||||
|
||||
|
|
@ -69,12 +69,12 @@ include::{snippets}mappings/response-fields-servlet-filters.adoc[]
|
|||
|
||||
|
||||
|
||||
[[mappings-retrieving-response-structure-dispatcher-servlets]]
|
||||
[[mappings-retrieving-response-structure-dispatcher-handlers]]
|
||||
=== Dispatcher Handlers Response Structure
|
||||
|
||||
When using Spring WebFlux, the response contains details of any `DispatcherHandler`
|
||||
request mappings beneath `contexts.*.mappings.dispatcherHandlers`. The following
|
||||
table describes the structure of this section of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}mappings/response-fields-dispatcher-handlers.adoc[]
|
||||
|
|
|
|||
|
|
@ -35,8 +35,13 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.payload.JsonFieldType;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.beneathPath;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
|
|
@ -84,7 +89,37 @@ public class MappingsEndpointReactiveDocumentationTests
|
|||
fieldWithPath("*.[].handler")
|
||||
.description("Handler for the mapping."),
|
||||
fieldWithPath("*.[].predicate")
|
||||
.description("Predicate for the mapping."))));
|
||||
.description("Predicate for the mapping."),
|
||||
fieldWithPath("*.[].details").optional()
|
||||
.type(JsonFieldType.OBJECT)
|
||||
.description("Additional implementation-specific "
|
||||
+ "details about the mapping. Optional."),
|
||||
fieldWithPath("*.[].details.handlerMethod").optional()
|
||||
.type(JsonFieldType.OBJECT)
|
||||
.description("Details of the method, if any, "
|
||||
+ "that will handle requests to "
|
||||
+ "this mapping."),
|
||||
fieldWithPath("*.[].details.handlerMethod.className")
|
||||
.type(JsonFieldType.STRING)
|
||||
.description("Fully qualified name of the class"
|
||||
+ " of the method."),
|
||||
fieldWithPath("*.[].details.handlerMethod.name")
|
||||
.type(JsonFieldType.STRING)
|
||||
.description("Name of the method."),
|
||||
fieldWithPath("*.[].details.handlerMethod.descriptor")
|
||||
.type(JsonFieldType.STRING)
|
||||
.description("Descriptor of the method as "
|
||||
+ "specified in the Java Language "
|
||||
+ "Specification."),
|
||||
fieldWithPath("*.[].details.handlerFunction")
|
||||
.optional().type(JsonFieldType.OBJECT)
|
||||
.description("Details of the function, if any, "
|
||||
+ "that will handle requests to this "
|
||||
+ "mapping."),
|
||||
fieldWithPath("*.[].details.handlerFunction.className")
|
||||
.type(JsonFieldType.STRING).description(
|
||||
"Fully qualified name of the class of "
|
||||
+ "the function."))));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
|
@ -108,6 +143,12 @@ public class MappingsEndpointReactiveDocumentationTests
|
|||
return new MappingsEndpoint(descriptionProviders, context);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> exampleRouter() {
|
||||
return RouterFunctions.route(RequestPredicates.GET("/foo"),
|
||||
(request) -> ServerResponse.ok().build());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,28 @@ public class MappingsEndpointServletDocumentationTests
|
|||
fieldWithPath("*.[].handler")
|
||||
.description("Handler for the mapping."),
|
||||
fieldWithPath("*.[].predicate")
|
||||
.description("Predicate for the mapping.")),
|
||||
.description("Predicate for the mapping."),
|
||||
fieldWithPath("*.[].details").optional()
|
||||
.type(JsonFieldType.OBJECT)
|
||||
.description("Additional implementation-specific "
|
||||
+ "details about the mapping. Optional."),
|
||||
fieldWithPath("*.[].details.handlerMethod").optional()
|
||||
.type(JsonFieldType.OBJECT)
|
||||
.description("Details of the method, if any, "
|
||||
+ "that will handle requests to "
|
||||
+ "this mapping."),
|
||||
fieldWithPath("*.[].details.handlerMethod.className")
|
||||
.type(JsonFieldType.STRING)
|
||||
.description("Fully qualified name of the class"
|
||||
+ " of the method."),
|
||||
fieldWithPath("*.[].details.handlerMethod.name")
|
||||
.type(JsonFieldType.STRING)
|
||||
.description("Name of the method."),
|
||||
fieldWithPath("*.[].details.handlerMethod.descriptor")
|
||||
.type(JsonFieldType.STRING)
|
||||
.description("Descriptor of the method as "
|
||||
+ "specified in the Java Language "
|
||||
+ "Specification.")),
|
||||
responseFields(
|
||||
beneathPath("contexts.*.mappings.servletFilters")
|
||||
.withSubsectionId("servlet-filters"),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.web.mappings;
|
||||
|
||||
import org.springframework.asm.Type;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
|
||||
/**
|
||||
* A description of a {@link HandlerMethod}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class HandlerMethodDescription {
|
||||
|
||||
private final String className;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String descriptor;
|
||||
|
||||
public HandlerMethodDescription(HandlerMethod handlerMethod) {
|
||||
this.name = handlerMethod.getMethod().getName();
|
||||
this.className = handlerMethod.getMethod().getDeclaringClass().getCanonicalName();
|
||||
this.descriptor = Type.getMethodDescriptor(handlerMethod.getMethod());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getDescriptor() {
|
||||
return this.descriptor;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return this.className;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -30,9 +30,13 @@ public class DispatcherHandlerMappingDescription {
|
|||
|
||||
private final String handler;
|
||||
|
||||
DispatcherHandlerMappingDescription(String predicate, String handler) {
|
||||
private final DispatcherHandlerMappingDetails details;
|
||||
|
||||
DispatcherHandlerMappingDescription(String predicate, String handler,
|
||||
DispatcherHandlerMappingDetails details) {
|
||||
this.predicate = predicate;
|
||||
this.handler = handler;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public String getHandler() {
|
||||
|
|
@ -43,4 +47,8 @@ public class DispatcherHandlerMappingDescription {
|
|||
return this.predicate;
|
||||
}
|
||||
|
||||
public DispatcherHandlerMappingDetails getDetails() {
|
||||
return this.details;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.web.mappings.reactive;
|
||||
|
||||
import org.springframework.boot.actuate.web.mappings.HandlerMethodDescription;
|
||||
import org.springframework.web.reactive.DispatcherHandler;
|
||||
|
||||
/**
|
||||
* Details of a {@link DispatcherHandler} mapping.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class DispatcherHandlerMappingDetails {
|
||||
|
||||
private HandlerMethodDescription handlerMethod;
|
||||
|
||||
private HandlerFunctionDescription handlerFunction;
|
||||
|
||||
private RequestMappingConditionsDescription requestMappingConditions;
|
||||
|
||||
public HandlerMethodDescription getHandlerMethod() {
|
||||
return this.handlerMethod;
|
||||
}
|
||||
|
||||
void setHandlerMethod(HandlerMethodDescription handlerMethod) {
|
||||
this.handlerMethod = handlerMethod;
|
||||
}
|
||||
|
||||
public HandlerFunctionDescription getHandlerFunction() {
|
||||
return this.handlerFunction;
|
||||
}
|
||||
|
||||
void setHandlerFunction(HandlerFunctionDescription handlerFunction) {
|
||||
this.handlerFunction = handlerFunction;
|
||||
}
|
||||
|
||||
public RequestMappingConditionsDescription getRequestMappingConditions() {
|
||||
return this.requestMappingConditions;
|
||||
}
|
||||
|
||||
void setRequestMappingConditions(
|
||||
RequestMappingConditionsDescription requestMappingConditions) {
|
||||
this.requestMappingConditions = requestMappingConditions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@ import java.util.stream.Stream;
|
|||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.boot.actuate.web.mappings.HandlerMethodDescription;
|
||||
import org.springframework.boot.actuate.web.mappings.MappingDescriptionProvider;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
|
@ -121,8 +122,11 @@ public class DispatcherHandlersMappingDescriptionProvider
|
|||
|
||||
private DispatcherHandlerMappingDescription describe(
|
||||
Entry<RequestMappingInfo, HandlerMethod> mapping) {
|
||||
DispatcherHandlerMappingDetails handlerMapping = new DispatcherHandlerMappingDetails();
|
||||
handlerMapping
|
||||
.setHandlerMethod(new HandlerMethodDescription(mapping.getValue()));
|
||||
return new DispatcherHandlerMappingDescription(mapping.getKey().toString(),
|
||||
mapping.getValue().toString());
|
||||
mapping.getValue().toString(), handlerMapping);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -145,7 +149,8 @@ public class DispatcherHandlersMappingDescriptionProvider
|
|||
private DispatcherHandlerMappingDescription describe(
|
||||
Entry<PathPattern, Object> mapping) {
|
||||
return new DispatcherHandlerMappingDescription(
|
||||
mapping.getKey().getPatternString(), mapping.getValue().toString());
|
||||
mapping.getKey().getPatternString(), mapping.getValue().toString(),
|
||||
null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -186,8 +191,10 @@ public class DispatcherHandlersMappingDescriptionProvider
|
|||
@Override
|
||||
public void route(RequestPredicate predicate,
|
||||
HandlerFunction<?> handlerFunction) {
|
||||
DispatcherHandlerMappingDetails details = new DispatcherHandlerMappingDetails();
|
||||
details.setHandlerFunction(new HandlerFunctionDescription(handlerFunction));
|
||||
this.descriptions.add(new DispatcherHandlerMappingDescription(
|
||||
predicate.toString(), handlerFunction.toString()));
|
||||
predicate.toString(), handlerFunction.toString(), details));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.web.mappings.reactive;
|
||||
|
||||
import org.springframework.web.reactive.function.server.HandlerFunction;
|
||||
|
||||
/**
|
||||
* Description of a {@link HandlerFunction}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class HandlerFunctionDescription {
|
||||
|
||||
private final String className;
|
||||
|
||||
HandlerFunctionDescription(HandlerFunction<?> handlerFunction) {
|
||||
this.className = handlerFunction.getClass().getCanonicalName();
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return this.className;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -30,32 +30,25 @@ public class DispatcherServletMappingDescription {
|
|||
|
||||
private final String predicate;
|
||||
|
||||
/**
|
||||
* Creates a new {@code DispatcherServletMappingDescription} for the given
|
||||
* {@code handler} that will receives requests that match the given {@code predicate}.
|
||||
*
|
||||
* @param predicate the predicate
|
||||
* @param handler the handler
|
||||
*/
|
||||
public DispatcherServletMappingDescription(String predicate, String handler) {
|
||||
private final DispatcherServletMappingDetails details;
|
||||
|
||||
DispatcherServletMappingDescription(String predicate, String handler,
|
||||
DispatcherServletMappingDetails details) {
|
||||
this.handler = handler;
|
||||
this.predicate = predicate;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the handler for the described mapping.
|
||||
* @return the handler
|
||||
*/
|
||||
public String getHandler() {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the predicate for the described mapping.
|
||||
* @return the predicate
|
||||
*/
|
||||
public String getPredicate() {
|
||||
return this.predicate;
|
||||
}
|
||||
|
||||
public DispatcherServletMappingDetails getDetails() {
|
||||
return this.details;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.web.mappings.servlet;
|
||||
|
||||
import org.springframework.boot.actuate.web.mappings.HandlerMethodDescription;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
/**
|
||||
* Details of a {@link DispatcherServlet} mapping.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class DispatcherServletMappingDetails {
|
||||
|
||||
private final HandlerMethodDescription handlerMethod;
|
||||
|
||||
DispatcherServletMappingDetails(HandlerMethodDescription handlerMethod) {
|
||||
this.handlerMethod = handlerMethod;
|
||||
}
|
||||
|
||||
public HandlerMethodDescription getHandlerMethod() {
|
||||
return this.handlerMethod;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ import java.util.Map.Entry;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.boot.actuate.web.mappings.HandlerMethodDescription;
|
||||
import org.springframework.boot.actuate.web.mappings.MappingDescriptionProvider;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping;
|
||||
|
|
@ -140,7 +141,8 @@ public class DispatcherServletsMappingDescriptionProvider
|
|||
private DispatcherServletMappingDescription describe(
|
||||
Entry<RequestMappingInfo, HandlerMethod> mapping) {
|
||||
return new DispatcherServletMappingDescription(mapping.getKey().toString(),
|
||||
mapping.getValue().toString());
|
||||
mapping.getValue().toString(), new DispatcherServletMappingDetails(
|
||||
new HandlerMethodDescription(mapping.getValue())));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -163,7 +165,7 @@ public class DispatcherServletsMappingDescriptionProvider
|
|||
private DispatcherServletMappingDescription describe(
|
||||
Entry<String, Object> mapping) {
|
||||
return new DispatcherServletMappingDescription(mapping.getKey().toString(),
|
||||
mapping.getValue().toString());
|
||||
mapping.getValue().toString(), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue