|
|
|
@ -20,13 +20,13 @@ import java.lang.reflect.Method; |
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.core.annotation.AnnotationUtils; |
|
|
|
import org.springframework.core.annotation.AnnotationUtils; |
|
|
|
import org.springframework.stereotype.Controller; |
|
|
|
import org.springframework.stereotype.Controller; |
|
|
|
import org.springframework.util.PathMatcher; |
|
|
|
|
|
|
|
import org.springframework.web.bind.annotation.RequestMapping; |
|
|
|
import org.springframework.web.bind.annotation.RequestMapping; |
|
|
|
import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition; |
|
|
|
|
|
|
|
import org.springframework.web.servlet.mvc.condition.RequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition; |
|
|
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo; |
|
|
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo; |
|
|
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; |
|
|
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; |
|
|
|
@ -41,9 +41,28 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping { |
|
|
|
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean useSuffixPatternMatch = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Set whether to use a suffix pattern match (".*") when matching patterns to URLs. |
|
|
|
|
|
|
|
* If enabled a method mapped to "/users" will also match to "/users.*". |
|
|
|
|
|
|
|
* <p>Default is "true". Turn this convention off if you intend to interpret path mappings strictly. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void setUseSuffixPatternMatch(boolean useSuffixPatternMatch) { |
|
|
|
|
|
|
|
this.useSuffixPatternMatch = useSuffixPatternMatch; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the value of the useSuffixPatternMatch flag, see {@link #setUseSuffixPatternMatch(boolean)}. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public boolean isUseSuffixPatternMatch() { |
|
|
|
|
|
|
|
return useSuffixPatternMatch; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* {@inheritDoc} The handler determination in this method is made based on the presence of a type-level {@link |
|
|
|
* {@inheritDoc} |
|
|
|
* Controller} annotation. |
|
|
|
* The default implementation checks for the presence of a type-level {@link Controller} |
|
|
|
|
|
|
|
* annotation via {@link AnnotationUtils#findAnnotation(Class, Class)}. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected boolean isHandler(Class<?> beanType) { |
|
|
|
protected boolean isHandler(Class<?> beanType) { |
|
|
|
@ -51,40 +70,54 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Provides a {@link RequestMappingInfo} for the given method. <p>Only {@link RequestMapping @RequestMapping}-annotated |
|
|
|
* Determines if the given method is a handler method and creates a {@link RequestMappingInfo} for it. |
|
|
|
* methods are considered. Type-level {@link RequestMapping @RequestMapping} annotations are also detected and their |
|
|
|
* |
|
|
|
* attributes combined with method-level {@link RequestMapping @RequestMapping} attributes. |
|
|
|
* <p>The default implementation expects the presence of a method-level @{@link RequestMapping} |
|
|
|
|
|
|
|
* annotation via {@link AnnotationUtils#findAnnotation(Class, Class)}. The presence of |
|
|
|
|
|
|
|
* type-level annotations is also checked and if present a RequestMappingInfo is created for each type- |
|
|
|
|
|
|
|
* and method-level annotations and combined via {@link RequestMappingInfo#combine(RequestMappingInfo)}. |
|
|
|
* |
|
|
|
* |
|
|
|
* @param method the method to create a mapping for |
|
|
|
* @param method the method to create a RequestMappingInfo for |
|
|
|
* @param handlerType the actual handler type, possibly a sub-type of {@code method.getDeclaringClass()} |
|
|
|
* @param handlerType the actual handler type, possibly a sub-type of {@code method.getDeclaringClass()} |
|
|
|
* @return the mapping, or {@code null} |
|
|
|
* @return the info, or {@code null} |
|
|
|
* @see RequestMappingInfo#combine(RequestMappingInfo, PathMatcher) |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) { |
|
|
|
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) { |
|
|
|
RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class); |
|
|
|
RequestMapping methodAnnot = AnnotationUtils.findAnnotation(method, RequestMapping.class); |
|
|
|
if (methodAnnotation == null) { |
|
|
|
if (methodAnnot != null) { |
|
|
|
return null; |
|
|
|
RequestMapping typeAnnot = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class); |
|
|
|
} |
|
|
|
RequestMappingInfo methodInfo = createRequestMappingInfo(methodAnnot, handlerType, method); |
|
|
|
RequestMappingInfo methodInfo = createFromRequestMapping(methodAnnotation); |
|
|
|
if (typeAnnot != null) { |
|
|
|
RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class); |
|
|
|
RequestMappingInfo typeInfo = createRequestMappingInfo(typeAnnot, handlerType, method); |
|
|
|
if (typeAnnotation != null) { |
|
|
|
return typeInfo.combine(methodInfo); |
|
|
|
RequestMappingInfo typeInfo = createFromRequestMapping(typeAnnotation); |
|
|
|
} |
|
|
|
return typeInfo.combine(methodInfo); |
|
|
|
else { |
|
|
|
} |
|
|
|
return methodInfo; |
|
|
|
else { |
|
|
|
} |
|
|
|
return methodInfo; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private RequestMappingInfo createFromRequestMapping(RequestMapping annotation) { |
|
|
|
/** |
|
|
|
|
|
|
|
* Override this method to create a {@link RequestMappingInfo} from a @{@link RequestMapping} annotation. The main |
|
|
|
|
|
|
|
* reason for doing so is to provide a custom {@link RequestCondition} to the RequestMappingInfo constructor. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* <p>This method is invoked both for type- and method-level @{@link RequestMapping} annotations. The resulting |
|
|
|
|
|
|
|
* {@link RequestMappingInfo}s are combined via {@link RequestMappingInfo#combine(RequestMappingInfo)}. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param annot a type- or a method-level {@link RequestMapping} annotation |
|
|
|
|
|
|
|
* @param handlerType the handler type |
|
|
|
|
|
|
|
* @param method the method with which the created RequestMappingInfo will be combined |
|
|
|
|
|
|
|
* @return a {@link RequestMappingInfo} instance; never {@code null} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected RequestMappingInfo createRequestMappingInfo(RequestMapping annot, Class<?> handlerType, Method method) { |
|
|
|
return new RequestMappingInfo( |
|
|
|
return new RequestMappingInfo( |
|
|
|
new PatternsRequestCondition(annotation.value(), getUrlPathHelper(), getPathMatcher()), |
|
|
|
new PatternsRequestCondition(annot.value(), getUrlPathHelper(), getPathMatcher(), useSuffixPatternMatch), |
|
|
|
new RequestMethodsRequestCondition(annotation.method()), |
|
|
|
new RequestMethodsRequestCondition(annot.method()), |
|
|
|
new ParamsRequestCondition(annotation.params()), |
|
|
|
new ParamsRequestCondition(annot.params()), |
|
|
|
new HeadersRequestCondition(annotation.headers()), |
|
|
|
new HeadersRequestCondition(annot.headers()), |
|
|
|
new ConsumesRequestCondition(annotation.consumes(), annotation.headers()), |
|
|
|
new ConsumesRequestCondition(annot.consumes(), annot.headers()), |
|
|
|
new ProducesRequestCondition(annotation.produces(), annotation.headers()), null); |
|
|
|
new ProducesRequestCondition(annot.produces(), annot.headers()), null); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|