Remove consumes from @RequestMapping

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@4234 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
Rossen Stoyanchev 2011-04-21 14:54:55 +00:00
parent ff1b05cd94
commit ef6efa3f6f
5 changed files with 48 additions and 40 deletions

View File

@ -129,7 +129,8 @@ public class RequestMappingHandlerMethodMapping extends AbstractHandlerMethodMap
private static RequestMappingInfo createFromRequestMapping(RequestMapping annotation) { private static RequestMappingInfo createFromRequestMapping(RequestMapping annotation) {
return new RequestMappingInfo(Arrays.asList(annotation.value()), Arrays.asList(annotation.method()), return new RequestMappingInfo(Arrays.asList(annotation.value()), Arrays.asList(annotation.method()),
RequestConditionFactory.parseParams(annotation.params()), RequestConditionFactory.parseParams(annotation.params()),
RequestConditionFactory.parseHeaders(annotation.headers())); RequestConditionFactory.parseHeaders(annotation.headers()),
RequestConditionFactory.parseConsumes());
} }
@Override @Override

View File

@ -53,6 +53,8 @@ public final class RequestMappingInfo {
private final RequestCondition headersCondition; private final RequestCondition headersCondition;
private final RequestCondition consumesCondition;
private int hash; private int hash;
/** /**
@ -61,7 +63,7 @@ public final class RequestMappingInfo {
* <p>Package protected for testing purposes. * <p>Package protected for testing purposes.
*/ */
RequestMappingInfo(Collection<String> patterns, Collection<RequestMethod> methods) { RequestMappingInfo(Collection<String> patterns, Collection<RequestMethod> methods) {
this(patterns, methods, null, null); this(patterns, methods, null, null, null);
} }
/** /**
@ -70,11 +72,13 @@ public final class RequestMappingInfo {
public RequestMappingInfo(Collection<String> patterns, public RequestMappingInfo(Collection<String> patterns,
Collection<RequestMethod> methods, Collection<RequestMethod> methods,
RequestCondition paramsCondition, RequestCondition paramsCondition,
RequestCondition headersCondition) { RequestCondition headersCondition,
RequestCondition consumesCondition) {
this.patterns = asUnmodifiableSet(prependLeadingSlash(patterns)); this.patterns = asUnmodifiableSet(prependLeadingSlash(patterns));
this.methods = asUnmodifiableSet(methods); this.methods = asUnmodifiableSet(methods);
this.paramsCondition = paramsCondition != null ? paramsCondition : RequestConditionFactory.trueCondition(); this.paramsCondition = paramsCondition != null ? paramsCondition : RequestConditionFactory.trueCondition();
this.headersCondition = headersCondition != null ? headersCondition : RequestConditionFactory.trueCondition(); this.headersCondition = headersCondition != null ? headersCondition : RequestConditionFactory.trueCondition();
this.consumesCondition = consumesCondition != null ? consumesCondition : RequestConditionFactory.trueCondition();
} }
private static Set<String> prependLeadingSlash(Collection<String> patterns) { private static Set<String> prependLeadingSlash(Collection<String> patterns) {
@ -139,6 +143,7 @@ public final class RequestMappingInfo {
* <li>HTTP methods are combined as union of all HTTP methods listed in both keys. * <li>HTTP methods are combined as union of all HTTP methods listed in both keys.
* <li>Request parameter are combined into a logical AND. * <li>Request parameter are combined into a logical AND.
* <li>Request header are combined into a logical AND. * <li>Request header are combined into a logical AND.
* <li>Consumes .. TODO
* </ul> * </ul>
* @param methodKey the key to combine with * @param methodKey the key to combine with
* @param pathMatcher to {@linkplain PathMatcher#combine(String, String) combine} the patterns * @param pathMatcher to {@linkplain PathMatcher#combine(String, String) combine} the patterns
@ -149,8 +154,9 @@ public final class RequestMappingInfo {
Set<RequestMethod> methods = union(this.methods, methodKey.methods); Set<RequestMethod> methods = union(this.methods, methodKey.methods);
RequestCondition params = RequestConditionFactory.and(this.paramsCondition, methodKey.paramsCondition); RequestCondition params = RequestConditionFactory.and(this.paramsCondition, methodKey.paramsCondition);
RequestCondition headers = RequestConditionFactory.and(this.headersCondition, methodKey.headersCondition); RequestCondition headers = RequestConditionFactory.and(this.headersCondition, methodKey.headersCondition);
RequestCondition consumes = RequestConditionFactory.mostSpecific(methodKey.consumesCondition, this.consumesCondition);
return new RequestMappingInfo(patterns, methods, params, headers); return new RequestMappingInfo(patterns, methods, params, headers, consumes);
} }
private static Set<String> combinePatterns(Collection<String> typePatterns, private static Set<String> combinePatterns(Collection<String> typePatterns,
@ -197,14 +203,16 @@ public final class RequestMappingInfo {
* @return a new request key that contains all matching attributes, or {@code null} if not all conditions match * @return a new request key that contains all matching attributes, or {@code null} if not all conditions match
*/ */
public RequestMappingInfo getMatchingRequestMapping(String lookupPath, HttpServletRequest request, PathMatcher pathMatcher) { public RequestMappingInfo getMatchingRequestMapping(String lookupPath, HttpServletRequest request, PathMatcher pathMatcher) {
if (!checkMethod(request) || !paramsCondition.match(request) || !headersCondition.match(request)) { if (!checkMethod(request) || !paramsCondition.match(request) || !headersCondition.match(request) ||
!consumesCondition.match(request)) {
return null; return null;
} }
else { else {
List<String> matchingPatterns = getMatchingPatterns(lookupPath, request, pathMatcher); List<String> matchingPatterns = getMatchingPatterns(lookupPath, request, pathMatcher);
if (!matchingPatterns.isEmpty()) { if (!matchingPatterns.isEmpty()) {
Set<RequestMethod> matchingMethods = getMatchingMethod(request); Set<RequestMethod> matchingMethods = getMatchingMethod(request);
return new RequestMappingInfo(matchingPatterns, matchingMethods, this.paramsCondition, this.headersCondition); return new RequestMappingInfo(matchingPatterns, matchingMethods, this.paramsCondition, this.headersCondition,
this.consumesCondition);
} }
else { else {
return null; return null;
@ -297,6 +305,7 @@ public final class RequestMappingInfo {
} }
builder.append(",params=").append(paramsCondition.toString()); builder.append(",params=").append(paramsCondition.toString());
builder.append(",headers=").append(headersCondition.toString()); builder.append(",headers=").append(headersCondition.toString());
builder.append(",consumes=").append(consumesCondition.toString());
builder.append('}'); builder.append('}');
return builder.toString(); return builder.toString();
} }

View File

@ -100,7 +100,7 @@ public class RequestKeyComparatorTests {
RequestMappingInfo empty = new RequestMappingInfo(null, null); RequestMappingInfo empty = new RequestMappingInfo(null, null);
RequestMappingInfo oneMethod = new RequestMappingInfo(null, asList(RequestMethod.GET)); RequestMappingInfo oneMethod = new RequestMappingInfo(null, asList(RequestMethod.GET));
RequestMappingInfo oneMethodOneParam = RequestMappingInfo oneMethodOneParam =
new RequestMappingInfo(null, asList(RequestMethod.GET), RequestConditionFactory.parseParams("foo"), null); new RequestMappingInfo(null, asList(RequestMethod.GET), RequestConditionFactory.parseParams("foo"), null, null);
List<RequestMappingInfo> list = asList(empty, oneMethod, oneMethodOneParam); List<RequestMappingInfo> list = asList(empty, oneMethod, oneMethodOneParam);
Collections.shuffle(list); Collections.shuffle(list);
Collections.sort(list, handlerMapping.getMappingComparator("", request)); Collections.sort(list, handlerMapping.getMappingComparator("", request));
@ -113,8 +113,8 @@ public class RequestKeyComparatorTests {
@Test @Test
@Ignore // TODO : remove ignore @Ignore // TODO : remove ignore
public void acceptHeaders() { public void acceptHeaders() {
RequestMappingInfo html = new RequestMappingInfo(null, null, null, RequestConditionFactory.parseHeaders("accept=text/html")); RequestMappingInfo html = new RequestMappingInfo(null, null, null, RequestConditionFactory.parseHeaders("accept=text/html"), null);
RequestMappingInfo xml = new RequestMappingInfo(null, null, null, RequestConditionFactory.parseHeaders("accept=application/xml")); RequestMappingInfo xml = new RequestMappingInfo(null, null, null, RequestConditionFactory.parseHeaders("accept=application/xml"), null);
RequestMappingInfo none = new RequestMappingInfo(null, null); RequestMappingInfo none = new RequestMappingInfo(null, null);
request.addHeader("Accept", "application/xml, text/html"); request.addHeader("Accept", "application/xml, text/html");

View File

@ -179,12 +179,12 @@ public class RequestKeyTests {
request.setParameter("foo", "bar"); request.setParameter("foo", "bar");
String lookupPath = new UrlPathHelper().getLookupPathForRequest(request); String lookupPath = new UrlPathHelper().getLookupPathForRequest(request);
RequestMappingInfo key = new RequestMappingInfo(asList("/foo"), null, RequestConditionFactory.parseParams("foo=bar"), null); RequestMappingInfo key = new RequestMappingInfo(asList("/foo"), null, RequestConditionFactory.parseParams("foo=bar"), null, null);
RequestMappingInfo match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher); RequestMappingInfo match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNotNull(match); assertNotNull(match);
key = new RequestMappingInfo(singleton("/foo"), null, RequestConditionFactory.parseParams("foo!=bar"), null); key = new RequestMappingInfo(singleton("/foo"), null, RequestConditionFactory.parseParams("foo!=bar"), null, null);
match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher); match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNull(match); assertNull(match);
@ -197,36 +197,36 @@ public class RequestKeyTests {
request.addHeader("foo", "bar"); request.addHeader("foo", "bar");
String lookupPath = new UrlPathHelper().getLookupPathForRequest(request); String lookupPath = new UrlPathHelper().getLookupPathForRequest(request);
RequestMappingInfo key = new RequestMappingInfo(singleton("/foo"), null, null, RequestConditionFactory.parseHeaders("foo=bar")); RequestMappingInfo key = new RequestMappingInfo(singleton("/foo"), null, null, RequestConditionFactory.parseHeaders("foo=bar"), null);
RequestMappingInfo match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher); RequestMappingInfo match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNotNull(match); assertNotNull(match);
key = new RequestMappingInfo(singleton("/foo"), null, null, RequestConditionFactory.parseHeaders("foo!=bar")); key = new RequestMappingInfo(singleton("/foo"), null, null, RequestConditionFactory.parseHeaders("foo!=bar"), null);
match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher); match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNull(match); assertNull(match);
} }
// @Test @Test
// public void consumesCondition() { public void consumesCondition() {
// PathMatcher pathMatcher = new AntPathMatcher(); PathMatcher pathMatcher = new AntPathMatcher();
// MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
// request.setContentType("text/plain"); request.setContentType("text/plain");
// String lookupPath = new UrlPathHelper().getLookupPathForRequest(request); String lookupPath = new UrlPathHelper().getLookupPathForRequest(request);
//
// RequestMappingInfo key = new RequestMappingInfo(singleton("/foo"), null, null, null, RequestConditionFactory.parseConsumes( RequestMappingInfo key = new RequestMappingInfo(singleton("/foo"), null, null, null, RequestConditionFactory.parseConsumes(
// "text/plain")); "text/plain"));
// RequestMappingInfo match = key.getMatchingKey(lookupPath, request, pathMatcher); RequestMappingInfo match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
//
// assertNotNull(match); assertNotNull(match);
//
// key = new RequestMappingInfo(singleton("/foo"), null, null, null, RequestConditionFactory.parseConsumes( key = new RequestMappingInfo(singleton("/foo"), null, null, null, RequestConditionFactory.parseConsumes(
// "application/xml")); "application/xml"));
// match = key.getMatchingKey(lookupPath, request, pathMatcher); match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
//
// assertNull(match); assertNull(match);
// } }
private RequestMappingInfo createKeyFromPatterns(String... patterns) { private RequestMappingInfo createKeyFromPatterns(String... patterns) {
return new RequestMappingInfo(asList(patterns), null); return new RequestMappingInfo(asList(patterns), null);

View File

@ -55,7 +55,7 @@ import java.lang.annotation.Target;
* As a consequence, such an argument will never be <code>null</code>. * As a consequence, such an argument will never be <code>null</code>.
* <i>Note that session access may not be thread-safe, in particular in a * <i>Note that session access may not be thread-safe, in particular in a
* Servlet environment: Consider switching the * Servlet environment: Consider switching the
* {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#setSynchronizeOnSession "synchronizeOnSession"} * {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter#setSynchronizeOnSession "synchronizeOnSession"}
* flag to "true" if multiple requests are allowed to access a session concurrently.</i> * flag to "true" if multiple requests are allowed to access a session concurrently.</i>
* <li>{@link org.springframework.web.context.request.WebRequest} or * <li>{@link org.springframework.web.context.request.WebRequest} or
* {@link org.springframework.web.context.request.NativeWebRequest}. * {@link org.springframework.web.context.request.NativeWebRequest}.
@ -106,7 +106,7 @@ import java.lang.annotation.Target;
* <li>Command/form objects to bind parameters to: as bean properties or fields, * <li>Command/form objects to bind parameters to: as bean properties or fields,
* with customizable type conversion, depending on {@link InitBinder} methods * with customizable type conversion, depending on {@link InitBinder} methods
* and/or the HandlerAdapter configuration - see the "webBindingInitializer" * and/or the HandlerAdapter configuration - see the "webBindingInitializer"
* property on AnnotationMethodHandlerAdapter. * property on RequestMappingHandlerMethodAdapter.
* Such command objects along with their validation results will be exposed * Such command objects along with their validation results will be exposed
* as model attributes, by default using the non-qualified command class name * as model attributes, by default using the non-qualified command class name
* in property notation (e.g. "orderAddress" for type "mypackage.OrderAddress"). * in property notation (e.g. "orderAddress" for type "mypackage.OrderAddress").
@ -180,8 +180,8 @@ import java.lang.annotation.Target;
* <code>DispatcherServlet</code> and <code>DispatcherPortlet</code>. * <code>DispatcherServlet</code> and <code>DispatcherPortlet</code>.
* However, if you are defining custom <code>HandlerMappings</code> or * However, if you are defining custom <code>HandlerMappings</code> or
* <code>HandlerAdapters</code>, then you need to make sure that a * <code>HandlerAdapters</code>, then you need to make sure that a
* corresponding custom <code>DefaultAnnotationHandlerMapping</code> * corresponding custom <code>RequestMappingHandlerMethodMapping</code>
* and/or <code>AnnotationMethodHandlerAdapter</code> is defined as well * and/or <code>RequestMappingHandlerMethodAdapter</code> is defined as well
* - provided that you intend to use <code>@RequestMapping</code>. * - provided that you intend to use <code>@RequestMapping</code>.
* *
* <p><b>NOTE:</b> When using controller interfaces (e.g. for AOP proxying), * <p><b>NOTE:</b> When using controller interfaces (e.g. for AOP proxying),
@ -198,8 +198,8 @@ import java.lang.annotation.Target;
* @see SessionAttributes * @see SessionAttributes
* @see InitBinder * @see InitBinder
* @see org.springframework.web.context.request.WebRequest * @see org.springframework.web.context.request.WebRequest
* @see org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodMapping
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter
* @see org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping * @see org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter * @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter
*/ */
@ -297,6 +297,4 @@ public @interface RequestMapping {
*/ */
String[] headers() default {}; String[] headers() default {};
String[] consumes() default "*/*";
} }