Update documentation with regards to differences between @MVC 3.0/3.1

Although the reference documentation listed the new @MVC support
classes and their benefits, it did not explicitly mention a few
use cases that are no longer supported. There is now a specific
section on the new support classes listing exactly what is not
supported.

Similary the @RequestMapping annotation never refered explicitly
to the existence of old and new support and never made it clear
exactly what the differences are.

Both have not been corrected.

SPR-9063, SPR-9042
This commit is contained in:
Rossen Stoyanchev 2012-02-07 19:49:44 -05:00
parent bf541db5b0
commit 4f4a2e7fc7
4 changed files with 157 additions and 70 deletions

View File

@ -38,7 +38,7 @@ Changes in version 3.1.1 (2012-02-13)
* added property to RedirectView to disable expanding URI variables in redirect URL * added property to RedirectView to disable expanding URI variables in redirect URL
* fixed request mapping bug involving direct vs pattern path matches with HTTP methods * fixed request mapping bug involving direct vs pattern path matches with HTTP methods
* removed check for HTTP "POST" when resolving multipart request controller method arguments * removed check for HTTP "POST" when resolving multipart request controller method arguments
* update @RequestMapping and reference docs wrt differences between @MVC 3.1 and @MVC 2.5-3.0
Changes in version 3.1 GA (2011-12-12) Changes in version 3.1 GA (2011-12-12)
-------------------------------------- --------------------------------------

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,17 +24,18 @@ import java.lang.annotation.Target;
/** /**
* Annotation for mapping web requests onto specific handler classes and/or * Annotation for mapping web requests onto specific handler classes and/or
* handler methods. Provides consistent style between Servlet and Portlet * handler methods. Provides a consistent style between Servlet and Portlet
* environments, with the semantics adapting to the concrete environment. * environments, with the semantics adapting to the concrete environment.
* *
* <p><b>NOTE:</b> Method-level mappings are only allowed to narrow the mapping * <p><b>NOTE:</b> The set of features supported for Servlets is a superset
* expressed at the class level (if any). In the Servlet case, an HTTP path needs to * of the set of features supported for Portlets. The places where this applies
* uniquely map onto one specific handler bean (not spread across multiple handler beans); * are marked with the label "Servlet-only" in this source file. For Servlet
* the remaining mapping parameters and conditions are effectively assertions only. * environments there are some further distinctions depending on whether an
* In the Portlet case, a portlet mode in combination with specific parameter conditions * application is configured with {@literal "@MVC 3.0"} or
* needs to uniquely map onto one specific handler bean, with all conditions evaluated * {@literal "@MVC 3.1"} support classes. The places where this applies are
* for mapping purposes. It is strongly recommended to co-locate related handler methods * marked with {@literal "@MVC 3.1-only"} in this source file. For more
* into the same bean and therefore keep the mappings simple and intuitive. * details see the note on the new support classes added in Spring MVC 3.1
* further below.
* *
* <p>Handler methods which are annotated with this annotation are allowed * <p>Handler methods which are annotated with this annotation are allowed
* to have very flexible signatures. They may have arguments of the following * to have very flexible signatures. They may have arguments of the following
@ -71,8 +72,8 @@ import java.lang.annotation.Target;
* <li>{@link java.io.OutputStream} / {@link java.io.Writer} for generating * <li>{@link java.io.OutputStream} / {@link java.io.Writer} for generating
* the response's content. This will be the raw OutputStream/Writer as * the response's content. This will be the raw OutputStream/Writer as
* exposed by the Servlet/Portlet API. * exposed by the Servlet/Portlet API.
* <li>{@link PathVariable @PathVariable} annotated parameters for access to * <li>{@link PathVariable @PathVariable} annotated parameters (Servlet-only)
* URI template values (i.e. /hotels/{hotel}). Variable values will be * for access to URI template values (i.e. /hotels/{hotel}). Variable values will be
* converted to the declared method argument type. By default, the URI template * converted to the declared method argument type. By default, the URI template
* will match against the regular expression {@code [^\.]*} (i.e. any character * will match against the regular expression {@code [^\.]*} (i.e. any character
* other than period), but this can be changed by specifying another regular * other than period), but this can be changed by specifying another regular
@ -90,30 +91,43 @@ import java.lang.annotation.Target;
* {@link org.springframework.util.MultiValueMap MultiValueMap&lt;String, String&gt;}, or * {@link org.springframework.util.MultiValueMap MultiValueMap&lt;String, String&gt;}, or
* {@link org.springframework.http.HttpHeaders HttpHeaders} method parameter to * {@link org.springframework.http.HttpHeaders HttpHeaders} method parameter to
* gain access to all request headers. * gain access to all request headers.
* <li>{@link RequestBody @RequestBody} annotated parameters for access to * <li>{@link RequestBody @RequestBody} annotated parameters (Servlet-only)
* the Servlet request HTTP contents. The request stream will be * for access to the Servlet request HTTP contents. The request stream will be
* converted to the declared method argument type using * converted to the declared method argument type using
* {@linkplain org.springframework.http.converter.HttpMessageConverter message * {@linkplain org.springframework.http.converter.HttpMessageConverter message
* converters}. Such parameters may optionally be annotated with {@code @Valid}. * converters}. Such parameters may optionally be annotated with {@code @Valid}
* <li>{@link RequestPart @RequestPart} annotated parameters for access to the content * but do not support access to validation results through a
* {@link org.springframework.validation.Errors} /
* {@link org.springframework.validation.BindingResult} argument.
* Instead a {@link org.springframework.web.servlet.mvc.method.annotation.MethodArgumentNotValidException}
* exception is raised.
* <li>{@link RequestPart @RequestPart} annotated parameters
* (Servlet-only, {@literal @MVC 3.1-only})
* for access to the content
* of a part of "multipart/form-data" request. The request part stream will be * of a part of "multipart/form-data" request. The request part stream will be
* converted to the declared method argument type using * converted to the declared method argument type using
* {@linkplain org.springframework.http.converter.HttpMessageConverter message * {@linkplain org.springframework.http.converter.HttpMessageConverter message
* converters}. Such parameters may optionally be annotated with {@code @Valid}. * converters}. Such parameters may optionally be annotated with {@code @Valid}
* but do not support access to validation results through a
* {@link org.springframework.validation.Errors} /
* {@link org.springframework.validation.BindingResult} argument.
* Instead a {@link org.springframework.web.servlet.mvc.method.annotation.MethodArgumentNotValidException}
* exception is raised.
* <li>{@link org.springframework.http.HttpEntity HttpEntity&lt;?&gt;} parameters * <li>{@link org.springframework.http.HttpEntity HttpEntity&lt;?&gt;} parameters
* for access to the Servlet request HTTP headers and contents. The request stream will be * (Servlet-only) for access to the Servlet request HTTP headers and contents.
* converted to the entity body using * The request stream will be converted to the entity body using
* {@linkplain org.springframework.http.converter.HttpMessageConverter message * {@linkplain org.springframework.http.converter.HttpMessageConverter message
* converters}. * converters}.
* <li>{@link java.util.Map} / {@link org.springframework.ui.Model} / * <li>{@link java.util.Map} / {@link org.springframework.ui.Model} /
* {@link org.springframework.ui.ModelMap} for enriching the implicit model * {@link org.springframework.ui.ModelMap} for enriching the implicit model
* that will be exposed to the web view. * that will be exposed to the web view.
* <li>{@link org.springframework.web.servlet.mvc.support.RedirectAttributes} * <li>{@link org.springframework.web.servlet.mvc.support.RedirectAttributes}
* to specify the exact set of attributes to use in case of a redirect * (Servlet-only, {@literal @MVC 3.1-only}) to specify the exact set of attributes
* and also to add flash attributes (attributes stored temporarily on the * to use in case of a redirect and also to add flash attributes (attributes
* server-side to make them available to the request after the redirect). * stored temporarily on the server-side to make them available to the request
* {@code RedirectAttributes} is used instead of the implicit model if the * after the redirect). {@code RedirectAttributes} is used instead of the
* method returns a "redirect:" prefixed view name or {@code RedirectView}. * implicit model if the method returns a "redirect:" prefixed view name or
* {@code RedirectView}.
* <li>Command/form objects to bind parameters to: as bean properties or fields, * <li>Command/form objects to bind parameters to: as bean properties or fields,
* with customizable type conversion, depending on {@link InitBinder} methods * with customizable type conversion, depending on {@link InitBinder} methods
* and/or the HandlerAdapter configuration - see the "webBindingInitializer" * and/or the HandlerAdapter configuration - see the "webBindingInitializer"
@ -130,9 +144,10 @@ import java.lang.annotation.Target;
* for marking form processing as complete (triggering the cleanup of session * for marking form processing as complete (triggering the cleanup of session
* attributes that have been indicated by the {@link SessionAttributes} annotation * attributes that have been indicated by the {@link SessionAttributes} annotation
* at the handler type level). * at the handler type level).
* <li>{@link org.springframework.web.util.UriComponentsBuilder} a builder for * <li>{@link org.springframework.web.util.UriComponentsBuilder}
* preparing a URL relative to the current request's host, port, scheme, context * (Servlet-only, {@literal @MVC 3.1-only})
* path, and the literal part of the servlet mapping. * for preparing a URL relative to the current request's host, port, scheme,
* context path, and the literal part of the servlet mapping.
* </ul> * </ul>
* *
* <p>The following return types are supported for handler methods: * <p>The following return types are supported for handler methods:
@ -160,15 +175,15 @@ import java.lang.annotation.Target;
* The handler method may also programmatically enrich the model by * The handler method may also programmatically enrich the model by
* declaring a {@link org.springframework.ui.ModelMap} argument * declaring a {@link org.springframework.ui.ModelMap} argument
* (see above). * (see above).
* <li>{@link ResponseBody @ResponseBody} annotated methods for access to * <li>{@link ResponseBody @ResponseBody} annotated methods (Servlet-only)
* the Servlet response HTTP contents. The return value will be converted * for access to the Servlet response HTTP contents. The return value will
* to the response stream using * be converted to the response stream using
* {@linkplain org.springframework.http.converter.HttpMessageConverter message * {@linkplain org.springframework.http.converter.HttpMessageConverter message
* converters}. * converters}.
* <li>A {@link org.springframework.http.HttpEntity HttpEntity&lt;?&gt;} or * <li>A {@link org.springframework.http.HttpEntity HttpEntity&lt;?&gt;} or
* {@link org.springframework.http.ResponseEntity ResponseEntity&lt;?&gt;} object * {@link org.springframework.http.ResponseEntity ResponseEntity&lt;?&gt;} object
* to access to the Servlet response HTTP headers and contents. The entity body will * (Servlet-only) to access to the Servlet response HTTP headers and contents.
* be converted to the response stream using * The entity body will be converted to the response stream using
* {@linkplain org.springframework.http.converter.HttpMessageConverter message * {@linkplain org.springframework.http.converter.HttpMessageConverter message
* converters}. * converters}.
* <li><code>void</code> if the method handles the response itself (by * <li><code>void</code> if the method handles the response itself (by
@ -187,16 +202,24 @@ import java.lang.annotation.Target;
* {@link ModelAttribute} annotated reference data accessor methods. * {@link ModelAttribute} annotated reference data accessor methods.
* </ul> * </ul>
* *
* <p><b>NOTE: <code>@RequestMapping</code> will only be processed if a * <p><b>NOTE:</b> <code>@RequestMapping</code> will only be processed if an
* corresponding <code>HandlerMapping</code> (for type level annotations) * an appropriate <code>HandlerMapping</code>-<code>HandlerAdapter</code> pair
* and/or <code>HandlerAdapter</code> (for method level annotations) is * is configured. This is the case by default in both the
* present in the dispatcher.</b> This is the case by default in both * <code>DispatcherServlet</code> and the <code>DispatcherPortlet</code>.
* <code>DispatcherServlet</code> and <code>DispatcherPortlet</code>.
* However, if you are defining custom <code>HandlerMappings</code> or * However, if you are defining custom <code>HandlerMappings</code> or
* <code>HandlerAdapters</code>, then you need to make sure that a * <code>HandlerAdapters</code>, then you need to add
* corresponding custom <code>RequestMappingHandlerMethodMapping</code> * <code>DefaultAnnotationHandlerMapping</code> and
* and/or <code>RequestMappingHandlerMethodAdapter</code> is defined as well * <code>AnnotationMethodHandlerAdapter</code> to your configuration.</code>.
* - provided that you intend to use <code>@RequestMapping</code>. *
* <p><b>NOTE:</b> Spring 3.1 introduced a new set of support classes for
* <code>@RequestMapping</code> methods in Servlet environments called
* <code>RequestMappingHandlerMapping</code> and
* <code>RequestMappingHandlerAdapter</code>. They are recommended for use and
* even required to take advantage of new features in Spring MVC 3.1 (search
* {@literal "@MVC 3.1-only"} in this source file) and going forward.
* The new support classes are enabled by default from the MVC namespace and
* with use of the MVC Java config (<code>@EnableWebMvc</code>) but must be
* configured explicitly if using neither.
* *
* <p><b>NOTE:</b> When using controller interfaces (e.g. for AOP proxying), * <p><b>NOTE:</b> When using controller interfaces (e.g. for AOP proxying),
* make sure to consistently put <i>all</i> your mapping annotations - such as * make sure to consistently put <i>all</i> your mapping annotations - such as
@ -234,20 +257,6 @@ public @interface RequestMapping {
* <p><b>Supported at the type level as well as at the method level!</b> * <p><b>Supported at the type level as well as at the method level!</b>
* When used at the type level, all method-level mappings inherit * When used at the type level, all method-level mappings inherit
* this primary mapping, narrowing it for a specific handler method. * this primary mapping, narrowing it for a specific handler method.
* <p>In case of Servlet-based handler methods, the method names are
* taken into account for narrowing if no path was specified explicitly,
* according to the specified
* {@link org.springframework.web.servlet.mvc.multiaction.MethodNameResolver}
* (by default an
* {@link org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver}).
* Note that this only applies in case of ambiguous annotation mappings
* that do not specify a path mapping explicitly. In other words,
* the method name is only used for narrowing among a set of matching
* methods; it does not constitute a primary path mapping itself.
* <p>If you have a single default method (without explicit path mapping),
* then all requests without a more specific mapped method found will
* be dispatched to it. If you have multiple such default methods, then
* the method name will be taken into account for choosing between them.
*/ */
String[] value() default {}; String[] value() default {};

