revised handler method resolution, in particular with respect to generic interfaces (SPR-7355)

This commit is contained in:
Juergen Hoeller
2010-08-15 21:12:54 +00:00
parent 49a2970def
commit 35971f9f90
7 changed files with 322 additions and 114 deletions

View File

@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@@ -496,10 +497,36 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
*/
private class ServletHandlerMethodResolver extends HandlerMethodResolver {
private final Map<Method, RequestMappingInfo> mappings = new HashMap<Method, RequestMappingInfo>();
private ServletHandlerMethodResolver(Class<?> handlerType) {
init(handlerType);
}
@Override
protected boolean isHandlerMethod(Method method) {
if (this.mappings.containsKey(method)) {
return true;
}
RequestMapping mapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);
if (mapping != null) {
RequestMappingInfo mappingInfo = new RequestMappingInfo();
mappingInfo.patterns = mapping.value();
if (!hasTypeLevelMapping() || !Arrays.equals(mapping.method(), getTypeLevelMapping().method())) {
mappingInfo.methods = mapping.method();
}
if (!hasTypeLevelMapping() || !Arrays.equals(mapping.params(), getTypeLevelMapping().params())) {
mappingInfo.params = mapping.params();
}
if (!hasTypeLevelMapping() || !Arrays.equals(mapping.headers(), getTypeLevelMapping().headers())) {
mappingInfo.headers = mapping.headers();
}
this.mappings.put(method, mappingInfo);
return true;
}
return false;
}
public Method resolveHandlerMethod(HttpServletRequest request) throws ServletException {
String lookupPath = urlPathHelper.getLookupPathForRequest(request);
Comparator<String> pathComparator = pathMatcher.getPatternComparator(lookupPath);
@@ -507,7 +534,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
Set<String> allowedMethods = new LinkedHashSet<String>(7);
String resolvedMethodName = null;
for (Method handlerMethod : getHandlerMethods()) {
RequestMappingInfo mappingInfo = createRequestMappingInfo(handlerMethod);
RequestMappingInfo mappingInfo = this.mappings.get(handlerMethod);
boolean match = false;
if (mappingInfo.hasPatterns()) {
List<String> matchingPatterns = new ArrayList<String>(mappingInfo.patterns.length);
@@ -599,22 +626,6 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
}
}
private RequestMappingInfo createRequestMappingInfo(Method handlerMethod) {
RequestMappingInfo mappingInfo = new RequestMappingInfo();
RequestMapping mapping = AnnotationUtils.findAnnotation(handlerMethod, RequestMapping.class);
mappingInfo.patterns = mapping.value();
if (!hasTypeLevelMapping() || !Arrays.equals(mapping.method(), getTypeLevelMapping().method())) {
mappingInfo.methods = mapping.method();
}
if (!hasTypeLevelMapping() || !Arrays.equals(mapping.params(), getTypeLevelMapping().params())) {
mappingInfo.params = mapping.params();
}
if (!hasTypeLevelMapping() || !Arrays.equals(mapping.headers(), getTypeLevelMapping().headers())) {
mappingInfo.headers = mapping.headers();
}
return mappingInfo;
}
/**
* Determines the combined pattern for the given methodLevelPattern and path.
* <p>Uses the following algorithm: <ol>

View File

@@ -17,7 +17,7 @@
package org.springframework.web.servlet.mvc.annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
@@ -165,8 +165,9 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler
}
final Set<String> urls = new LinkedHashSet<String>();
Class<?>[] handlerTypes =
Proxy.isProxyClass(handlerType) ? handlerType.getInterfaces() : new Class<?>[]{handlerType};
Set<Class<?>> handlerTypes = new LinkedHashSet<Class<?>>();
handlerTypes.add(handlerType);
handlerTypes.addAll(Arrays.asList(handlerType.getInterfaces()));
for (Class<?> currentHandlerType : handlerTypes) {
ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() {
public void doWith(Method method) {
@@ -187,7 +188,7 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler
}
}
}
}, ReflectionUtils.NON_BRIDGED_METHODS);
}, ReflectionUtils.USER_DECLARED_METHODS);
}
return StringUtils.toStringArray(urls);
}