Browse Source

SPR-7353 Doc update for consumes/produces + changelog update

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@4327 50f2f4bb-b051-0410-bef5-90022cba6387
pull/1/merge
Rossen Stoyanchev 15 years ago
parent
commit
6e86bc5bc2
  1. 10
      build-spring-framework/resources/changelog.txt
  2. 336
      spring-framework-reference/src/mvc.xml

10
build-spring-framework/resources/changelog.txt

@ -9,7 +9,15 @@ Changes in version 3.1 M2 (2011-??-??) @@ -9,7 +9,15 @@ Changes in version 3.1 M2 (2011-??-??)
* deprecated AbstractJUnit38SpringContextTests and AbstractTransactionalJUnit38SpringContextTests
* eliminated @Feature support in favor of @Enable* and framework-provided @Configuration classes
* introduced @EnableTransactionManagement, @EnableScheduling, and other @Enable* annotations
* introduced @EnableWebMvc to provide default configuration for Spring MVC applications
* introduced HandlerMethod abstraction representing a Spring MVC controller method
* added HandlerMapping/HandlerAdapter/HandlerExceptionResolver HandlerMethod-based implementations
* enabled HandlerMethod-based infrastructure through the mvc namespace and Java-based configuration
* support for automatically adding @PathVariables to the model
* support for including @PathVariables in data binding
* support for URI template variables in view names with the "redirect:" prefix
* a flag for extracting the value from single-key models in MappingJacksonJsonView
* allow bean references in mvc:interceptor namespace elements
Changes in version 3.1 M1 (2011-02-11)
--------------------------------------

336
spring-framework-reference/src/mvc.xml

