Add CompositeRequestCondition
The new type makes it easier providing multiple custom request mapping conditions via setters on RequestMappingHandlerMapping. Issue: SPR-9350
This commit is contained in:
parent
fbb2103e4d
commit
bdc3599d3d
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright 2002-2012 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.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import edu.emory.mathcs.backport.java.util.Collections;
|
||||
|
||||
/**
|
||||
* Implements the {@link RequestCondition} contract by delegating to multiple
|
||||
* {@code RequestCondition} types and using a logical conjunction (' && ') to
|
||||
* ensure all conditions match a given request.
|
||||
*
|
||||
* <p>When {@code CompositeRequestCondition} instances are combined or compared
|
||||
* they are expected to (a) contain the same number of conditions and (b) that
|
||||
* conditions in the respective index are of the same type. It is acceptable to
|
||||
* provide {@code null} conditions or no conditions at all to the constructor.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class CompositeRequestCondition extends AbstractRequestCondition<CompositeRequestCondition> {
|
||||
|
||||
private final RequestConditionHolder[] requestConditions;
|
||||
|
||||
/**
|
||||
* Create an instance with 0 or more {@code RequestCondition} types. It is
|
||||
* important to create {@code CompositeRequestCondition} instances with the
|
||||
* same number of conditions so they may be compared and combined.
|
||||
* It is acceptable to provide {@code null} conditions.
|
||||
*/
|
||||
public CompositeRequestCondition(RequestCondition<?>... requestConditions) {
|
||||
this.requestConditions = wrap(requestConditions);
|
||||
}
|
||||
|
||||
private RequestConditionHolder[] wrap(RequestCondition<?>... rawConditions) {
|
||||
RequestConditionHolder[] wrappedConditions = new RequestConditionHolder[rawConditions.length];
|
||||
for (int i = 0; i < rawConditions.length; i++) {
|
||||
wrappedConditions[i] = new RequestConditionHolder(rawConditions[i]);
|
||||
}
|
||||
return wrappedConditions;
|
||||
}
|
||||
|
||||
private CompositeRequestCondition(RequestConditionHolder[] requestConditions) {
|
||||
this.requestConditions = requestConditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this instance contains 0 conditions or not.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return ObjectUtils.isEmpty(this.requestConditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying conditions, possibly empty but never {@code null}.
|
||||
*/
|
||||
public List<RequestCondition<?>> getConditions() {
|
||||
return unwrap();
|
||||
}
|
||||
|
||||
private List<RequestCondition<?>> unwrap() {
|
||||
List<RequestCondition<?>> result = new ArrayList<RequestCondition<?>>();
|
||||
for (RequestConditionHolder holder : this.requestConditions) {
|
||||
result.add(holder.getCondition());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<?> getContent() {
|
||||
return (isEmpty()) ? Collections.emptyList() : getConditions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getToStringInfix() {
|
||||
return " && ";
|
||||
}
|
||||
|
||||
private int getLength() {
|
||||
return this.requestConditions.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* If one instance is empty, return the other.
|
||||
* If both instances have conditions, combine the individual conditions
|
||||
* after ensuring they are of the same type and number.
|
||||
*/
|
||||
public CompositeRequestCondition combine(CompositeRequestCondition other) {
|
||||
if (isEmpty() && other.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
else if (other.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
else if (isEmpty()) {
|
||||
return other;
|
||||
}
|
||||
else {
|
||||
assertNumberOfConditions(other);
|
||||
RequestConditionHolder[] combinedConditions = new RequestConditionHolder[getLength()];
|
||||
for (int i = 0; i < getLength(); i++) {
|
||||
combinedConditions[i] = this.requestConditions[i].combine(other.requestConditions[i]);
|
||||
}
|
||||
return new CompositeRequestCondition(combinedConditions);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertNumberOfConditions(CompositeRequestCondition other) {
|
||||
Assert.isTrue(getLength() == other.getLength(),
|
||||
"Cannot combine CompositeRequestConditions with a different number of conditions. "
|
||||
+ this.requestConditions + " and " + other.requestConditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate to <em>all</em> contained conditions to match the request and return the
|
||||
* resulting "matching" condition instances.
|
||||
* <p>An empty {@code CompositeRequestCondition} matches to all requests.
|
||||
*/
|
||||
public CompositeRequestCondition getMatchingCondition(HttpServletRequest request) {
|
||||
if (isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
RequestConditionHolder[] matchingConditions = new RequestConditionHolder[getLength()];
|
||||
for (int i = 0; i < getLength(); i++) {
|
||||
matchingConditions[i] = this.requestConditions[i].getMatchingCondition(request);
|
||||
if (matchingConditions[i] == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new CompositeRequestCondition(matchingConditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* If one instance is empty, the other "wins". If both instances have
|
||||
* conditions, compare them in the order in which they were provided.
|
||||
*/
|
||||
public int compareTo(CompositeRequestCondition other, HttpServletRequest request) {
|
||||
if (isEmpty() && other.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
else if (isEmpty()) {
|
||||
return 1;
|
||||
}
|
||||
else if (other.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
assertNumberOfConditions(other);
|
||||
for (int i = 0; i < getLength(); i++) {
|
||||
int result = this.requestConditions[i].compareTo(other.requestConditions[i], request);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
|
|
@ -23,40 +23,42 @@ import javax.servlet.http.HttpServletRequest;
|
|||
|
||||
|
||||
/**
|
||||
* A holder for a {@link RequestCondition} useful when the type of the held
|
||||
* request condition is not known ahead of time - e.g. custom condition.
|
||||
* A holder for a {@link RequestCondition} useful when the type of the request
|
||||
* condition is not known ahead of time, e.g. custom condition. Since this
|
||||
* class is also an implementation of {@code RequestCondition}, effectively it
|
||||
* decorates the held request condition and allows it to be combined and compared
|
||||
* with other request conditions in a type and null safe way.
|
||||
*
|
||||
* <p>An implementation of {@code RequestCondition} itself, a
|
||||
* {@code RequestConditionHolder} decorates the held request condition allowing
|
||||
* it to be combined and compared with other custom request conditions while
|
||||
* ensuring type and null safety.
|
||||
* <p>When two {@code RequestConditionHolder} instances are combined or compared
|
||||
* with each other, it is expected the conditions they hold are of the same type.
|
||||
* If they are not, a {@link ClassCastException} is raised.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
*/
|
||||
public final class RequestConditionHolder extends AbstractRequestCondition<RequestConditionHolder> {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final RequestCondition condition;
|
||||
private final RequestCondition<Object> condition;
|
||||
|
||||
/**
|
||||
* Create a new holder to wrap the given request condition.
|
||||
* @param requestCondition the condition to hold, may be {@code null}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public RequestConditionHolder(RequestCondition<?> requestCondition) {
|
||||
this.condition = requestCondition;
|
||||
this.condition = (RequestCondition<Object>) requestCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the held request condition, or {@code null} if not holding one.
|
||||
*/
|
||||
public RequestCondition<?> getCondition() {
|
||||
return condition;
|
||||
return this.condition;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<?> getContent() {
|
||||
return condition != null ? Collections.singleton(condition) : Collections.emptyList();
|
||||
return this.condition != null ? Collections.singleton(this.condition) : Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -69,20 +71,19 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
|
|||
* instances after making sure the conditions are of the same type.
|
||||
* Or if one holder is empty, the other holder is returned.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public RequestConditionHolder combine(RequestConditionHolder other) {
|
||||
if (condition == null && other.condition == null) {
|
||||
if (this.condition == null && other.condition == null) {
|
||||
return this;
|
||||
}
|
||||
else if (condition == null) {
|
||||
else if (this.condition == null) {
|
||||
return other;
|
||||
}
|
||||
else if (other.condition == null) {
|
||||
return this;
|
||||
}
|
||||
else {
|
||||
assertIsCompatible(other);
|
||||
RequestCondition<?> combined = (RequestCondition<?>) condition.combine(other.condition);
|
||||
assertEqualConditionTypes(other);
|
||||
RequestCondition<?> combined = (RequestCondition<?>) this.condition.combine(other.condition);
|
||||
return new RequestConditionHolder(combined);
|
||||
}
|
||||
}
|
||||
|
|
@ -90,8 +91,8 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
|
|||
/**
|
||||
* Ensure the held request conditions are of the same type.
|
||||
*/
|
||||
private void assertIsCompatible(RequestConditionHolder other) {
|
||||
Class<?> clazz = condition.getClass();
|
||||
private void assertEqualConditionTypes(RequestConditionHolder other) {
|
||||
Class<?> clazz = this.condition.getClass();
|
||||
Class<?> otherClazz = other.condition.getClass();
|
||||
if (!clazz.equals(otherClazz)) {
|
||||
throw new ClassCastException("Incompatible request conditions: " + clazz + " and " + otherClazz);
|
||||
|
|
@ -104,10 +105,10 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
|
|||
* holder, return the same holder instance.
|
||||
*/
|
||||
public RequestConditionHolder getMatchingCondition(HttpServletRequest request) {
|
||||
if (condition == null) {
|
||||
if (this.condition == null) {
|
||||
return this;
|
||||
}
|
||||
RequestCondition<?> match = (RequestCondition<?>) condition.getMatchingCondition(request);
|
||||
RequestCondition<?> match = (RequestCondition<?>) this.condition.getMatchingCondition(request);
|
||||
return (match != null) ? new RequestConditionHolder(match) : null;
|
||||
}
|
||||
|
||||
|
|
@ -116,20 +117,19 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
|
|||
* instances after making sure the conditions are of the same type.
|
||||
* Or if one holder is empty, the other holder is preferred.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public int compareTo(RequestConditionHolder other, HttpServletRequest request) {
|
||||
if (condition == null && other.condition == null) {
|
||||
if (this.condition == null && other.condition == null) {
|
||||
return 0;
|
||||
}
|
||||
else if (condition == null) {
|
||||
else if (this.condition == null) {
|
||||
return 1;
|
||||
}
|
||||
else if (other.condition == null) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
assertIsCompatible(other);
|
||||
return condition.compareTo(other.condition, request);
|
||||
assertEqualConditionTypes(other);
|
||||
return this.condition.compareTo(other.condition, request);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import java.lang.reflect.Method;
|
|||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.mvc.condition.AbstractRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.CompositeRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition;
|
||||
|
|
@ -113,23 +115,16 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
|||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a custom method-level request condition.
|
||||
* The custom {@link RequestCondition} can be of any type so long as the
|
||||
* same condition type is returned from all calls to this method in order
|
||||
* to ensure custom request conditions can be combined and compared.
|
||||
* @param method the handler method for which to create the condition
|
||||
* @return the condition, or {@code null}
|
||||
*/
|
||||
protected RequestCondition<?> getCustomMethodCondition(Method method) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a custom type-level request condition.
|
||||
* The custom {@link RequestCondition} can be of any type so long as the
|
||||
* same condition type is returned from all calls to this method in order
|
||||
* to ensure custom request conditions can be combined and compared.
|
||||
*
|
||||
* <p>Consider extending {@link AbstractRequestCondition} for custom
|
||||
* condition types and using {@link CompositeRequestCondition} to provide
|
||||
* multiple custom conditions.
|
||||
*
|
||||
* @param handlerType the handler type for which to create the condition
|
||||
* @return the condition, or {@code null}
|
||||
*/
|
||||
|
|
@ -137,6 +132,23 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a custom method-level request condition.
|
||||
* The custom {@link RequestCondition} can be of any type so long as the
|
||||
* same condition type is returned from all calls to this method in order
|
||||
* to ensure custom request conditions can be combined and compared.
|
||||
*
|
||||
* <p>Consider extending {@link AbstractRequestCondition} for custom
|
||||
* condition types and using {@link CompositeRequestCondition} to provide
|
||||
* multiple custom conditions.
|
||||
*
|
||||
* @param method the handler method for which to create the condition
|
||||
* @return the condition, or {@code null}
|
||||
*/
|
||||
protected RequestCondition<?> getCustomMethodCondition(Method method) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Created a RequestMappingInfo from a RequestMapping annotation.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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.condition;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
/**
|
||||
* A test fixture for {@link CompositeRequestCondition} tests.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class CompositeRequestConditionTests {
|
||||
|
||||
private ParamsRequestCondition param1;
|
||||
private ParamsRequestCondition param2;
|
||||
private ParamsRequestCondition param3;
|
||||
|
||||
private HeadersRequestCondition header1;
|
||||
private HeadersRequestCondition header2;
|
||||
private HeadersRequestCondition header3;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.param1 = new ParamsRequestCondition("param1");
|
||||
this.param2 = new ParamsRequestCondition("param2");
|
||||
this.param3 = this.param1.combine(this.param2);
|
||||
|
||||
this.header1 = new HeadersRequestCondition("header1");
|
||||
this.header2 = new HeadersRequestCondition("header2");
|
||||
this.header3 = this.header1.combine(this.header2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combine() {
|
||||
CompositeRequestCondition cond1 = new CompositeRequestCondition(this.param1, this.header1);
|
||||
CompositeRequestCondition cond2 = new CompositeRequestCondition(this.param2, this.header2);
|
||||
CompositeRequestCondition cond3 = new CompositeRequestCondition(this.param3, this.header3);
|
||||
|
||||
assertEquals(cond3, cond1.combine(cond2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineEmpty() {
|
||||
CompositeRequestCondition empty = new CompositeRequestCondition();
|
||||
CompositeRequestCondition notEmpty = new CompositeRequestCondition(this.param1);
|
||||
|
||||
assertSame(empty, empty.combine(empty));
|
||||
assertSame(notEmpty, notEmpty.combine(empty));
|
||||
assertSame(notEmpty, empty.combine(notEmpty));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void combineDifferentLength() {
|
||||
CompositeRequestCondition cond1 = new CompositeRequestCondition(this.param1);
|
||||
CompositeRequestCondition cond2 = new CompositeRequestCondition(this.param1, this.header1);
|
||||
cond1.combine(cond2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void match() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.setParameter("param1", "paramValue1");
|
||||
request.addHeader("header1", "headerValue1");
|
||||
|
||||
RequestCondition<?> getPostCond = new RequestMethodsRequestCondition(RequestMethod.GET, RequestMethod.POST);
|
||||
RequestCondition<?> getCond = new RequestMethodsRequestCondition(RequestMethod.GET);
|
||||
|
||||
CompositeRequestCondition condition = new CompositeRequestCondition(this.param1, getPostCond);
|
||||
CompositeRequestCondition matchingCondition = new CompositeRequestCondition(this.param1, getCond);
|
||||
|
||||
assertEquals(matchingCondition, condition.getMatchingCondition(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
CompositeRequestCondition cond = new CompositeRequestCondition(this.param1);
|
||||
|
||||
assertNull(cond.getMatchingCondition(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchEmpty() {
|
||||
CompositeRequestCondition empty = new CompositeRequestCondition();
|
||||
assertSame(empty, empty.getMatchingCondition(new MockHttpServletRequest()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compare() {
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
CompositeRequestCondition cond1 = new CompositeRequestCondition(this.param1);
|
||||
CompositeRequestCondition cond3 = new CompositeRequestCondition(this.param3);
|
||||
|
||||
assertEquals(1, cond1.compareTo(cond3, request));
|
||||
assertEquals(-1, cond3.compareTo(cond1, request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareEmpty() {
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
CompositeRequestCondition empty = new CompositeRequestCondition();
|
||||
CompositeRequestCondition notEmpty = new CompositeRequestCondition(this.param1);
|
||||
|
||||
assertEquals(0, empty.compareTo(empty, request));
|
||||
assertEquals(-1, notEmpty.compareTo(empty, request));
|
||||
assertEquals(1, empty.compareTo(notEmpty, request));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void compareDifferentLength() {
|
||||
CompositeRequestCondition cond1 = new CompositeRequestCondition(this.param1);
|
||||
CompositeRequestCondition cond2 = new CompositeRequestCondition(this.param1, this.header1);
|
||||
cond1.compareTo(cond2, new MockHttpServletRequest());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
|
|
@ -27,23 +27,12 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
|||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
/**
|
||||
* A test fixture for
|
||||
* {code org.springframework.web.servlet.mvc.method.RequestConditionHolder} tests.
|
||||
* A test fixture for {@link RequestConditionHolder} tests.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class RequestConditionHolderTests {
|
||||
|
||||
@Test
|
||||
public void combineEmpty() {
|
||||
RequestConditionHolder empty = new RequestConditionHolder(null);
|
||||
RequestConditionHolder notEmpty = new RequestConditionHolder(new ParamsRequestCondition("name"));
|
||||
|
||||
assertSame(empty, empty.combine(new RequestConditionHolder(null)));
|
||||
assertSame(notEmpty, notEmpty.combine(empty));
|
||||
assertSame(notEmpty, empty.combine(notEmpty));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combine() {
|
||||
RequestConditionHolder params1 = new RequestConditionHolder(new ParamsRequestCondition("name1"));
|
||||
|
|
@ -53,6 +42,16 @@ public class RequestConditionHolderTests {
|
|||
assertEquals(expected, params1.combine(params2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineEmpty() {
|
||||
RequestConditionHolder empty = new RequestConditionHolder(null);
|
||||
RequestConditionHolder notEmpty = new RequestConditionHolder(new ParamsRequestCondition("name"));
|
||||
|
||||
assertSame(empty, empty.combine(empty));
|
||||
assertSame(notEmpty, notEmpty.combine(empty));
|
||||
assertSame(notEmpty, empty.combine(notEmpty));
|
||||
}
|
||||
|
||||
@Test(expected=ClassCastException.class)
|
||||
public void combineIncompatible() {
|
||||
RequestConditionHolder params = new RequestConditionHolder(new ParamsRequestCondition("name"));
|
||||
|
|
|
|||
|
|
@ -6,24 +6,25 @@ http://www.springsource.org
|
|||
Changes in version 3.2 M1
|
||||
-------------------------------------
|
||||
|
||||
* add Servlet 3.0 based async support
|
||||
* upgraded to AspectJ 1.6.12, JUnit 4.10, TestNG 6.5.2
|
||||
* add HttpMessageConverter and View types compatible with Jackson 2.0
|
||||
* better handling on failure to parse invalid 'Content-Type' or 'Accept' headers
|
||||
* handle a controller method's return value based on the actual returned value (vs declared type)
|
||||
* fix issue with combining identical controller and method level request mapping paths
|
||||
* fix concurrency issue in AnnotationMethodHandlerExceptionResolver
|
||||
* fix case-sensitivity issue with some containers on access to 'Content-Disposition' header
|
||||
* add Servlet 3.0 based async support
|
||||
* fix issue with encoded params in UriComponentsBuilder
|
||||
* add HttpMessageConverter and View types compatible with Jackson 2.0
|
||||
* add pretty print option to Jackson HttpMessageConverter and View types
|
||||
* fix issue with resolving Errors controller method argument
|
||||
* detect controller methods via InitializingBean in RequestMappingHandlerMapping
|
||||
* translate IOException from Jackson to HttpMessageNotReadableException
|
||||
* fix issue with resolving Errors controller method argument
|
||||
* implement InitializingBean in RequestMappingHandlerMapping to detect controller methods
|
||||
* fix content negotiation issue when sorting selected media types by quality value
|
||||
* Prevent further writing to the response when @ResponseStatus contains a reason
|
||||
* Deprecate HttpStatus codes 419, 420, 421
|
||||
* prevent further writing to the response when @ResponseStatus contains a reason
|
||||
* deprecate HttpStatus codes 419, 420, 421
|
||||
* support access to all URI vars via @PathVariable Map<String, String>
|
||||
* add "excludedExceptions" property to SimpleUrlHandlerMapping
|
||||
* add CompositeRequestCondition for use with multiple custom request mapping conditions
|
||||
|
||||
Changes in version 3.1.1 (2012-02-16)
|
||||
-------------------------------------
|
||||
|
|
|
|||
Loading…
Reference in New Issue