From a37c85f4fc913310ad53b32d545a63147de31826 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Fri, 8 Apr 2011 12:06:53 +0000 Subject: [PATCH] SPR-7354 - Added equivalent of JAX-RS @Consumes to Spring MVC git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@4197 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../mvc/method/annotation/RequestKey.java | 21 ++++---------- .../condition/ConsumesRequestCondition.java | 16 ++++++----- .../condition/RequestConditionFactory.java | 10 +++++++ .../method/annotation/RequestKeyTests.java | 28 ++++++++++++++++--- 4 files changed, 49 insertions(+), 26 deletions(-) diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestKey.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestKey.java index 1fcdb95516c..50348e785a8 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestKey.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestKey.java @@ -164,12 +164,9 @@ public final class RequestKey { Set methods = union(this.methods, methodKey.methods); RequestCondition params = RequestConditionFactory.and(this.paramsCondition, methodKey.paramsCondition); RequestCondition headers = RequestConditionFactory.and(this.headersCondition, methodKey.headersCondition); - RequestCondition consumes; -// if (methodKey.consumesCondition.weight() > this.consumesCondition.weight()) { -// -// } + RequestCondition consumes = RequestConditionFactory.mostSpecific(methodKey.consumesCondition, this.consumesCondition); - return new RequestKey(patterns, methods, params, headers, null); + return new RequestKey(patterns, methods, params, headers, consumes); } private static Set combinePatterns(Collection typePatterns, @@ -213,14 +210,16 @@ public final class RequestKey { * @return a new request key that contains all matching attributes */ public RequestKey getMatchingKey(HttpServletRequest request, PathMatcher pathMatcher, UrlPathHelper urlPathHelper) { - if (!checkMethod(request) || !checkParams(request) || !checkHeaders(request)) { + if (!checkMethod(request) || !paramsCondition.match(request) || !headersCondition.match(request) || + !consumesCondition.match(request)) { return null; } else { List matchingPatterns = getMatchingPatterns(request, pathMatcher, urlPathHelper); if (!matchingPatterns.isEmpty()) { Set matchingMethods = getMatchingMethods(request); - return new RequestKey(matchingPatterns, matchingMethods, this.paramsCondition, this.headersCondition, null); + return new RequestKey(matchingPatterns, matchingMethods, this.paramsCondition, this.headersCondition, + this.consumesCondition); } else { return null; @@ -259,14 +258,6 @@ public final class RequestKey { return methods.isEmpty() || methods.contains(RequestMethod.valueOf(request.getMethod())); } - private boolean checkParams(HttpServletRequest request) { - return paramsCondition.match(request); - } - - private boolean checkHeaders(HttpServletRequest request) { - return headersCondition.match(request); - } - private String getMatchingPattern(String pattern, String lookupPath, PathMatcher pathMatcher) { if (pattern.equals(lookupPath) || pathMatcher.match(pattern, lookupPath)) { return pattern; diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/condition/ConsumesRequestCondition.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/condition/ConsumesRequestCondition.java index 7de8d288918..204a7440d3d 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/condition/ConsumesRequestCondition.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/condition/ConsumesRequestCondition.java @@ -22,8 +22,8 @@ import org.springframework.http.MediaType; import org.springframework.util.StringUtils; /** -* @author Arjen Poutsma -*/ + * @author Arjen Poutsma + */ class ConsumesRequestCondition extends AbstractRequestCondition { private final MediaType mediaType; @@ -33,12 +33,14 @@ class ConsumesRequestCondition extends AbstractRequestCondition { } public boolean match(HttpServletRequest request) { - String contentTypeString = request.getContentType(); - if (StringUtils.hasLength(contentTypeString)) { - MediaType contentType = MediaType.parseMediaType(contentTypeString); - return this.mediaType.includes(contentType); + MediaType contentType; + if (StringUtils.hasLength(request.getContentType())) { + contentType = MediaType.parseMediaType(request.getContentType()); + } + else { + contentType = MediaType.APPLICATION_OCTET_STREAM; } - return false; + return this.mediaType.includes(contentType); } @Override diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/condition/RequestConditionFactory.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/condition/RequestConditionFactory.java index 6c9fc89e185..f33ff7a3c7c 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/condition/RequestConditionFactory.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/condition/RequestConditionFactory.java @@ -84,6 +84,16 @@ public abstract class RequestConditionFactory { return FALSE_CONDITION; } + public static RequestCondition mostSpecific(RequestCondition... conditions) { + if (ObjectUtils.isEmpty(conditions)) { + return trueCondition(); + } + RequestCondition[] copy = new RequestCondition[conditions.length]; + System.arraycopy(conditions, 0, copy, 0, conditions.length); + Arrays.sort(copy); + return copy[0]; + } + /** * Combines the given conditions into a logical AND, i.e. the returned condition will return {@code true} for {@link * RequestCondition#match(HttpServletRequest)} if all of the given conditions do so. diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestKeyTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestKeyTests.java index c44817ba504..d66c7f695cf 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestKeyTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestKeyTests.java @@ -147,7 +147,7 @@ public class RequestKeyTests { } @Test - public void testMatchingKeyContent() { + public void matchingKeyContent() { UrlPathHelper urlPathHelper = new UrlPathHelper(); PathMatcher pathMatcher = new AntPathMatcher(); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); @@ -167,7 +167,7 @@ public class RequestKeyTests { } @Test - public void testParamConditions() { + public void paramsCondition() { UrlPathHelper urlPathHelper = new UrlPathHelper(); PathMatcher pathMatcher = new AntPathMatcher(); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); @@ -185,7 +185,7 @@ public class RequestKeyTests { } @Test - public void testHeaderConditions() { + public void headersCondition() { UrlPathHelper urlPathHelper = new UrlPathHelper(); PathMatcher pathMatcher = new AntPathMatcher(); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); @@ -203,7 +203,27 @@ public class RequestKeyTests { } @Test - public void testCreateFromServletRequest() { + public void consumesCondition() { + UrlPathHelper urlPathHelper = new UrlPathHelper(); + PathMatcher pathMatcher = new AntPathMatcher(); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); + request.setContentType("text/plain"); + + RequestKey key = new RequestKey(singleton("/foo"), null, null, null, RequestConditionFactory.parseConsumes( + "text/plain")); + RequestKey match = key.getMatchingKey(request, pathMatcher, urlPathHelper); + + assertNotNull(match); + + key = new RequestKey(singleton("/foo"), null, null, null, RequestConditionFactory.parseConsumes( + "application/xml")); + match = key.getMatchingKey(request, pathMatcher, urlPathHelper); + + assertNull(match); + } + + @Test + public void createFromServletRequest() { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); RequestKey key = RequestKey.createFromServletRequest(request, new UrlPathHelper()); assertEquals(new RequestKey(singleton("/foo"), singleton(RequestMethod.GET), null, null, null), key);