@ -62,21 +62,20 @@ @@ -62,21 +62,20 @@
business objects.</para>
<para>Spring's view resolution is extremely flexible. A
<interfacename>Controller</interfacename> implementation can even write
directly to the response stream. Typically, a
<classname>ModelAndView</classname> instance consists of a view name and a
model <interfacename>Map</interfacename>, which contains bean names and
corresponding objects such as a command or form, which contain reference
data. View name resolution is highly configurable, through bean names, a
properties file, or your own <interfacename>ViewResolver</interfacename>
implementation. The model (the M in MVC) is based on the
<interfacename>Controller</interfacename> is typically responsible for preparing
a model <classname>Map</classname> with data and selecting a view name but it
can also write directly to the response stream and complete the request.
View name resolution is highly configurable through file extension or Accept header
content type negotiation, through bean names, a properties file,
or even a custom <interfacename>ViewResolver</interfacename>
implementation. The model (the M in MVC) is a
<interfacename>Map</interfacename> interface, which allows for the
complete abstraction of the view technology. You can integrate directly
JSP, Velocity, or any other rendering technology. The model
<interfacename>Map</interfacename> is simply transformed into an
appropriate format, such as JSP request attributes or a Velocity template
JSP, Velocity, or render content types such as XML, JSON, Atom, and others.
The model <interfacename>Map</interfacename> is simply transformed into an
appropriate format, such as JSP request attributes, a Velocity template
model.</para>
<section id="mvc-features">
<title>Features of Spring Web MVC<!--I moved Features of Spring Web MVC before Pluggability of other MVC implementations. You want to highlight your own imp. first.--></title>
@ -261,14 +260,14 @@ @@ -261,14 +260,14 @@
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;example&lt;/servlet-name&gt;
&lt;url-pattern&gt;*.form&lt;/url-pattern&gt;
&lt;url-pattern&gt;/example/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
&lt;/web-app&gt;</programlisting>
<para>In the preceding example, all requests ending with
<literal>.form</literal> will be handled by the <literal>example</literal>
<classname>DispatcherServlet</classname>. This is only the first step in
<para>In the preceding example, all requests startig with
<literal>/example</literal> will be handled by the <classname>DispatcherServlet</classname>
instance named <literal>example</literal>. This is only the first step in
setting up Spring Web MVC. <!--The discussion below is a little vague about what you're doing, when you do it, and what you're accomplishing. --><!-- Is the next step shown in the next example screen?-->You
now need to configure the various beans used by the Spring Web MVC
framework (over and above the <classname>DispatcherServlet</classname>
@ -590,9 +589,10 @@ @@ -590,9 +589,10 @@
<tip>
<para>Available in the <link linkend="new-in-3-samples">samples repository</link>,
the <emphasis>PetClinic</emphasis> web application leverages
the annotation support described in this section, in the context of
simple form processing.</para>
a number of web applications leverage the annotation support described in this section
including <emphasis>MvcShowcase</emphasis>, <emphasis>MvcAjax</emphasis>,
<emphasis>MvcBasic</emphasis>, <emphasis>PetClinic</emphasis>,
<emphasis>PetCare</emphasis>, and others.</para>
<!-- MLP Note removed reference to imagedb -->
</tip>
@ -680,8 +680,8 @@ public class HelloWorldController { @@ -680,8 +680,8 @@ public class HelloWorldController {
narrowing the primary mapping for a specific HTTP method request method
("GET", "POST", etc.) or an HTTP request parameter condition.</para>
<para>The following example shows a controller in a Spring MVC
application that uses this annotation:</para>
<para>The following example from the <emphasis>Petcare</emphasis> sample shows
a controller in a Spring MVC application that uses this annotation:</para>
<programlisting language="java">@Controller
<emphasis role="bold">@RequestMapping("/appointments")</emphasis>
@ -739,7 +739,7 @@ public class AppointmentsController { @@ -739,7 +739,7 @@ public class AppointmentsController {
<para>A <interfacename>@RequestMapping</interfacename> on the class
level is not required. Without it, all paths are simply absolute, and
not relative. The following example from the PetClinic sample
not relative. The following example from the <emphasis>PetClinic</emphasis> sample
application shows a multi-action controller using
<classname>@RequestMapping</classname>:</para>
@ -765,60 +765,43 @@ public class ClinicController { @@ -765,60 +765,43 @@ public class ClinicController {
}</programlisting>
<tip>
<title>Working with interface-based @Controller classes</title>
<para>A common pitfall when working with annotated controller classes
happens when applying functionality that requires creating a proxy
proxy for the controller object (e.g.
<interfacename>@Transactional</interfacename> methods). Usually you
will introduce an interface for the controller in order to use JDK
dynamic proxies. To make this work you must move the
<interfacename>@RequestMapping</interfacename> annotations to the
interface as as the mapping mechanism can only "see" the interface
exposed by the proxy. As an alternative, you may choose to activate
<code>proxy-target-class="true"</code> in the configuration for the
functionality applied to the controller (in our transaction scenario
in <code>&lt;tx:annotation-driven /&gt;</code>). Doing so indicates
that CGLIB-based subclass proxies should be used instead of
interface-based JDK proxies. For more information on various proxying
mechanisms see <xref linkend="aop-proxying"/>.</para>
</tip>
<title>Using <interfacename>@RequestMapping</interfacename> On Interface Methods</title>
<para>
A common pitfall when working with annotated controller classes
happens when applying functionality that requires creating a proxy
for the controller object (e.g.
<interfacename>@Transactional</interfacename> methods). Usually you
will introduce an interface for the controller in order to use JDK
dynamic proxies. To make this work you must move the
<interfacename>@RequestMapping</interfacename> annotations to the
interface as well as the mapping mechanism can only "see" the interface
exposed by the proxy. Alternatively, you could activate
<code>proxy-target-class="true"</code> in the configuration for the
functionality applied to the controller (in our transaction scenario
in <code>&lt;tx:annotation-driven /&gt;</code>). Doing so indicates
that CGLIB-based subclass proxies should be used instead of
interface-based JDK proxies. For more information on various proxying
mechanisms see <xref linkend="aop-proxying"/>.
</para>
</tip>
<section id="mvc-ann-requestmapping-uri-templates">
<title>URI Templates</title>
<para>To access parts of a request URL in your handling methods, use
the <emphasis><emphasis>URI templates</emphasis></emphasis> in the
<interfacename>@RequestMapping</interfacename> path value.</para>
<sidebar id="mvc-uri-templates">
<title>URI Templates</title>
<para>A URI Template is a URI-like string, containing one or more
variable names. When you substitute values for these variables, the
template becomes a URI. The <ulink
url="http://bitworking.org/projects/URI-Templates/">proposed
RFC</ulink> for URI Templates defines how a URI is parameterized.
For example, the URI Template</para>
<programlisting>http://www.example.com/users/{userid}</programlisting>
<para>contains the variable <emphasis>userid</emphasis>. If we
assign the variable the value fred, the URI Template yields:</para>
<programlisting>http://www.example.com/users/fred</programlisting>
<para>During the processing of a request, the URI can be compared to
an expected URI Template in order to extract a collection of
variables.</para>
</sidebar>
<para>Use the <interfacename>@PathVariable</interfacename> method
parameter annotation to indicate that a method parameter should be
bound to the value of a URI template variable.</para>
<para>The following code snippet shows the usage of a single
<interfacename>@PathVariable</interfacename> in a controller
method:</para>
<title>URI Templates In <interfacename>@RequestMapping</interfacename></title>
<para><emphasis>URI templates</emphasis> can be used for convenient access to selected
segments of a URL in a <interfacename>@RequestMapping</interfacename> method.</para>
<para>A URI Template is a URI-like string, containing one or more
variable names. When you substitute values for these variables, the
template becomes a URI. The <ulink
url="http://bitworking.org/projects/URI-Templates/">proposed RFC</ulink> for URI Templates
defines how a URI is parameterized. For example, the URI Template
<code>http://www.example.com/users/{userId}</code> contains the variable
<emphasis>userId</emphasis>. Assigning the value <emphasis>fred</emphasis> to the variable
yields <code>http://www.example.com/users/fred</code>.</para>
<para>In Spring MVC you can apply the <interfacename>@PathVariable</interfacename> annotation
to a method argument to indicate that it is bound to the value of a URI template variable:</para>
<programlisting language="java">@RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
public String findOwner(<emphasis role="bold">@PathVariable</emphasis> String ownerId, Model model) {
@ -829,36 +812,32 @@ public String findOwner(<emphasis role="bold">@PathVariable</emphasis> String ow @@ -829,36 +812,32 @@ public String findOwner(<emphasis role="bold">@PathVariable</emphasis> String ow
</programlisting>
<para>The URI Template "<literal>/owners/{ownerId}</literal>"
specifies the variable name <emphasis>ownerId</emphasis>. When the
controller handles this request, the value of
<emphasis>ownerId</emphasis> is set to the value in the request URI.
For example, when a request comes in for /owners/fred, the value fred
is bound to the method parameter <literal>String
ownerId</literal>.</para>
<!-- MLP: Bev Review -->
<para>The matching of method parameter names to URI Template variable
names can only be done if your code is compiled with debugging
enabled. If you do not have debugging enabled, you must specify the
name of the URI Template variable name in the @PathVariable annotation
in order to bind the resolved value of the variable name to a method
parameter. For example:</para>
specifies the variable name <literal>ownerId</literal>. When the
controller handles this request, the value of <literal>ownerId</literal>
is set to the value found in the appropriate segment of the URI.
For example, when a request comes in for <code>/owners/fred</code>, the value
<literal>fred</literal> is bound to the <literal>ownerId</literal> method argument.</para>
<programlisting language="java">@RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
<tip>
<para>The matching of method parameter names to URI Template variable
names can only be done if your code is compiled with debugging
enabled. This is normally the case, however, if you do not have debugging enabled,
you will need to specify the name of the URI Template variable as follows:</para>
<programlisting language="java">@RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
public String findOwner(<emphasis role="bold">@PathVariable</emphasis>("ownerId") String ownerId, Model model) {
// implementation omitted
}</programlisting>
<para>You can also use a controller method with the following
signature:</para>
<programlisting language="java">@RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
<para>You can do the same if you want the names of URI template variable and the method argument to differ:</para>
<programlisting language="java">@RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
public String findOwner(<emphasis role="bold">@PathVariable</emphasis>("ownerId") String theOwner, Model model) {
// implementation omitted
}</programlisting>
</tip>
<para>You can use multiple @PathVariable annotations to bind <!--specify: to bind *what* to multiple URI template variables? method parameter String ownerId?-->to
multiple URI Template variables:</para>
<para>A method can have multiple <interfacename>@PathVariable</interfacename> annotations:</para>
<programlisting language="java">@RequestMapping(value="/owners/{ownerId}/pets/{petId}", method=RequestMethod.GET)
public String findPet(<emphasis role="bold">@PathVariable</emphasis> String ownerId, <emphasis
@ -870,10 +849,9 @@ public String findPet(<emphasis role="bold">@PathVariable</emphasis> String owne @@ -870,10 +849,9 @@ public String findPet(<emphasis role="bold">@PathVariable</emphasis> String owne
}
</programlisting>
<para>The following code snippet shows the usage of path variables on
a relative path, so that the <methodname>findPet()</methodname> method
will be invoked for <filename>/owners/42/pets/21</filename>, for
instance.</para>
<para>A URI template can be assembled from type and path level <emphasis>@RequestMapping</emphasis>
annotations. As a result the <methodname>findPet()</methodname> method can be invoked with a URL
such as <filename>/owners/42/pets/21</filename>.</para>
<programlisting language="java">@Controller
@RequestMapping(<emphasis role="bold">"/owners/{ownerId}"</emphasis>)
@ -886,22 +864,19 @@ public class RelativePathUriTemplateController { @@ -886,22 +864,19 @@ public class RelativePathUriTemplateController {
}
</programlisting>
<tip>
<para>Method parameters that are decorated with the
<interfacename>@PathVariable</interfacename> annotation can be of
<emphasis role="bold">any simple type </emphasis>such as int, long,
Date, etc. Spring automatically converts to the appropriate type and
throws a <classname>TypeMismatchException</classname> if the type is
not correct. You can further customize this conversion process by
customizing the data binder. See <xref linkend="mvc-ann-typeconversion"/>
and <xref linkend="mvc-ann-webdatabinder" />.</para>
</tip>
</section>
<para><interfacename>@PathVariable</interfacename> method arguments can be of
<emphasis role="bold">any simple type</emphasis> such as int, long, Date, etc.
Spring automatically converts to the appropriate type or throws a
<classname>TypeMismatchException</classname> if it fails to do so.
This type conversion process can be customized through a data binder.
See <xref linkend="mvc-ann-typeconversion"/> and <xref linkend="mvc-ann-webdatabinder" />.
</para>
<section id="mvc-ann-requestmapping-advanced">
<title>Advanced <interfacename>@RequestMapping</interfacename>
options</title>
</section>
<section id="mvc-ann-requestmapping-patterns">
<title>Path Patterns In <interfacename>@RequestMapping</interfacename></title>
<para>In addition to URI templates, the
<interfacename>@RequestMapping</interfacename> annotation also
supports Ant-style path patterns (for example,
@ -909,58 +884,105 @@ public class RelativePathUriTemplateController { @@ -909,58 +884,105 @@ public class RelativePathUriTemplateController {
Ant-style globs is also supported (for example,
<filename>/owners/*/pets/{petId}</filename>).</para>
<para>The handler method names are taken into account for narrowing if
no path was specified explicitly, according to the specified
<interfacename>org.springframework.web.servlet.mvc.multiaction.MethodNameResolver</interfacename>
(by default an
<classname>org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver</classname>).
This only applies if annotation mappings 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.</para>
<para>If you have a single default method (without explicit path
mapping), then all requests without a more specific mapped method
found are dispatched to it. If you have multiple such default methods,
then the method name is taken into account for choosing between
them.</para>
<para>You can narrow path mappings through parameter conditions: a
sequence of "myParam=myValue" style expressions, with a request only
mapped if each such parameter is found to have the given value. For
example: <programlisting language="java">@Controller
</section>
<section id="mvc-ann-requestmapping-consumes">
<title>Consumable Media Types In <interfacename>@RequestMapping</interfacename></title>
<para>
You can narrow the primary mapping by specifying a list of consumable media types.
The request will be matched only if the <emphasis>Content-Type</emphasis> request header
matches the specified media type. For example:
</para>
<programlisting language="java">@Controller
@RequestMapping(value = "/pets", method = RequestMethod.POST, <emphasis role="bold">consumes="application/json"</emphasis>)
public void addPet(@RequestBody Pet pet, Model model) {
// implementation omitted
}
</programlisting>
<para>
Consumable media type expressions can also be negated as in <emphasis>!text/plain</emphasis>
to match to all requests other than those with <emphasis>Content-Type</emphasis> of
<emphasis>text/plain</emphasis>.
</para>
<tip>
<para>The <emphasis>consumes</emphasis> condition is supported on the type and on the
method level. Unlike most other conditions, when used at the type level, method-level
consumable types override rather than extend type-level consumeable types.</para>
</tip>
</section>
<section id="mvc-ann-requestmapping-produces">
<title>Producible Media Types In <interfacename>@RequestMapping</interfacename></title>
<para>
You can narrow the primary mapping by specifying a list of producible media types.
The request will be matched only if the <emphasis>Accept</emphasis> request header
matches one of these values. Furthermore, use of the <emphasis>produces</emphasis>
condition ensures the actual content type used to generate the response respects
the media types specified in the <emphasis>produces</emphasis> condition.
For example:
</para>
<programlisting language="java">@Controller
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, <emphasis role="bold">produces="application/json"</emphasis>)
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {
// implementation omitted
}
</programlisting>
<para>
Just like with <emphasis>consumes</emphasis>, producible media type
expressions can be negated as in <emphasis>!text/plain</emphasis> to match
to all requests other than those with an <emphasis>Accept</emphasis> header value of
<emphasis>text/plain</emphasis>.
</para>
<tip>
<para>The <emphasis>produces</emphasis> condition is supported on the type and on the method level.
Unlike most other conditions, when used at the type level, method-level producible types
override rather than extend type-level producible types.</para>
</tip>
</section>
<section id="mvc-ann-requestmapping-params-and-headers">
<title>Request Parameter and Header Conditions In <interfacename>@RequestMapping</interfacename></title>
<para>You can narrow request matching through request parameter conditions such as
<code>"myParam"</code>, <code>"!myParam"</code>, or <code>"myParam=myValue"</code>.
The first two test for request parameter presense/absence and the third for a specific parameter value.
Here is an example with a request parameter value condition:</para>
<programlisting language="java">@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping(value = "/pets/{petId}", <emphasis role="bold">params="myParam=myValue"</emphasis>)
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, <emphasis role="bold">params="myParam=myValue"</emphasis>)
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
// implementation omitted
}
}
</programlisting> "myParam" style expressions are also supported, with such
parameters having to be present in the request (allowed to have any
value). <!--I don't understand the preceding sentence. Can you reword?-->Finally,
"!myParam" style expressions indicate that the specified parameter is
<emphasis>not</emphasis> supposed to be present in the request.</para>
</programlisting>
<para>Similarly, path mappings can be narrowed down through header
conditions:</para>
<para>The same can be done to test for request header presence/absence or
to match based on a specific request header value:</para>
<programlisting language="java">@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping(value = "/pets", method = RequestMethod.POST, <emphasis
role="bold">headers="content-type=text/*"</emphasis>)
public void addPet(Pet pet, @PathVariable String ownerId) {
@RequestMapping(value = "/pets", method = RequestMethod.GET, <emphasis role="bold">headers="myHeader=myValue"</emphasis>)
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
// implementation omitted
}
}</programlisting>
<tip>
<para>Although you can match to <emphasis>Content-Type</emphasis> and
<emphasis>Accept</emphasis> header values using media type wildcards (for example
<emphasis>"content-type=text/*"</emphasis> will match to <emphasis>"text/plain"</emphasis>
and <emphasis>"text/html"</emphasis>), it is recommended to use the
<emphasis>consumes</emphasis> and <emphasis>produces</emphasis> conditions
respectively instead. They are intended specifically for that purpose.
</para>
</tip>
<para>In the above example, the <methodname>addPet()</methodname>
method is only invoked when the <literal>content-type</literal>
matches the <literal>text/*</literal> pattern, for example,
<literal>text/xml</literal>.</para>
</section>
<section id="mvc-ann-requestmapping-arguments">
@ -1074,19 +1096,19 @@ public class RelativePathUriTemplateController { @@ -1074,19 +1096,19 @@ public class RelativePathUriTemplateController {
</listitem>
<listitem>
<para>Command or form objects to bind parameters to: as bean
properties or fields, <!--What do you mean by *as bean properties or fields*, what does that refer to? Why do you have a colon? Don't get this line.--><!--*to bind parameters to* is awkward. Avoid slashes as with *command/form objects*. Do you mean command or form objects? Revise.-->with
<para>Command or form objects to bind request parameters to bean
properties (via setters) or directly to fields, with
customizable type conversion, depending on
<classname>@InitBinder</classname> methods and/or the
HandlerAdapter configuration. See the
<literal>webBindingInitializer</literal> property on
<classname>AnnotationMethodHandlerAdapter</classname>. Such
<classname>RequestMappingHandlerAdapter</classname>. Such
command objects along with their validation results will be
exposed as model attributes by default, using the non-qualified
command class name in property notation. <!--Who or what uses the non-qualified class name in property notation? Is this something you have to set up?-->For
example, "orderAddress" for type "mypackage.OrderAddress".
Specify a parameter-level <classname>ModelAttribute</classname>
annotation for declaring a specific model attribute name.</para>
exposed as model attributes by default, using the command class
class name - e.g. model attribute "orderAddress" for a command
object of type "some.package.OrderAddress".
The <classname>ModelAttribute</classname> annotation can be used
on a method argument to customize the model attribute name used.</para>
</listitem>
<listitem>

Loading…
Cancel
Save