Expose return-value-handlers in mvc namespace

Mirroring the MvcConfigurer#addCustomReturnValueHandlers callback which
allows for providing a list of HandlerMethodReturnValueHandler types

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@4271 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
Chris Beams 2011-05-06 19:13:44 +00:00
parent 9e0b7303b4
commit fc3ccd1052
4 changed files with 84 additions and 10 deletions

View File

@ -124,6 +124,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
ManagedList<?> messageConverters = getMessageConverters(element, source, parserContext);
ManagedList<?> argumentResolvers = getArgumentResolvers(element, source, parserContext);
ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, source, parserContext);
RootBeanDefinition methodAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
methodAdapterDef.setSource(source);
@ -133,6 +134,9 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
if (argumentResolvers != null) {
methodAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
}
if (returnValueHandlers != null) {
methodAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
}
String methodAdapterName = parserContext.getReaderContext().registerWithGeneratedName(methodAdapterDef);
RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
@ -228,6 +232,14 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
return null;
}
private ManagedList<?> getReturnValueHandlers(Element element, Object source, ParserContext parserContext) {
Element handlersElement = DomUtils.getChildElementByTagName(element, "return-value-handlers");
if (handlersElement != null) {
return extractBeanSubElements(handlersElement, parserContext);
}
return null;
}
private ManagedList<?> getMessageConverters(Element element, Object source, ParserContext parserContext) {
Element convertersElement = DomUtils.getChildElementByTagName(element, "message-converters");
ManagedList<? super Object> messageConverters = new ManagedList<Object>();

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://www.springframework.org/schema/mvc"
@ -40,19 +40,19 @@
<xsd:attribute name="register-defaults" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Whether or not default HttpMessageConverter registrations should be added in addition to the ones provided within this element.
Whether or not default HttpMessageConverter registrations should be added in addition to the ones provided within this element.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:element>
<xsd:element name="argument-resolvers" minOccurs="0">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configures one or more WebArgumentResolver types to use for resolving custom arguments to handler methods.
Typically implemented to detect special parameter types, resolving well-known argument values for them.
Using this configuration element is optional.
Using it does not override the built-in support for resolving handler method arguments.
Using it does not override the built-in support for resolving handler method arguments.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
@ -60,7 +60,27 @@
<xsd:element ref="beans:bean" minOccurs="1" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
The HttpMessageConverter bean definition.
The HandlerMethodArgumentResolver or WebArgumentResolver bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="return-value-handlers" minOccurs="0">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configures one or more HandlerMethodReturnValueHandler types to use for handling the return value from handler methods.
Using this configuration element is optional.
Using it does not override the built-in support for handling return values.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="beans:bean" minOccurs="1" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
The HandlerMethodReturnValueHandler bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
@ -101,7 +121,7 @@
<xsd:annotation>
<xsd:documentation><![CDATA[
The bean name of a MessageCodesResolver to use to build message codes from data binding and validation error codes.
This attribute is not required.
This attribute is not required.
If not specified the DefaultMessageCodesResolver is used.
]]></xsd:documentation>
<xsd:appinfo>
@ -171,10 +191,10 @@
Configures a handler for serving static resources by forwarding to the Servlet container's default Servlet. Use of this
handler allows using a "/" mapping with the DispatcherServlet while still utilizing the Servlet container to serve static
resources.
This handler will forward all requests to the default Servlet. Therefore it is important that it remains last in the
order of all other URL HandlerMappings. That will be the case if you use the "annotation-driven" element or alternatively
if you are setting up your customized HandlerMapping instance be sure to set its "order" property to a value lower than
that of the DefaultServletHttpRequestHandler, which is Integer.MAX_VALUE.
This handler will forward all requests to the default Servlet. Therefore it is important that it remains last in the
order of all other URL HandlerMappings. That will be the case if you use the "annotation-driven" element or alternatively
if you are setting up your customized HandlerMapping instance be sure to set its "order" property to a value lower than
that of the DefaultServletHttpRequestHandler, which is Integer.MAX_VALUE.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>

View File

@ -37,6 +37,7 @@ 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.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
@ -96,6 +97,20 @@ public class AnnotationDrivenBeanDefinitionParserTests {
assertTrue(resolvers.get(1) instanceof TestHandlerMethodArgumentResolver);
}
@SuppressWarnings("unchecked")
@Test
public void testReturnValueHandlers() {
loadBeanDefinitions("mvc-config-return-value-handlers.xml");
RequestMappingHandlerAdapter adapter = appContext.getBean(RequestMappingHandlerAdapter.class);
assertNotNull(adapter);
Object value = new DirectFieldAccessor(adapter).getPropertyValue("customReturnValueHandlers");
assertNotNull(value);
assertTrue(value instanceof List);
List<HandlerMethodReturnValueHandler> handlers = (List<HandlerMethodReturnValueHandler>) value;
assertEquals(1, handlers.size());
assertEquals(TestHandlerMethodReturnValueHandler.class, handlers.get(0).getClass());
}
private void loadBeanDefinitions(String fileName) {
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(appContext);
reader.loadBeanDefinitions(new ClassPathResource(fileName,
@ -141,6 +156,19 @@ class TestHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver
}
}
class TestHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
public boolean supportsReturnType(MethodParameter returnType) {
return false;
}
public void handleReturnValue(Object returnValue,
MethodParameter returnType, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception {
}
}
class TestMessageCodesResolver implements MessageCodesResolver {
public String[] resolveMessageCodes(String errorCode, String objectName) {

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<mvc:annotation-driven>
<mvc:return-value-handlers>
<bean class="org.springframework.web.servlet.config.TestHandlerMethodReturnValueHandler"/>
</mvc:return-value-handlers>
</mvc:annotation-driven>
</beans>