SPR-7354 - Added equivalent of JAX-RS @Consumes to Spring MVC
This commit is contained in:
parent
bf6693dbc5
commit
ff89c0e55a
|
|
@ -155,15 +155,19 @@ public final class RequestKey {
|
||||||
* Combines this {@code RequestKey} with another. The typical use case for this is combining type
|
* Combines this {@code RequestKey} with another. The typical use case for this is combining type
|
||||||
* and method-level {@link RequestMapping @RequestMapping} annotations.
|
* and method-level {@link RequestMapping @RequestMapping} annotations.
|
||||||
*
|
*
|
||||||
* @param other the method-level RequestKey
|
* @param methodKey the method-level RequestKey
|
||||||
* @param pathMatcher to {@linkplain PathMatcher#combine(String, String) combine} the patterns
|
* @param pathMatcher to {@linkplain PathMatcher#combine(String, String) combine} the patterns
|
||||||
* @return the combined request key
|
* @return the combined request key
|
||||||
*/
|
*/
|
||||||
public RequestKey combine(RequestKey other, PathMatcher pathMatcher) {
|
public RequestKey combine(RequestKey methodKey, PathMatcher pathMatcher) {
|
||||||
Set<String> patterns = combinePatterns(this.patterns, other.patterns, pathMatcher);
|
Set<String> patterns = combinePatterns(this.patterns, methodKey.patterns, pathMatcher);
|
||||||
Set<RequestMethod> methods = union(this.methods, other.methods);
|
Set<RequestMethod> methods = union(this.methods, methodKey.methods);
|
||||||
RequestCondition params = RequestConditionFactory.and(this.paramsCondition, other.paramsCondition);
|
RequestCondition params = RequestConditionFactory.and(this.paramsCondition, methodKey.paramsCondition);
|
||||||
RequestCondition headers = RequestConditionFactory.and(this.headersCondition, other.headersCondition);
|
RequestCondition headers = RequestConditionFactory.and(this.headersCondition, methodKey.headersCondition);
|
||||||
|
RequestCondition consumes;
|
||||||
|
// if (methodKey.consumesCondition.weight() > this.consumesCondition.weight()) {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
return new RequestKey(patterns, methods, params, headers, null);
|
return new RequestKey(patterns, methods, params, headers, null);
|
||||||
}
|
}
|
||||||
|
|
@ -278,15 +282,6 @@ public final class RequestKey {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkConditions(Set<RequestCondition> conditions, HttpServletRequest request) {
|
|
||||||
for (RequestCondition condition : conditions) {
|
|
||||||
if (!condition.match(request)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
|
|
|
||||||
|
|
@ -252,11 +252,11 @@ public class RequestMappingHandlerMethodMapping extends AbstractHandlerMethodMap
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = otherKey.getParams().weight() - key.getParams().weight();
|
result = key.getParams().compareTo(otherKey.getParams());
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = otherKey.getHeaders().weight() - key.getHeaders().weight();
|
result = key.getHeaders().compareTo(otherKey.getHeaders());
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
abstract class AbstractNameValueCondition<T> implements RequestCondition {
|
abstract class AbstractNameValueCondition<T> extends AbstractRequestCondition {
|
||||||
|
|
||||||
protected final String name;
|
protected final String name;
|
||||||
|
|
||||||
|
|
@ -35,6 +35,7 @@ abstract class AbstractNameValueCondition<T> implements RequestCondition {
|
||||||
protected final boolean isNegated;
|
protected final boolean isNegated;
|
||||||
|
|
||||||
AbstractNameValueCondition(String expression) {
|
AbstractNameValueCondition(String expression) {
|
||||||
|
super(1);
|
||||||
int separator = expression.indexOf('=');
|
int separator = expression.indexOf('=');
|
||||||
if (separator == -1) {
|
if (separator == -1) {
|
||||||
this.isNegated = expression.startsWith("!");
|
this.isNegated = expression.startsWith("!");
|
||||||
|
|
@ -65,11 +66,6 @@ abstract class AbstractNameValueCondition<T> implements RequestCondition {
|
||||||
|
|
||||||
protected abstract boolean matchValue(HttpServletRequest request);
|
protected abstract boolean matchValue(HttpServletRequest request);
|
||||||
|
|
||||||
public int weight() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = name.hashCode();
|
int result = name.hashCode();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2011 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.web.servlet.mvc.method.condition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract base class for {@link RequestCondition} that provides a standard {@link Comparable} implementation.
|
||||||
|
*
|
||||||
|
* @author Arjen Poutsma
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
public abstract class AbstractRequestCondition implements RequestCondition {
|
||||||
|
|
||||||
|
private final int weight;
|
||||||
|
|
||||||
|
protected AbstractRequestCondition(int weight) {
|
||||||
|
this.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWeight() {
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compareTo(RequestCondition o) {
|
||||||
|
AbstractRequestCondition other = (AbstractRequestCondition) o;
|
||||||
|
return other.weight - this.weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -24,11 +24,12 @@ import org.springframework.util.StringUtils;
|
||||||
/**
|
/**
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
*/
|
*/
|
||||||
class ConsumesRequestCondition implements RequestCondition {
|
class ConsumesRequestCondition extends AbstractRequestCondition {
|
||||||
|
|
||||||
private final MediaType mediaType;
|
private final MediaType mediaType;
|
||||||
|
|
||||||
ConsumesRequestCondition(String mediaType) {
|
ConsumesRequestCondition(String mediaType) {
|
||||||
|
super(1);
|
||||||
this.mediaType = MediaType.parseMediaType(mediaType);
|
this.mediaType = MediaType.parseMediaType(mediaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,7 +42,4 @@ class ConsumesRequestCondition implements RequestCondition {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int weight() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
* @see RequestConditionFactory
|
* @see RequestConditionFactory
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
public interface RequestCondition {
|
public interface RequestCondition extends Comparable<RequestCondition> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether this condition matches against the given servlet request.
|
* Indicates whether this condition matches against the given servlet request.
|
||||||
|
|
@ -39,11 +39,4 @@ public interface RequestCondition {
|
||||||
*/
|
*/
|
||||||
boolean match(HttpServletRequest request);
|
boolean match(HttpServletRequest request);
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates the relative weight of this condition. More important conditions have a higher weight than ones that are
|
|
||||||
* less so.
|
|
||||||
*
|
|
||||||
* @return the weight of this condition
|
|
||||||
*/
|
|
||||||
int weight();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.web.servlet.mvc.method.condition;
|
package org.springframework.web.servlet.mvc.method.condition;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -25,20 +26,24 @@ import java.util.List;
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
abstract class RequestConditionComposite implements RequestCondition {
|
abstract class RequestConditionComposite extends AbstractRequestCondition {
|
||||||
|
|
||||||
protected final List<RequestCondition> conditions;
|
protected final List<RequestCondition> conditions;
|
||||||
|
|
||||||
public RequestConditionComposite(List<RequestCondition> conditions) {
|
protected RequestConditionComposite(List<RequestCondition> conditions) {
|
||||||
this.conditions = conditions;
|
super(getWeight(conditions));
|
||||||
|
this.conditions = Collections.unmodifiableList(conditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int weight() {
|
private static int getWeight(List<RequestCondition> conditions) {
|
||||||
int size = 0;
|
int weight = 0;
|
||||||
for (RequestCondition condition : conditions) {
|
for (RequestCondition condition : conditions) {
|
||||||
size += condition.weight();
|
if (condition instanceof AbstractRequestCondition) {
|
||||||
|
AbstractRequestCondition abstractRequestCondition = (AbstractRequestCondition) condition;
|
||||||
|
weight += abstractRequestCondition.getWeight();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return size;
|
return weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -33,41 +33,42 @@ import org.springframework.util.ObjectUtils;
|
||||||
*/
|
*/
|
||||||
public abstract class RequestConditionFactory {
|
public abstract class RequestConditionFactory {
|
||||||
|
|
||||||
private static final RequestCondition TRUE_CONDITION = new RequestCondition() {
|
private static final RequestCondition TRUE_CONDITION = new AbstractRequestCondition(0) {
|
||||||
public boolean match(HttpServletRequest request) {
|
public boolean match(HttpServletRequest request) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int weight() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TRUE";
|
return "TRUE";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final RequestCondition FALSE_CONDITION = new RequestCondition() {
|
private static final RequestCondition FALSE_CONDITION = new AbstractRequestCondition(0) {
|
||||||
public boolean match(HttpServletRequest request) {
|
public boolean match(HttpServletRequest request) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int weight() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "FALSE";
|
return "FALSE";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a condition that always returns {@code true} for {@link RequestCondition#match(HttpServletRequest)}.
|
||||||
|
*
|
||||||
|
* @return a condition that returns {@code true}
|
||||||
|
*/
|
||||||
public static RequestCondition trueCondition() {
|
public static RequestCondition trueCondition() {
|
||||||
return TRUE_CONDITION;
|
return TRUE_CONDITION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a condition that always returns {@code false} for {@link RequestCondition#match(HttpServletRequest)}.
|
||||||
|
*
|
||||||
|
* @return a condition that returns {@code false}
|
||||||
|
*/
|
||||||
public static RequestCondition falseCondition() {
|
public static RequestCondition falseCondition() {
|
||||||
return FALSE_CONDITION;
|
return FALSE_CONDITION;
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +88,12 @@ public abstract class RequestConditionFactory {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new LogicalConjunctionRequestCondition(filteredConditions);
|
if (filteredConditions.isEmpty()) {
|
||||||
|
return trueCondition();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new LogicalConjunctionRequestCondition(filteredConditions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -108,7 +114,12 @@ public abstract class RequestConditionFactory {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new LogicalDisjunctionRequestCondition(filteredConditions);
|
if (filteredConditions.isEmpty()) {
|
||||||
|
return trueCondition();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new LogicalDisjunctionRequestCondition(filteredConditions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -120,7 +131,7 @@ public abstract class RequestConditionFactory {
|
||||||
*/
|
*/
|
||||||
public static RequestCondition parseParams(String... params) {
|
public static RequestCondition parseParams(String... params) {
|
||||||
if (ObjectUtils.isEmpty(params)) {
|
if (ObjectUtils.isEmpty(params)) {
|
||||||
return TRUE_CONDITION;
|
return trueCondition();
|
||||||
}
|
}
|
||||||
RequestCondition[] result = new RequestCondition[params.length];
|
RequestCondition[] result = new RequestCondition[params.length];
|
||||||
for (int i = 0; i < params.length; i++) {
|
for (int i = 0; i < params.length; i++) {
|
||||||
|
|
@ -138,7 +149,7 @@ public abstract class RequestConditionFactory {
|
||||||
*/
|
*/
|
||||||
public static RequestCondition parseHeaders(String... headers) {
|
public static RequestCondition parseHeaders(String... headers) {
|
||||||
if (ObjectUtils.isEmpty(headers)) {
|
if (ObjectUtils.isEmpty(headers)) {
|
||||||
return TRUE_CONDITION;
|
return trueCondition();
|
||||||
}
|
}
|
||||||
RequestCondition[] result = new RequestCondition[headers.length];
|
RequestCondition[] result = new RequestCondition[headers.length];
|
||||||
for (int i = 0; i < headers.length; i++) {
|
for (int i = 0; i < headers.length; i++) {
|
||||||
|
|
@ -157,9 +168,16 @@ public abstract class RequestConditionFactory {
|
||||||
return "Accept".equalsIgnoreCase(name) || "Content-Type".equalsIgnoreCase(name);
|
return "Accept".equalsIgnoreCase(name) || "Content-Type".equalsIgnoreCase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given consumes, and returns them as a single request condition.
|
||||||
|
*
|
||||||
|
* @param consumes the consumes
|
||||||
|
* @return the request condition
|
||||||
|
* @see org.springframework.web.bind.annotation.RequestMapping#consumes()
|
||||||
|
*/
|
||||||
public static RequestCondition parseConsumes(String... consumes) {
|
public static RequestCondition parseConsumes(String... consumes) {
|
||||||
if (ObjectUtils.isEmpty(consumes)) {
|
if (ObjectUtils.isEmpty(consumes)) {
|
||||||
return TRUE_CONDITION;
|
return trueCondition();
|
||||||
}
|
}
|
||||||
RequestCondition[] result = new RequestCondition[consumes.length];
|
RequestCondition[] result = new RequestCondition[consumes.length];
|
||||||
for (int i = 0; i < consumes.length; i++) {
|
for (int i = 0; i < consumes.length; i++) {
|
||||||
|
|
@ -168,8 +186,4 @@ public abstract class RequestConditionFactory {
|
||||||
return or(result);
|
return or(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Conditions
|
|
||||||
//
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue