Pattern suffix issue in AnnotationMethodHandlerAdapter
SPR-9333
This commit is contained in:
parent
ae216fbbb5
commit
cf5d55173b
|
|
@ -208,7 +208,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
|||
*/
|
||||
protected void validateHandler(Object handler, HttpServletRequest request) throws Exception {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build a handler object for the given raw handler, exposing the actual
|
||||
* handler, the {@link #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE}, as well as
|
||||
|
|
|
|||
|
|
@ -588,7 +588,8 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
|
|||
if (!typeLevelPattern.startsWith("/")) {
|
||||
typeLevelPattern = "/" + typeLevelPattern;
|
||||
}
|
||||
if (getMatchingPattern(typeLevelPattern, lookupPath) != null) {
|
||||
boolean useSuffixPattern = useSuffixPattern(request);
|
||||
if (getMatchingPattern(typeLevelPattern, lookupPath, useSuffixPattern) != null) {
|
||||
if (mappingInfo.matches(request)) {
|
||||
match = true;
|
||||
mappingInfo.addMatchedPattern(typeLevelPattern);
|
||||
|
|
@ -675,6 +676,11 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
|
|||
return (Boolean) request.getAttribute(HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING);
|
||||
}
|
||||
|
||||
private boolean useSuffixPattern(HttpServletRequest request) {
|
||||
Object value = request.getAttribute(DefaultAnnotationHandlerMapping.USE_DEFAULT_SUFFIX_PATTERN);
|
||||
return (value != null) ? (Boolean) value : Boolean.TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the combined pattern for the given methodLevelPattern and path.
|
||||
* <p>Uses the following algorithm:
|
||||
|
|
@ -687,6 +693,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
|
|||
* </ol>
|
||||
*/
|
||||
private String getCombinedPattern(String methodLevelPattern, String lookupPath, HttpServletRequest request) {
|
||||
boolean useSuffixPattern = useSuffixPattern(request);
|
||||
if (useTypeLevelMapping(request)) {
|
||||
String[] typeLevelPatterns = getTypeLevelMapping().value();
|
||||
for (String typeLevelPattern : typeLevelPatterns) {
|
||||
|
|
@ -694,7 +701,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
|
|||
typeLevelPattern = "/" + typeLevelPattern;
|
||||
}
|
||||
String combinedPattern = pathMatcher.combine(typeLevelPattern, methodLevelPattern);
|
||||
String matchingPattern = getMatchingPattern(combinedPattern, lookupPath);
|
||||
String matchingPattern = getMatchingPattern(combinedPattern, lookupPath, useSuffixPattern);
|
||||
if (matchingPattern != null) {
|
||||
return matchingPattern;
|
||||
}
|
||||
|
|
@ -704,20 +711,20 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
|
|||
String bestMatchingPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
if (StringUtils.hasText(bestMatchingPattern) && bestMatchingPattern.endsWith("*")) {
|
||||
String combinedPattern = pathMatcher.combine(bestMatchingPattern, methodLevelPattern);
|
||||
String matchingPattern = getMatchingPattern(combinedPattern, lookupPath);
|
||||
String matchingPattern = getMatchingPattern(combinedPattern, lookupPath, useSuffixPattern);
|
||||
if (matchingPattern != null && !matchingPattern.equals(bestMatchingPattern)) {
|
||||
return matchingPattern;
|
||||
}
|
||||
}
|
||||
return getMatchingPattern(methodLevelPattern, lookupPath);
|
||||
return getMatchingPattern(methodLevelPattern, lookupPath, useSuffixPattern);
|
||||
}
|
||||
|
||||
private String getMatchingPattern(String pattern, String lookupPath) {
|
||||
private String getMatchingPattern(String pattern, String lookupPath, boolean useSuffixPattern) {
|
||||
if (pattern.equals(lookupPath)) {
|
||||
return pattern;
|
||||
}
|
||||
boolean hasSuffix = pattern.indexOf('.') != -1;
|
||||
if (!hasSuffix) {
|
||||
if (useSuffixPattern && !hasSuffix) {
|
||||
String patternWithSuffix = pattern + ".*";
|
||||
if (pathMatcher.match(patternWithSuffix, lookupPath)) {
|
||||
return patternWithSuffix;
|
||||
|
|
@ -727,7 +734,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
|
|||
return pattern;
|
||||
}
|
||||
boolean endsWithSlash = pattern.endsWith("/");
|
||||
if (!endsWithSlash) {
|
||||
if (useSuffixPattern && !endsWithSlash) {
|
||||
String patternWithSlash = pattern + "/";
|
||||
if (pathMatcher.match(patternWithSlash, lookupPath)) {
|
||||
return patternWithSlash;
|
||||
|
|
@ -1236,7 +1243,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
|
|||
private int compareAcceptHeaders(RequestMappingInfo info1, RequestMappingInfo info2) {
|
||||
List<MediaType> requestAccepts = request.getHeaders().getAccept();
|
||||
MediaType.sortByQualityValue(requestAccepts);
|
||||
|
||||
|
||||
List<MediaType> info1Accepts = getAcceptHeaderValue(info1);
|
||||
List<MediaType> info2Accepts = getAcceptHeaderValue(info2);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
|
|
@ -22,6 +22,7 @@ import java.util.HashMap;
|
|||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
|
@ -81,9 +82,11 @@ import org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMappin
|
|||
*/
|
||||
public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandlerMapping {
|
||||
|
||||
static final String USE_DEFAULT_SUFFIX_PATTERN = DefaultAnnotationHandlerMapping.class.getName() + ".useDefaultSuffixPattern";
|
||||
|
||||
private boolean useDefaultSuffixPattern = true;
|
||||
|
||||
private final Map<Class, RequestMapping> cachedMappings = new HashMap<Class, RequestMapping>();
|
||||
private final Map<Class<?>, RequestMapping> cachedMappings = new HashMap<Class<?>, RequestMapping>();
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -229,6 +232,7 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler
|
|||
if (mapping != null) {
|
||||
validateMapping(mapping, request);
|
||||
}
|
||||
request.setAttribute(USE_DEFAULT_SUFFIX_PATTERN, this.useDefaultSuffixPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
|
|
@ -351,6 +351,31 @@ public class UriTemplateServletAnnotationControllerTests {
|
|||
assertEquals("foo-foo", response.getContentAsString());
|
||||
}
|
||||
|
||||
// SPR-9333
|
||||
@Test
|
||||
@SuppressWarnings("serial")
|
||||
public void suppressDefaultSuffixPattern() throws Exception {
|
||||
servlet = new DispatcherServlet() {
|
||||
@Override
|
||||
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
|
||||
throws BeansException {
|
||||
GenericWebApplicationContext wac = new GenericWebApplicationContext();
|
||||
wac.registerBeanDefinition("controller", new RootBeanDefinition(VariableNamesController.class));
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(DefaultAnnotationHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useDefaultSuffixPattern", false);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
wac.refresh();
|
||||
return wac;
|
||||
}
|
||||
};
|
||||
servlet.init(new MockServletConfig());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/jsmith@mail.com");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("foo-jsmith@mail.com", response.getContentAsString());
|
||||
}
|
||||
|
||||
// SPR-6906
|
||||
@Test
|
||||
public void controllerClassName() throws Exception {
|
||||
|
|
@ -389,7 +414,7 @@ public class UriTemplateServletAnnotationControllerTests {
|
|||
@Test
|
||||
public void doIt() throws Exception {
|
||||
initServlet(Spr6978Controller.class);
|
||||
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo/100");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
|
|
|
|||
Loading…
Reference in New Issue