From 6e86bc5bc26390ff6f1570e81aea9b7f83e950ef Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 19 May 2011 13:05:53 +0000 Subject: [PATCH] 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 --- .../resources/changelog.txt | 10 +- spring-framework-reference/src/mvc.xml | 336 ++++++++++-------- 2 files changed, 188 insertions(+), 158 deletions(-) diff --git a/build-spring-framework/resources/changelog.txt b/build-spring-framework/resources/changelog.txt index 6636c9503e8..c3f8d904185 100644 --- a/build-spring-framework/resources/changelog.txt +++ b/build-spring-framework/resources/changelog.txt @@ -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) -------------------------------------- diff --git a/spring-framework-reference/src/mvc.xml b/spring-framework-reference/src/mvc.xml index 6cc981bd40c..34e4f0e2fba 100644 --- a/spring-framework-reference/src/mvc.xml +++ b/spring-framework-reference/src/mvc.xml @@ -62,21 +62,20 @@ business objects. Spring's view resolution is extremely flexible. A - Controller implementation can even write - directly to the response stream. Typically, a - ModelAndView instance consists of a view name and a - model Map, 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 ViewResolver - implementation. The model (the M in MVC) is based on the + Controller is typically responsible for preparing + a model Map 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 ViewResolver + implementation. The model (the M in MVC) is a Map interface, which allows for the complete abstraction of the view technology. You can integrate directly - JSP, Velocity, or any other rendering technology. The model - Map 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 Map is simply transformed into an + appropriate format, such as JSP request attributes, a Velocity template model. - +
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.--> @@ -261,14 +260,14 @@ <servlet-mapping> <servlet-name>example</servlet-name> - <url-pattern>*.form</url-pattern> + <url-pattern>/example/*</url-pattern> </servlet-mapping> </web-app> - In the preceding example, all requests ending with - .form will be handled by the example - DispatcherServlet. This is only the first step in + In the preceding example, all requests startig with + /example will be handled by the DispatcherServlet + instance named example. This is only the first step in setting up Spring Web MVC. You now need to configure the various beans used by the Spring Web MVC framework (over and above the DispatcherServlet @@ -590,9 +589,10 @@ Available in the samples repository, - the PetClinic web application leverages - the annotation support described in this section, in the context of - simple form processing. + a number of web applications leverage the annotation support described in this section + including MvcShowcase, MvcAjax, + MvcBasic, PetClinic, + PetCare, and others. @@ -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. - The following example shows a controller in a Spring MVC - application that uses this annotation: + The following example from the Petcare sample shows + a controller in a Spring MVC application that uses this annotation: @Controller @RequestMapping("/appointments") @@ -739,7 +739,7 @@ public class AppointmentsController { A @RequestMapping 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 PetClinic sample application shows a multi-action controller using @RequestMapping: @@ -765,60 +765,43 @@ public class ClinicController { } - Working with interface-based @Controller classes - 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. - @Transactional 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 - @RequestMapping 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 - proxy-target-class="true" in the configuration for the - functionality applied to the controller (in our transaction scenario - in <tx:annotation-driven />). 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 . - + Using <interfacename>@RequestMapping</interfacename> On Interface Methods + + A common pitfall when working with annotated controller classes + happens when applying functionality that requires creating a proxy + for the controller object (e.g. + @Transactional 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 + @RequestMapping annotations to the + interface as well as the mapping mechanism can only "see" the interface + exposed by the proxy. Alternatively, you could activate + proxy-target-class="true" in the configuration for the + functionality applied to the controller (in our transaction scenario + in <tx:annotation-driven />). 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 . + +
- URI Templates - - To access parts of a request URL in your handling methods, use - the URI templates in the - @RequestMapping path value. - - - URI Templates - - 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 proposed - RFC for URI Templates defines how a URI is parameterized. - For example, the URI Template - - http://www.example.com/users/{userid} - - contains the variable userid. If we - assign the variable the value fred, the URI Template yields: - - http://www.example.com/users/fred - - During the processing of a request, the URI can be compared to - an expected URI Template in order to extract a collection of - variables. - - - Use the @PathVariable method - parameter annotation to indicate that a method parameter should be - bound to the value of a URI template variable. - - The following code snippet shows the usage of a single - @PathVariable in a controller - method: + URI Templates In <interfacename>@RequestMapping</interfacename> + + URI templates can be used for convenient access to selected + segments of a URL in a @RequestMapping method. + + 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 proposed RFC for URI Templates + defines how a URI is parameterized. For example, the URI Template + http://www.example.com/users/{userId} contains the variable + userId. Assigning the value fred to the variable + yields http://www.example.com/users/fred. + + In Spring MVC you can apply the @PathVariable annotation + to a method argument to indicate that it is bound to the value of a URI template variable: @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET) public String findOwner(@PathVariable String ownerId, Model model) { @@ -829,36 +812,32 @@ public String findOwner(@PathVariable String ow The URI Template "/owners/{ownerId}" - specifies the variable name ownerId. When the - controller handles this request, the value of - ownerId 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 String - ownerId. - - - 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: + specifies the variable name ownerId. When the + controller handles this request, the value of ownerId + is set to the value found in the appropriate segment of the URI. + For example, when a request comes in for /owners/fred, the value + fred is bound to the ownerId method argument. - @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET) + + 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: + + @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET) public String findOwner(@PathVariable("ownerId") String ownerId, Model model) { // implementation omitted } - - You can also use a controller method with the following - signature: - - @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET) + + You can do the same if you want the names of URI template variable and the method argument to differ: + + @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET) public String findOwner(@PathVariable("ownerId") String theOwner, Model model) { // implementation omitted } + - You can use multiple @PathVariable annotations to bind to - multiple URI Template variables: + A method can have multiple @PathVariable annotations: @RequestMapping(value="/owners/{ownerId}/pets/{petId}", method=RequestMethod.GET) public String findPet(@PathVariable String ownerId, @PathVariable String owne } - The following code snippet shows the usage of path variables on - a relative path, so that the findPet() method - will be invoked for /owners/42/pets/21, for - instance. + A URI template can be assembled from type and path level @RequestMapping + annotations. As a result the findPet() method can be invoked with a URL + such as /owners/42/pets/21. @Controller @RequestMapping("/owners/{ownerId}") @@ -886,22 +864,19 @@ public class RelativePathUriTemplateController { } - - Method parameters that are decorated with the - @PathVariable annotation can be of - any simple type such as int, long, - Date, etc. Spring automatically converts to the appropriate type and - throws a TypeMismatchException if the type is - not correct. You can further customize this conversion process by - customizing the data binder. See - and . - -
+ @PathVariable method arguments can be of + any simple type such as int, long, Date, etc. + Spring automatically converts to the appropriate type or throws a + TypeMismatchException if it fails to do so. + This type conversion process can be customized through a data binder. + See and . + -
- Advanced <interfacename>@RequestMapping</interfacename> - options +
+
+ Path Patterns In <interfacename>@RequestMapping</interfacename> + In addition to URI templates, the @RequestMapping annotation also supports Ant-style path patterns (for example, @@ -909,58 +884,105 @@ public class RelativePathUriTemplateController { Ant-style globs is also supported (for example, /owners/*/pets/{petId}). - The handler method names are taken into account for narrowing if - no path was specified explicitly, according to the specified - org.springframework.web.servlet.mvc.multiaction.MethodNameResolver - (by default an - org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver). - 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. - - 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. - - 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: @Controller +
+ +
+ Consumable Media Types In <interfacename>@RequestMapping</interfacename> + + You can narrow the primary mapping by specifying a list of consumable media types. + The request will be matched only if the Content-Type request header + matches the specified media type. For example: + + @Controller +@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json") +public void addPet(@RequestBody Pet pet, Model model) { + // implementation omitted +} + + + Consumable media type expressions can also be negated as in !text/plain + to match to all requests other than those with Content-Type of + text/plain. + + + The consumes 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. + + +
+ +
+ Producible Media Types In <interfacename>@RequestMapping</interfacename> + + You can narrow the primary mapping by specifying a list of producible media types. + The request will be matched only if the Accept request header + matches one of these values. Furthermore, use of the produces + condition ensures the actual content type used to generate the response respects + the media types specified in the produces condition. + For example: + + @Controller +@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json") +@ResponseBody +public Pet getPet(@PathVariable String petId, Model model) { + // implementation omitted +} + + + Just like with consumes, producible media type + expressions can be negated as in !text/plain to match + to all requests other than those with an Accept header value of + text/plain. + + + The produces 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. + +
+ +
+ Request Parameter and Header Conditions In <interfacename>@RequestMapping</interfacename> + + You can narrow request matching through request parameter conditions such as + "myParam", "!myParam", or "myParam=myValue". + 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: + + @Controller @RequestMapping("/owners/{ownerId}") public class RelativePathUriTemplateController { - @RequestMapping(value = "/pets/{petId}", params="myParam=myValue") + @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, params="myParam=myValue") public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) { // implementation omitted } } - "myParam" style expressions are also supported, with such - parameters having to be present in the request (allowed to have any - value). Finally, - "!myParam" style expressions indicate that the specified parameter is - not supposed to be present in the request. + - Similarly, path mappings can be narrowed down through header - conditions: + The same can be done to test for request header presence/absence or + to match based on a specific request header value: @Controller @RequestMapping("/owners/{ownerId}") public class RelativePathUriTemplateController { -@RequestMapping(value = "/pets", method = RequestMethod.POST, headers="content-type=text/*") - public void addPet(Pet pet, @PathVariable String ownerId) { +@RequestMapping(value = "/pets", method = RequestMethod.GET, headers="myHeader=myValue") + public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) { // implementation omitted } } + + Although you can match to Content-Type and + Accept header values using media type wildcards (for example + "content-type=text/*" will match to "text/plain" + and "text/html"), it is recommended to use the + consumes and produces conditions + respectively instead. They are intended specifically for that purpose. + + - In the above example, the addPet() - method is only invoked when the content-type - matches the text/* pattern, for example, - text/xml.
@@ -1074,19 +1096,19 @@ public class RelativePathUriTemplateController { - Command or form objects to bind parameters to: as bean - properties or fields, with + Command or form objects to bind request parameters to bean + properties (via setters) or directly to fields, with customizable type conversion, depending on @InitBinder methods and/or the HandlerAdapter configuration. See the webBindingInitializer property on - AnnotationMethodHandlerAdapter. Such + RequestMappingHandlerAdapter. 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. For - example, "orderAddress" for type "mypackage.OrderAddress". - Specify a parameter-level ModelAttribute - annotation for declaring a specific model attribute name. + 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 ModelAttribute annotation can be used + on a method argument to customize the model attribute name used.