|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Copyright 2002-2010 the original author or authors. |
|
|
|
* Copyright 2002-2011 the original author or authors. |
|
|
|
* |
|
|
|
* |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -430,10 +430,19 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator |
|
|
|
return mav; |
|
|
|
return mav; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* This method always returns -1 since an annotated controller can have many methods, |
|
|
|
|
|
|
|
* each requiring separate lastModified calculations. Instead, an |
|
|
|
|
|
|
|
* @{@link RequestMapping}-annotated method can calculate the lastModified value, call |
|
|
|
|
|
|
|
* {@link org.springframework.web.context.request.WebRequest#checkNotModified(long)} |
|
|
|
|
|
|
|
* to check it, and return {@code null} if that returns {@code true}. |
|
|
|
|
|
|
|
* @see org.springframework.web.context.request.WebRequest#checkNotModified(long) |
|
|
|
|
|
|
|
*/ |
|
|
|
public long getLastModified(HttpServletRequest request, Object handler) { |
|
|
|
public long getLastModified(HttpServletRequest request, Object handler) { |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Build a HandlerMethodResolver for the given handler type. |
|
|
|
* Build a HandlerMethodResolver for the given handler type. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@ -463,8 +472,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator |
|
|
|
* @see ServletRequestDataBinder#bind(javax.servlet.ServletRequest) |
|
|
|
* @see ServletRequestDataBinder#bind(javax.servlet.ServletRequest) |
|
|
|
* @see ServletRequestDataBinder#convertIfNecessary(Object, Class, org.springframework.core.MethodParameter) |
|
|
|
* @see ServletRequestDataBinder#convertIfNecessary(Object, Class, org.springframework.core.MethodParameter) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ServletRequestDataBinder createBinder(HttpServletRequest request, Object target, String objectName) |
|
|
|
protected ServletRequestDataBinder createBinder(HttpServletRequest request, Object target, String objectName) throws Exception { |
|
|
|
throws Exception { |
|
|
|
|
|
|
|
return new ServletRequestDataBinder(target, objectName); |
|
|
|
return new ServletRequestDataBinder(target, objectName); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -620,21 +628,20 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
if (!allowedMethods.isEmpty()) { |
|
|
|
if (!allowedMethods.isEmpty()) { |
|
|
|
throw new HttpRequestMethodNotSupportedException(request.getMethod(), |
|
|
|
throw new HttpRequestMethodNotSupportedException(request.getMethod(), StringUtils.toStringArray(allowedMethods)); |
|
|
|
StringUtils.toStringArray(allowedMethods)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
throw new NoSuchRequestHandlingMethodException(lookupPath, request.getMethod(), |
|
|
|
throw new NoSuchRequestHandlingMethodException(lookupPath, request.getMethod(), request.getParameterMap()); |
|
|
|
request.getParameterMap()); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Determines the combined pattern for the given methodLevelPattern and path. |
|
|
|
* Determines the combined pattern for the given methodLevelPattern and path. |
|
|
|
* <p>Uses the following algorithm: <ol> |
|
|
|
* <p>Uses the following algorithm: |
|
|
|
|
|
|
|
* <ol> |
|
|
|
* <li>If there is a type-level mapping with path information, it is {@linkplain |
|
|
|
* <li>If there is a type-level mapping with path information, it is {@linkplain |
|
|
|
* PathMatcher#combine(String, String) combined} with the method-level pattern.</li> |
|
|
|
* PathMatcher#combine(String, String) combined} with the method-level pattern.</li> |
|
|
|
* <li>If there is a {@linkplain HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE best matching pattern} in the |
|
|
|
* <li>If there is a {@linkplain HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE best matching pattern} |
|
|
|
* request, it is combined with the method-level pattern.</li> |
|
|
|
* in the request, it is combined with the method-level pattern.</li> |
|
|
|
* <li>Otherwise, the method-level pattern is returned.</li> |
|
|
|
* <li>Otherwise, the method-level pattern is returned.</li> |
|
|
|
* </ol> |
|
|
|
* </ol> |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@ -646,8 +653,9 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator |
|
|
|
typeLevelPattern = "/" + typeLevelPattern; |
|
|
|
typeLevelPattern = "/" + typeLevelPattern; |
|
|
|
} |
|
|
|
} |
|
|
|
String combinedPattern = pathMatcher.combine(typeLevelPattern, methodLevelPattern); |
|
|
|
String combinedPattern = pathMatcher.combine(typeLevelPattern, methodLevelPattern); |
|
|
|
if (isPathMatchInternal(combinedPattern, lookupPath)) { |
|
|
|
String matchingPattern = getMatchingPattern(combinedPattern, lookupPath); |
|
|
|
return combinedPattern; |
|
|
|
if (matchingPattern != null) { |
|
|
|
|
|
|
|
return matchingPattern; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return null; |
|
|
|
return null; |
|
|
|
@ -655,44 +663,44 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator |
|
|
|
String bestMatchingPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); |
|
|
|
String bestMatchingPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); |
|
|
|
if (StringUtils.hasText(bestMatchingPattern) && bestMatchingPattern.endsWith("*")) { |
|
|
|
if (StringUtils.hasText(bestMatchingPattern) && bestMatchingPattern.endsWith("*")) { |
|
|
|
String combinedPattern = pathMatcher.combine(bestMatchingPattern, methodLevelPattern); |
|
|
|
String combinedPattern = pathMatcher.combine(bestMatchingPattern, methodLevelPattern); |
|
|
|
if (!combinedPattern.equals(bestMatchingPattern) && |
|
|
|
String matchingPattern = getMatchingPattern(combinedPattern, lookupPath); |
|
|
|
(isPathMatchInternal(combinedPattern, lookupPath))) { |
|
|
|
if (matchingPattern != null && !matchingPattern.equals(bestMatchingPattern)) { |
|
|
|
return combinedPattern; |
|
|
|
return matchingPattern; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (isPathMatchInternal(methodLevelPattern, lookupPath)) { |
|
|
|
return getMatchingPattern(methodLevelPattern, lookupPath); |
|
|
|
return methodLevelPattern; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private boolean isPathMatchInternal(String pattern, String lookupPath) { |
|
|
|
private String getMatchingPattern(String pattern, String lookupPath) { |
|
|
|
if (pattern.equals(lookupPath) || pathMatcher.match(pattern, lookupPath)) { |
|
|
|
if (pattern.equals(lookupPath)) { |
|
|
|
return true; |
|
|
|
return pattern; |
|
|
|
} |
|
|
|
} |
|
|
|
boolean hasSuffix = pattern.indexOf('.') != -1; |
|
|
|
boolean hasSuffix = pattern.indexOf('.') != -1; |
|
|
|
if (!hasSuffix && pathMatcher.match(pattern + ".*", lookupPath)) { |
|
|
|
if (!hasSuffix) { |
|
|
|
return true; |
|
|
|
String patternWithSuffix = pattern + ".*"; |
|
|
|
|
|
|
|
if (pathMatcher.match(patternWithSuffix, lookupPath)) { |
|
|
|
|
|
|
|
return patternWithSuffix; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (pathMatcher.match(pattern, lookupPath)) { |
|
|
|
|
|
|
|
return pattern; |
|
|
|
} |
|
|
|
} |
|
|
|
boolean endsWithSlash = pattern.endsWith("/"); |
|
|
|
boolean endsWithSlash = pattern.endsWith("/"); |
|
|
|
if (!endsWithSlash && pathMatcher.match(pattern + "/", lookupPath)) { |
|
|
|
if (!endsWithSlash) { |
|
|
|
return true; |
|
|
|
String patternWithSlash = pattern + "/"; |
|
|
|
|
|
|
|
if (pathMatcher.match(patternWithSlash, lookupPath)) { |
|
|
|
|
|
|
|
return patternWithSlash; |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
private void extractHandlerMethodUriTemplates(String mappedPattern, |
|
|
|
private void extractHandlerMethodUriTemplates(String mappedPattern, String lookupPath, HttpServletRequest request) { |
|
|
|
String lookupPath, |
|
|
|
|
|
|
|
HttpServletRequest request) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, String> variables = |
|
|
|
Map<String, String> variables = |
|
|
|
(Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); |
|
|
|
(Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); |
|
|
|
|
|
|
|
|
|
|
|
int patternVariableCount = StringUtils.countOccurrencesOf(mappedPattern, "{"); |
|
|
|
int patternVariableCount = StringUtils.countOccurrencesOf(mappedPattern, "{"); |
|
|
|
|
|
|
|
if ((variables == null || patternVariableCount != variables.size()) && pathMatcher.match(mappedPattern, lookupPath)) { |
|
|
|
if ( (variables == null || patternVariableCount != variables.size()) |
|
|
|
|
|
|
|
&& pathMatcher.match(mappedPattern, lookupPath)) { |
|
|
|
|
|
|
|
variables = pathMatcher.extractUriTemplateVariables(mappedPattern, lookupPath); |
|
|
|
variables = pathMatcher.extractUriTemplateVariables(mappedPattern, lookupPath); |
|
|
|
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, variables); |
|
|
|
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, variables); |
|
|
|
} |
|
|
|
} |
|
|
|
|