SPR-7707 - Unexpected behavior with class-level @RequestMappings

This commit is contained in:
Arjen Poutsma
2010-11-08 14:56:35 +00:00
parent 01e79cfedd
commit 8762ec956c
5 changed files with 81 additions and 5 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2010 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.
@@ -74,6 +74,14 @@ public interface HandlerMapping {
*/
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
/**
* Name of the boolean {@link HttpServletRequest} attribute that indicates
* whether type-level mappings should be inspected.
* <p>Note: This attribute is not required to be supported by all
* HandlerMapping implementations.
*/
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";
/**
* Name of the {@link HttpServletRequest} attribute that contains the URI
* templates map, mapping variable names to values.

View File

@@ -429,6 +429,13 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
return Collections.unmodifiableMap(this.handlerMap);
}
/**
* Indicates whether this handler mapping support type-level mappings. Default to {@code false}.
*/
protected boolean supportsTypeLevelMappings() {
return false;
}
/**
* Special interceptor for exposing the
@@ -449,10 +456,11 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
exposePathWithinMapping(this.bestMatchingPattern, this.pathWithinMapping, request);
request.setAttribute(HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING, supportsTypeLevelMappings());
return true;
}
}
}
/**
* Special interceptor for exposing the

View File

@@ -34,7 +34,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@@ -45,6 +44,7 @@ import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
@@ -571,6 +571,27 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
}
mappingInfo.sortMatchedPatterns(pathComparator);
}
else if (useTypeLevelMapping(request)) {
String[] typeLevelPatterns = getTypeLevelMapping().value();
for (String typeLevelPattern : typeLevelPatterns) {
if (!typeLevelPattern.startsWith("/")) {
typeLevelPattern = "/" + typeLevelPattern;
}
if (isPathMatchInternal(typeLevelPattern, lookupPath)) {
if (mappingInfo.matches(request)) {
match = true;
mappingInfo.addMatchedPattern(typeLevelPattern);
}
else {
if (!mappingInfo.matchesRequestMethod(request)) {
allowedMethods.addAll(mappingInfo.methodNames());
}
break;
}
}
}
mappingInfo.sortMatchedPatterns(pathComparator);
}
else {
// No paths specified: parameter match sufficient.
match = mappingInfo.matches(request);
@@ -638,6 +659,14 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
}
}
private boolean useTypeLevelMapping(HttpServletRequest request) {
if (!hasTypeLevelMapping() || ObjectUtils.isEmpty(getTypeLevelMapping().value())) {
return false;
}
return (Boolean) request.getAttribute(
HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING);
}
/**
* Determines the combined pattern for the given methodLevelPattern and path.
* <p>Uses the following algorithm: <ol>
@@ -649,7 +678,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
* </ol>
*/
private String getCombinedPattern(String methodLevelPattern, String lookupPath, HttpServletRequest request) {
if (hasTypeLevelMapping() && (!ObjectUtils.isEmpty(getTypeLevelMapping().value()))) {
if (useTypeLevelMapping(request)) {
String[] typeLevelPatterns = getTypeLevelMapping().value();
for (String typeLevelPattern : typeLevelPatterns) {
if (!typeLevelPattern.startsWith("/")) {

View File

@@ -261,4 +261,8 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler
}
}
@Override
protected boolean supportsTypeLevelMappings() {
return true;
}
}