SPR-8487 Ensure setters for argument resolvers and return value handlers replace the defaults completely.
This commit is contained in:
parent
8504830da1
commit
78470782d4
|
|
@ -122,9 +122,9 @@ import org.springframework.web.util.WebUtils;
|
|||
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware,
|
||||
InitializingBean {
|
||||
|
||||
private List<HandlerMethodArgumentResolver> customArgumentResolvers;
|
||||
private List<? extends HandlerMethodArgumentResolver> customArgumentResolvers;
|
||||
|
||||
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
|
||||
private List<? extends HandlerMethodReturnValueHandler> customReturnValueHandlers;
|
||||
|
||||
private List<ModelAndViewResolver> modelAndViewResolvers;
|
||||
|
||||
|
|
@ -179,7 +179,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
|||
* <p>An existing {@link WebArgumentResolver} can either adapted with {@link ServletWebArgumentResolverAdapter}
|
||||
* or preferably converted to a {@link HandlerMethodArgumentResolver} instead.
|
||||
*/
|
||||
public void setCustomArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
public void setCustomArgumentResolvers(List<? extends HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
this.customArgumentResolvers = argumentResolvers;
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
|||
* {@link #setCustomArgumentResolvers(List)}, which does not override default registrations.
|
||||
* @param argumentResolvers argument resolvers for {@link RequestMapping} and {@link ModelAttribute} methods
|
||||
*/
|
||||
public void setArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
public void setArgumentResolvers(List<? extends HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
if (argumentResolvers != null) {
|
||||
this.argumentResolvers = new HandlerMethodArgumentResolverComposite();
|
||||
this.argumentResolvers.addResolvers(argumentResolvers);
|
||||
|
|
@ -202,7 +202,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
|||
* {@link #setCustomArgumentResolvers(List)}, which does not override default registrations.
|
||||
* @param argumentResolvers argument resolvers for {@link InitBinder} methods
|
||||
*/
|
||||
public void setInitBinderArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
public void setInitBinderArgumentResolvers(List<? extends HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
if (argumentResolvers != null) {
|
||||
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite();
|
||||
this.initBinderArgumentResolvers.addResolvers(argumentResolvers);
|
||||
|
|
@ -216,7 +216,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
|||
* and others. Those handlers can only be customized via {@link #setReturnValueHandlers(List)}.
|
||||
* @param returnValueHandlers custom return value handlers for {@link RequestMapping} methods
|
||||
*/
|
||||
public void setCustomReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
|
||||
public void setCustomReturnValueHandlers(List<? extends HandlerMethodReturnValueHandler> returnValueHandlers) {
|
||||
this.customReturnValueHandlers = returnValueHandlers;
|
||||
}
|
||||
|
||||
|
|
@ -226,7 +226,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
|||
* {@link #setCustomReturnValueHandlers(List)}, which does not override default registrations.
|
||||
* @param returnValueHandlers the return value handlers for {@link RequestMapping} methods
|
||||
*/
|
||||
public void setReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
|
||||
public void setReturnValueHandlers(List<? extends HandlerMethodReturnValueHandler> returnValueHandlers) {
|
||||
if (returnValueHandlers != null) {
|
||||
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite();
|
||||
this.returnValueHandlers.addHandlers(returnValueHandlers);
|
||||
|
|
@ -340,10 +340,12 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
|||
}
|
||||
|
||||
private void initArgumentResolvers() {
|
||||
if (argumentResolvers == null) {
|
||||
argumentResolvers = new HandlerMethodArgumentResolverComposite();
|
||||
if (argumentResolvers != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
argumentResolvers = new HandlerMethodArgumentResolverComposite();
|
||||
|
||||
// Annotation-based resolvers
|
||||
argumentResolvers.addResolver(new RequestParamMethodArgumentResolver(beanFactory, false));
|
||||
argumentResolvers.addResolver(new RequestParamMapMethodArgumentResolver());
|
||||
|
|
@ -371,10 +373,12 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
|||
}
|
||||
|
||||
private void initInitBinderArgumentResolvers() {
|
||||
if (initBinderArgumentResolvers == null) {
|
||||
initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite();
|
||||
if (initBinderArgumentResolvers != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite();
|
||||
|
||||
// Annotation-based resolvers
|
||||
initBinderArgumentResolvers.addResolver(new RequestParamMethodArgumentResolver(beanFactory, false));
|
||||
initBinderArgumentResolvers.addResolver(new RequestParamMapMethodArgumentResolver());
|
||||
|
|
@ -382,7 +386,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
|||
initBinderArgumentResolvers.addResolver(new ExpressionValueMethodArgumentResolver(beanFactory));
|
||||
|
||||
// Custom resolvers
|
||||
argumentResolvers.addResolvers(customArgumentResolvers);
|
||||
initBinderArgumentResolvers.addResolvers(customArgumentResolvers);
|
||||
|
||||
// Type-based resolvers
|
||||
initBinderArgumentResolvers.addResolver(new ServletRequestMethodArgumentResolver());
|
||||
|
|
@ -393,10 +397,12 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
|||
}
|
||||
|
||||
private void initReturnValueHandlers() {
|
||||
if (returnValueHandlers == null) {
|
||||
returnValueHandlers = new HandlerMethodReturnValueHandlerComposite();
|
||||
if (returnValueHandlers != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
returnValueHandlers = new HandlerMethodReturnValueHandlerComposite();
|
||||
|
||||
// Annotation-based handlers
|
||||
returnValueHandlers.addHandler(new RequestResponseBodyMethodProcessor(messageConverters));
|
||||
returnValueHandlers.addHandler(new ModelAttributeMethodProcessor(false));
|
||||
|
|
|
|||
|
|
@ -111,10 +111,10 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
|||
* @param handlerType the handler type
|
||||
* @return a {@link RequestMappingInfo} instance; never {@code null}
|
||||
*/
|
||||
RequestMappingInfo createRequestMappingInfo(RequestMapping annot,
|
||||
boolean isMethodAnnotation,
|
||||
Method method,
|
||||
Class<?> handlerType) {
|
||||
protected RequestMappingInfo createRequestMappingInfo(RequestMapping annot,
|
||||
boolean isMethodAnnotation,
|
||||
Method method,
|
||||
Class<?> handlerType) {
|
||||
return new RequestMappingInfo(
|
||||
new PatternsRequestCondition(annot.value(), getUrlPathHelper(), getPathMatcher(), useSuffixPatternMatch),
|
||||
new RequestMethodsRequestCondition(annot.method()),
|
||||
|
|
|
|||
|
|
@ -20,15 +20,29 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.method.annotation.support.ModelMethodProcessor;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
|
||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
|
||||
import org.springframework.web.method.support.InvocableHandlerMethod;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.support.ServletRequestMethodArgumentResolver;
|
||||
|
||||
/**
|
||||
* Fine-grained {@link RequestMappingHandlerAdapter} unit tests.
|
||||
|
|
@ -36,8 +50,8 @@ import org.springframework.web.method.support.InvocableHandlerMethod;
|
|||
* <p>For higher-level adapter tests see:
|
||||
* <ul>
|
||||
* <li>{@link ServletHandlerMethodTests}
|
||||
* <li>{@link HandlerMethodAnnotationDetectionTests}
|
||||
* <li>{@link RequestMappingHandlerAdapterIntegrationTests}
|
||||
* <li>{@link HandlerMethodAdapterAnnotationDetectionTests}
|
||||
* </ul>
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
|
|
@ -54,7 +68,6 @@ public class RequestMappingHandlerAdapterTests {
|
|||
public void setup() throws Exception {
|
||||
this.handlerAdapter = new RequestMappingHandlerAdapter();
|
||||
this.handlerAdapter.setApplicationContext(new GenericWebApplicationContext());
|
||||
this.handlerAdapter.afterPropertiesSet();
|
||||
|
||||
this.request = new MockHttpServletRequest();
|
||||
this.response = new MockHttpServletResponse();
|
||||
|
|
@ -62,6 +75,7 @@ public class RequestMappingHandlerAdapterTests {
|
|||
|
||||
@Test
|
||||
public void cacheControlWithoutSessionAttributes() throws Exception {
|
||||
handlerAdapter.afterPropertiesSet();
|
||||
handlerAdapter.setCacheSeconds(100);
|
||||
handlerAdapter.handle(request, response, handlerMethod(new SimpleHandler(), "handle"));
|
||||
|
||||
|
|
@ -70,17 +84,131 @@ public class RequestMappingHandlerAdapterTests {
|
|||
|
||||
@Test
|
||||
public void cacheControlWithSessionAttributes() throws Exception {
|
||||
handlerAdapter.afterPropertiesSet();
|
||||
handlerAdapter.setCacheSeconds(100);
|
||||
handlerAdapter.handle(request, response, handlerMethod(new SessionAttributeHandler(), "handle"));
|
||||
|
||||
assertEquals("no-cache", response.getHeader("Cache-Control"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setArgumentResolvers() {
|
||||
List<HandlerMethodArgumentResolver> expected = new ArrayList<HandlerMethodArgumentResolver>();
|
||||
expected.add(new ServletRequestMethodArgumentResolver());
|
||||
handlerAdapter.setArgumentResolvers(expected);
|
||||
handlerAdapter.afterPropertiesSet();
|
||||
|
||||
HandlerMethodArgumentResolverComposite composite = (HandlerMethodArgumentResolverComposite)
|
||||
new DirectFieldAccessor(handlerAdapter).getPropertyValue("argumentResolvers");
|
||||
|
||||
List<HandlerMethodArgumentResolver> actual = (List<HandlerMethodArgumentResolver>)
|
||||
new DirectFieldAccessor(composite).getPropertyValue("argumentResolvers");
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setInitBinderArgumentResolvers() {
|
||||
List<HandlerMethodArgumentResolver> expected = new ArrayList<HandlerMethodArgumentResolver>();
|
||||
expected.add(new ServletRequestMethodArgumentResolver());
|
||||
handlerAdapter.setInitBinderArgumentResolvers(expected);
|
||||
handlerAdapter.afterPropertiesSet();
|
||||
|
||||
HandlerMethodArgumentResolverComposite composite = (HandlerMethodArgumentResolverComposite)
|
||||
new DirectFieldAccessor(handlerAdapter).getPropertyValue("initBinderArgumentResolvers");
|
||||
|
||||
List<HandlerMethodArgumentResolver> actual = (List<HandlerMethodArgumentResolver>)
|
||||
new DirectFieldAccessor(composite).getPropertyValue("argumentResolvers");
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setReturnValueHandlers() {
|
||||
List<HandlerMethodReturnValueHandler> expected = new ArrayList<HandlerMethodReturnValueHandler>();
|
||||
expected.add(new ModelMethodProcessor());
|
||||
handlerAdapter.setReturnValueHandlers(expected);
|
||||
handlerAdapter.afterPropertiesSet();
|
||||
|
||||
HandlerMethodReturnValueHandlerComposite composite = (HandlerMethodReturnValueHandlerComposite)
|
||||
new DirectFieldAccessor(handlerAdapter).getPropertyValue("returnValueHandlers");
|
||||
|
||||
List<HandlerMethodReturnValueHandler> actual = (List<HandlerMethodReturnValueHandler>)
|
||||
new DirectFieldAccessor(composite).getPropertyValue("returnValueHandlers");
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setCustomArgumentResolvers() {
|
||||
TestHanderMethodArgumentResolver resolver = new TestHanderMethodArgumentResolver();
|
||||
handlerAdapter.setCustomArgumentResolvers(Arrays.asList(resolver));
|
||||
handlerAdapter.afterPropertiesSet();
|
||||
|
||||
HandlerMethodArgumentResolverComposite composite = (HandlerMethodArgumentResolverComposite)
|
||||
new DirectFieldAccessor(handlerAdapter).getPropertyValue("argumentResolvers");
|
||||
|
||||
List<HandlerMethodArgumentResolver> actual = (List<HandlerMethodArgumentResolver>)
|
||||
new DirectFieldAccessor(composite).getPropertyValue("argumentResolvers");
|
||||
|
||||
assertTrue(actual.contains(resolver));
|
||||
|
||||
composite = (HandlerMethodArgumentResolverComposite)
|
||||
new DirectFieldAccessor(handlerAdapter).getPropertyValue("initBinderArgumentResolvers");
|
||||
|
||||
actual = (List<HandlerMethodArgumentResolver>)
|
||||
new DirectFieldAccessor(composite).getPropertyValue("argumentResolvers");
|
||||
|
||||
assertTrue(actual.contains(resolver));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setCustomReturnValueHandlers() {
|
||||
TestHandlerMethodReturnValueHandler handler = new TestHandlerMethodReturnValueHandler();
|
||||
handlerAdapter.setCustomReturnValueHandlers(Arrays.asList(handler));
|
||||
handlerAdapter.afterPropertiesSet();
|
||||
|
||||
HandlerMethodReturnValueHandlerComposite composite = (HandlerMethodReturnValueHandlerComposite)
|
||||
new DirectFieldAccessor(handlerAdapter).getPropertyValue("returnValueHandlers");
|
||||
|
||||
List<HandlerMethodReturnValueHandler> actual = (List<HandlerMethodReturnValueHandler>)
|
||||
new DirectFieldAccessor(composite).getPropertyValue("returnValueHandlers");
|
||||
|
||||
assertTrue(actual.contains(handler));
|
||||
}
|
||||
|
||||
private HandlerMethod handlerMethod(Object handler, String methodName, Class<?>... paramTypes) throws Exception {
|
||||
Method method = handler.getClass().getDeclaredMethod(methodName, paramTypes);
|
||||
return new InvocableHandlerMethod(handler, method);
|
||||
}
|
||||
|
||||
private final class TestHanderMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final class TestHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler{
|
||||
|
||||
public boolean supportsReturnType(MethodParameter returnType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void handleReturnValue(Object returnValue, MethodParameter returnType,
|
||||
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
|
||||
}
|
||||
}
|
||||
|
||||
private static class SimpleHandler {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu
|
|||
/**
|
||||
* Add the given {@link HandlerMethodArgumentResolver}s.
|
||||
*/
|
||||
public void addResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
public void addResolvers(List<? extends HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
if (argumentResolvers != null) {
|
||||
for (HandlerMethodArgumentResolver resolver : argumentResolvers) {
|
||||
this.argumentResolvers.add(resolver);
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodRe
|
|||
/**
|
||||
* Add the given {@link HandlerMethodReturnValueHandler}s.
|
||||
*/
|
||||
public void addHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
|
||||
public void addHandlers(List<? extends HandlerMethodReturnValueHandler> returnValueHandlers) {
|
||||
if (returnValueHandlers != null) {
|
||||
for (HandlerMethodReturnValueHandler handler : returnValueHandlers) {
|
||||
this.returnValueHandlers.add(handler);
|
||||
|
|
|
|||
Loading…
Reference in New Issue