View File

@ -857,6 +857,69 @@ public class ClinicController {
mechanisms see <xref linkend="aop-proxying" />.</para> mechanisms see <xref linkend="aop-proxying" />.</para>
</tip> </tip>
<section id="mvc-ann-requestmapping-31-vs-30">
<title>New Support Classes for <classname>@RequestMapping</classname> methods in Spring MVC 3.1</title>
<para>Spring 3.1 introduced a new set of support classes for
<classname>@RequestMapping</classname> methods called
<classname>RequestMappingHandlerMapping</classname> and
<classname>RequestMappingHandlerAdapter</classname> respectively.
They are recommended for use and even required to take advantage of
new features in Spring MVC 3.1 and going forward. The new support
classes are enabled by default by the MVC namespace and MVC Java
config (<classname>@EnableWebMvc</classname>) but must be configured
explicitly if using neither. This section describes a few
important differences between the old and the new support classes.
</para>
<para>Prior to Spring 3.1, type and method-level request mappings were
examined in two separate stages -- a controller was selected first
by the <classname>DefaultAnnotationHandlerMapping</classname> and the
actual method to invoke was narrowed down second by
the <classname>AnnotationMethodHandlerAdapter</classname>.</para>
<para>With the new support classes in Spring 3.1, the
<classname>RequestMappingHandlerMapping</classname> is the only place
where a decision is made about which method should process the request.
Think of controller methods as a collection of unique endpoints
with mappings for each method derived from type and method-level
<classname>@RequestMapping</classname> information.</para>
<para>This enables some new possibilities. For once a
<classname>HandlerInterceptor</classname> or a
<classname>HandlerExceptionResolver</classname> can now expect the
Object-based handler to be a <classname>HandlerMethod</classname>,
which allows them to examine the exact method, its parameters and
associated annotations. The processing for a URL no longer needs to
be split across different controllers.
</para>
<para>There are also several things no longer possible:</para>
<itemizedlist>
<listitem><para>Select a controller first with a
<classname>SimpleUrlHandlerMapping</classname> or
<classname>BeanNameUrlHandlerMapping</classname> and then narrow
the method based on <classname>@RequestMapping</classname>
annotations.</para></listitem>
<listitem><para>Rely on method names as a fall-back mechanism to
disambiguate between two <classname>@RequestMapping</classname> methods
that don't have an explicit path mapping URL path but otherwise
match equally, e.g. by HTTP method. In the new support classes
<classname>@RequestMapping</classname> methods have to be mapped
uniquely.</para></listitem>
<listitem><para>Have a single default method (without an explicit
path mapping) with which requests are processed if no other
controller method matches more concretely. In the new support
classes if a matching method is not found a 404 error
is raised.</para></listitem>
</itemizedlist>
<para>The above features are still supported with the existing support
classes. However to take advantage of new Spring MVC 3.1 features
you'll need to use the new support classes.</para>
</section>
<section id="mvc-ann-requestmapping-uri-templates"> <section id="mvc-ann-requestmapping-uri-templates">
<title>URI Template Patterns</title> <title>URI Template Patterns</title>
@ -1104,6 +1167,17 @@ public class RelativePathUriTemplateController {
<classname>BindingResult</classname> arguments. This is described in the <classname>BindingResult</classname> arguments. This is described in the
next section.</para> next section.</para>
<note><para>Spring 3.1 introduced a new set of support classes for
<classname>@RequestMapping</classname> methods called
<classname>RequestMappingHandlerMapping</classname> and
<classname>RequestMappingHandlerAdapter</classname> respectively.
They are recommended for use and even required to take advantage
of new features in Spring MVC 3.1 and going forward.
The new support classes are enabled by default from the MVC namespace and
with use of the MVC Java config (<code>@EnableWebMvc</code>) but must be
configured explicitly if using neither.
</para></note>
<section id="mvc-ann-arguments"> <section id="mvc-ann-arguments">
<title>Supported method argument types</title> <title>Supported method argument types</title>

View File

@ -390,6 +390,10 @@
Java-based configuration via <interface>@EnableWebMvc</interface>. The Java-based configuration via <interface>@EnableWebMvc</interface>. The
existing classes will continue to be available but use of the new existing classes will continue to be available but use of the new
classes is recommended going forward.</para> classes is recommended going forward.</para>
<para>See <xref linkend="mvc-ann-requestmapping-31-vs-30"/> for additional
details and a list of features not available with the new support classes.</para>
</section> </section>
<section> <section>