提交 67330dfc 编写于 作者: R Rossen Stoyanchev

Expose mapped handler as an exchange attribute

Issue: SPR-15564
上级 58a5e7f1
......@@ -31,29 +31,31 @@ import org.springframework.web.server.ServerWebExchange;
public interface HandlerMapping {
/**
* Name of the {@link ServerWebExchange} attribute that contains the
* best matching pattern within the handler mapping.
* <p>Note: This attribute is not required to be supported by all
* HandlerMapping implementations. URL-based HandlerMappings will
* typically support it, but handlers should not necessarily expect
* this request attribute to be present in all scenarios.
* Name of the {@link ServerWebExchange#getAttributes() attribute} that
* contains the mapped handler for the best matching pattern.
*/
String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";
/**
* Name of the {@link ServerWebExchange#getAttributes() attribute} that
* contains the best matching pattern within the handler mapping.
*/
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
/**
* Name of the {@link ServerWebExchange} attribute that contains the path
* within the handler mapping, in case of a pattern match, or the full
* relevant URI (typically within the DispatcherServlet's mapping) else.
* Name of the {@link ServerWebExchange#getAttributes() attribute} that
* contains the path within the handler mapping, in case of a pattern match
* such as {@code "/static/**"} or the full relevant URI otherwise.
* <p>Note: This attribute is not required to be supported by all
* HandlerMapping implementations. URL-based HandlerMappings will
* typically support it, but handlers should not necessarily expect
* typically support it but handlers should not necessarily expect
* this request attribute to be present in all scenarios.
*/
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
/**
* Name of the {@link ServerWebExchange} attribute that contains the URI
* templates map, mapping variable names to values.
* Name of the {@link ServerWebExchange#getAttributes() attribute} that
* contains the URI templates map mapping variable names to values.
* <p>Note: This attribute is not required to be supported by all
* HandlerMapping implementations. URL-based HandlerMappings will
* typically support it, but handlers should not necessarily expect
......@@ -62,8 +64,9 @@ public interface HandlerMapping {
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
/**
* Name of the {@link ServerWebExchange} attribute that contains a map with
* URI matrix variables.
* Name of the {@link ServerWebExchange#getAttributes() attribute} that
* contains a map with URI variable names and a corresponding MultiValueMap
* of URI matrix variables for each.
* <p>Note: This attribute is not required to be supported by all
* HandlerMapping implementations and may also not be present depending on
* whether the HandlerMapping is configured to keep matrix variable content
......@@ -72,8 +75,8 @@ public interface HandlerMapping {
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
/**
* Name of the {@link ServerWebExchange} attribute that contains the set of
* producible MediaTypes applicable to the mapped handler.
* Name of the {@link ServerWebExchange#getAttributes() attribute} containing
* the set of producible MediaType's applicable to the mapped handler.
* <p>Note: This attribute is not required to be supported by all
* HandlerMapping implementations. Handlers should not necessarily expect
* this request attribute to be present in all scenarios.
......
......@@ -145,8 +145,9 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
validateHandler(handler, exchange);
exchange.getAttributes().put(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathWithinMapping);
exchange.getAttributes().put(BEST_MATCHING_HANDLER_ATTRIBUTE, handler);
exchange.getAttributes().put(BEST_MATCHING_PATTERN_ATTRIBUTE, bestMatch);
exchange.getAttributes().put(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathWithinMapping);
return handler;
}
......
......@@ -322,7 +322,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
lookupPath + "': {" + m1 + ", " + m2 + "}");
}
}
handleMatch(bestMatch.mapping, lookupPath, exchange);
handleMatch(bestMatch.mapping, bestMatch.handlerMethod, lookupPath, exchange);
return bestMatch.handlerMethod;
}
else {
......@@ -342,10 +342,12 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
/**
* Invoked when a matching mapping is found.
* @param mapping the matching mapping
* @param handlerMethod the matching method
* @param lookupPath the lookup path within the current mapping
* @param exchange the current exchange
*/
protected void handleMatch(T mapping, String lookupPath, ServerWebExchange exchange) {
protected void handleMatch(T mapping, HandlerMethod handlerMethod, String lookupPath,
ServerWebExchange exchange) {
}
/**
......
......@@ -106,8 +106,10 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
* @see HandlerMapping#PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE
*/
@Override
protected void handleMatch(RequestMappingInfo info, String lookupPath, ServerWebExchange exchange) {
super.handleMatch(info, lookupPath, exchange);
protected void handleMatch(RequestMappingInfo info, HandlerMethod handlerMethod, String lookupPath,
ServerWebExchange exchange) {
super.handleMatch(info, handlerMethod, lookupPath, exchange);
PathPattern bestPattern;
Map<String, String> uriVariables;
......@@ -133,6 +135,7 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
));
}
exchange.getAttributes().put(BEST_MATCHING_HANDLER_ATTRIBUTE, handlerMethod);
exchange.getAttributes().put(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern);
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriVariables);
......
......@@ -39,6 +39,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.util.ClassUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
......@@ -60,6 +61,7 @@ import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.get;
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.method;
......@@ -69,6 +71,8 @@ import static org.springframework.web.bind.annotation.RequestMethod.OPTIONS;
import static org.springframework.web.method.MvcAnnotationPredicates.getMapping;
import static org.springframework.web.method.MvcAnnotationPredicates.requestMapping;
import static org.springframework.web.method.ResolvableMethod.on;
import static org.springframework.web.reactive.HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE;
import static org.springframework.web.reactive.HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE;
import static org.springframework.web.reactive.result.method.RequestMappingInfo.paths;
/**
......@@ -77,6 +81,9 @@ import static org.springframework.web.reactive.result.method.RequestMappingInfo.
*/
public class RequestMappingInfoHandlerMappingTests {
private static final HandlerMethod handlerMethod = new HandlerMethod(new TestController(),
ClassUtils.getMethod(TestController.class, "dummy"));
private TestRequestMappingInfoHandlerMapping handlerMapping;
......@@ -169,8 +176,8 @@ public class RequestMappingInfoHandlerMappingTests {
Mono<Object> mono = this.handlerMapping.getHandler(exchange);
assertError(mono, UnsupportedMediaTypeStatusException.class,
ex -> assertEquals("Response status 415 with reason \"Invalid mime type \"bogus\": does not contain '/'\"",
ex.getMessage()));
ex -> assertEquals("Response status 415 with reason \"Invalid mime type \"bogus\": " +
"does not contain '/'\"", ex.getMessage()));
}
@Test // SPR-8462
......@@ -219,7 +226,7 @@ public class RequestMappingInfoHandlerMappingTests {
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
RequestMappingInfo key = paths("/{path1}/{path2}").build();
this.handlerMapping.handleMatch(key, lookupPath, exchange);
this.handlerMapping.handleMatch(key, handlerMethod, lookupPath, exchange);
String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
Map<String, String> uriVariables = (Map<String, String>) exchange.getAttributes().get(name);
......@@ -236,7 +243,7 @@ public class RequestMappingInfoHandlerMappingTests {
ServerWebExchange exchange = method(HttpMethod.GET, url).toExchange();
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
this.handlerMapping.handleMatch(key, lookupPath, exchange);
this.handlerMapping.handleMatch(key, handlerMethod, lookupPath, exchange);
String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
@SuppressWarnings("unchecked")
......@@ -252,11 +259,13 @@ public class RequestMappingInfoHandlerMappingTests {
RequestMappingInfo key = paths("/{path1}/2", "/**").build();
ServerWebExchange exchange = get("/1/2").toExchange();
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
this.handlerMapping.handleMatch(key, lookupPath, exchange);
this.handlerMapping.handleMatch(key, handlerMethod, lookupPath, exchange);
PathPattern bestMatch = (PathPattern) exchange.getAttributes()
.get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
PathPattern bestMatch = (PathPattern) exchange.getAttributes().get(BEST_MATCHING_PATTERN_ATTRIBUTE);
assertEquals("/{path1}/2", bestMatch.getPatternString());
HandlerMethod mapped = (HandlerMethod) exchange.getAttributes().get(BEST_MATCHING_HANDLER_ATTRIBUTE);
assertSame(handlerMethod, mapped);
}
@Test
......@@ -264,10 +273,9 @@ public class RequestMappingInfoHandlerMappingTests {
RequestMappingInfo key = paths().build();
ServerWebExchange exchange = get("/1/2").toExchange();
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
this.handlerMapping.handleMatch(key, lookupPath, exchange);
this.handlerMapping.handleMatch(key, handlerMethod, lookupPath, exchange);
PathPattern bestMatch = (PathPattern) exchange.getAttributes()
.get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
PathPattern bestMatch = (PathPattern) exchange.getAttributes().get(BEST_MATCHING_PATTERN_ATTRIBUTE);
assertEquals("/1/2", bestMatch.getPatternString());
}
......@@ -330,7 +338,6 @@ public class RequestMappingInfoHandlerMappingTests {
.consumeErrorWith(error -> {
assertEquals(exceptionClass, error.getClass());
consumer.accept((T) error);
})
.verify();
}
......@@ -375,19 +382,19 @@ public class RequestMappingInfoHandlerMappingTests {
private void handleMatch(ServerWebExchange exchange, String pattern) {
RequestMappingInfo info = paths(pattern).build();
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
this.handlerMapping.handleMatch(info, lookupPath, exchange);
this.handlerMapping.handleMatch(info, handlerMethod, lookupPath, exchange);
}
@SuppressWarnings("unchecked")
private MultiValueMap<String, String> getMatrixVariables(ServerWebExchange exchange, String uriVarName) {
String attrName = HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE;
return ((Map<String, MultiValueMap<String, String>>) exchange.getAttributes().get(attrName)).get(uriVarName);
return ((Map<String, MultiValueMap<String, String>>) exchange.getAttributes()
.get(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE)).get(uriVarName);
}
@SuppressWarnings("unchecked")
private Map<String, String> getUriTemplateVariables(ServerWebExchange exchange) {
String attrName = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
return (Map<String, String>) exchange.getAttributes().get(attrName);
return (Map<String, String>) exchange.getAttributes()
.get(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
}
......@@ -446,6 +453,8 @@ public class RequestMappingInfoHandlerMappingTests {
headers.add("Allow", "PUT,POST");
return headers;
}
public void dummy() { }
}
......
......@@ -96,11 +96,11 @@ public interface HandlerMapping {
/**
* Name of the {@link HttpServletRequest} attribute that contains a map with
* URI matrix variables.
* URI variable names and a corresponding MultiValueMap of URI matrix
* variables for each.
* <p>Note: This attribute is not required to be supported by all
* HandlerMapping implementations and may also not be present depending on
* whether the HandlerMapping is configured to keep matrix variable content
* in the request URI.
*/
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册