diff --git a/spring-framework-reference/src/mvc.xml b/spring-framework-reference/src/mvc.xml
index 37609f7e64f..8ff7c2cf9ad 100644
--- a/spring-framework-reference/src/mvc.xml
+++ b/spring-framework-reference/src/mvc.xml
@@ -1,8 +1,7 @@
-
-
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+Web MVC framework
@@ -11,25 +10,14 @@
Spring's Web MVC framework is designed around a
DispatcherServlet that dispatches requests to
handlers, with configurable handler mappings, view resolution, locale and
- theme resolution as well as support for upload files. The default handler
- is a very simple Controller interface, just
- offering a ModelAndView handleRequest(request,response)
- method. This can already be used for application controllers, but you will
- prefer the included implementation hierarchy, consisting of, for example
- AbstractController,
- AbstractCommandController and
- SimpleFormController. Application controllers will
- typically be subclasses of those. Note that you can choose an appropriate
- base class: if you don't have a form, you don't need a form controller.
- This is a major difference to Struts.
-
-
- Since Spring 2.5, an annotated controller style is available
- for Java 5+ users. This is a compelling alternative to implementing
- traditional Controller (sub-)classes,
- allowing for flexible multi-action handling. See the
- section for details.
-
+ theme resolution as well as support for uploading files. The default
+ handler is based on the @Controller and
+ @RequestMapping annotations, offering a
+ wide range of flexible handling methods. With the introduction of Spring
+ 3.0, the @Controller mechanism also allows
+ your to create RESTful Web sites or application, though the
+ @PathVarariable annotation and other
+ features.
Open for extension...
@@ -66,42 +54,23 @@
Note that you cannot add advice to final methods using Spring MVC.
This means it won't be possible to add advice to for example the
AbstractController.handleRequest() method. Refer to
- for more information on
+ for more information on
AOP proxies and why you cannot add advice to final methods.Spring Web MVC allows you to use any object as a command or form
- object - there is no need to implement a framework-specific interface or
- base class. Spring's data binding is highly flexible: for example, it
- treats type mismatches as validation errors that can be evaluated by the
- application, not as system errors. All this means that you don't need to
- duplicate your business objects' properties as simple, untyped strings in
- your form objects just to be able to handle invalid submissions, or to
- convert the Strings properly. Instead, it is often preferable to bind
- directly to your business objects. This is another major difference to
- Struts which is built around required base classes such as
- Action and
- ActionForm.
-
- Compared to WebWork, Spring has more differentiated object roles. It
- supports the notion of a Controller, an
- optional command or form object, and a model that gets passed to the view.
- The model will normally include the command or form object but also
- arbitrary reference data; instead, a WebWork
- Action combines all those roles into one
- single object. WebWork does allow you to use existing business objects as
- part of your form, but only by making them bean properties of the
- respective Action class. Finally, the same
- Action instance that handles the request is
- used for evaluation and form population in the view. Thus, reference data
- needs to be modeled as bean properties of the
- Action too. These are (arguably) too many
- roles for one object.
+ backing object - there is no need to implement a framework-specific
+ interface or base class. Spring's data binding is highly flexible: for
+ example, it treats type mismatches as validation errors that can be
+ evaluated by the application, not as system errors. All this means that
+ you don't need to duplicate your business objects' properties as simple,
+ untyped strings in your form objects just to be able to handle invalid
+ submissions, or to convert the Strings properly. Instead, it is often
+ preferable to bind directly to your business objects.
Spring's view resolution is extremely flexible. A
- Controller implementation can even write a
- view directly to the response (by returning null for
- the ModelAndView). In the normal case, a
+ Controller implementation can even write
+ directly to the response stream. In the normal case, a
ModelAndView instance consists of a view name and a
model Map, which contains bean names and
corresponding objects (like a command or form, containing reference data).
@@ -152,8 +121,8 @@
Features of Spring Web MVC
-
-
+ Spring's web module provides a wealth of unique web support
features, including:
@@ -175,10 +144,10 @@
- Adaptability, non-intrusiveness. Use whatever controller
- subclass you need (plain, command, form, wizard, multi-action, or a
- custom one) for a given scenario instead of deriving from a single
- controller for everything.
+ Adaptability, non-intrusiveness, and flexibility. Define
+ whatever controller method signature you need, possibly using one of
+ the parameter annotations (such as @RequestParam, @RequestHeader,
+ @PathVariable, and more) for a given scenario.
@@ -354,7 +323,7 @@
<servlet-mapping>
<servlet-name>golfing</servlet-name>
- <url-pattern>*.do</url-pattern>
+ <url-pattern>/golfing/*</url-pattern>
</servlet-mapping>
</web-app>
@@ -554,11 +523,13 @@
+
Parameter
+
Explanation
@@ -608,533 +579,986 @@
input into a sensible model which will be represented to the user by the
view. Spring has implemented the notion of a controller in a very abstract
way enabling a wide variety of different kinds of controllers to be
- created. Spring contains form-specific controllers, command-based
- controllers, and controllers that execute wizard-style logic, to name but
- a few.
+ created.
- Spring's basis for the controller architecture is the
- org.springframework.web.servlet.mvc.Controller
- interface, the source code for which is listed below.
+ Spring 2.5 introduced an annotation-based programming model for MVC
+ controllers, using annotations such as
+ @RequestMapping,
+ @RequestParam,
+ @ModelAttribute, etc. This annotation
+ support is available for both Servlet MVC and Portlet MVC. Controllers
+ implemented in this style do not have to extend specific base classes or
+ implement specific interfaces. Furthermore, they do not usually have
+ direct dependencies on Servlet or Portlet API's, although they can easily
+ get access to Servlet or Portlet facilities if desired.
- public interface Controller {
+
+ The Spring distribution ships with the
+ PetClinic sample, which is a web application that
+ takes advantage of the annotation support described in this section, in
+ the context of simple form processing. You can find the
+ PetClinic application in the
+ 'samples/petclinic' directory.
- /**
- * Process the request and return a ModelAndView object which the DispatcherServlet
- * will render.
- */
- ModelAndView handleRequest(
- HttpServletRequest request,
- HttpServletResponse response) throws Exception;
+ For a further sample application that builds on annotation-based
+ Web MVC, check out imagedb. The focus in that
+ sample is on stateless multi-action controllers, including the
+ processing of multipart file uploads. You can find the
+ imagedb application in the
+ 'samples/imagedb' directory.
+
-}
+ @Controller
+public class HelloWorldController {
- As you can see, the Controller
- interface defines a single method that is responsible for handling a
- request and returning an appropriate model and view. These three concepts
- are the basis for the Spring MVC implementation -
- ModelAndView and
- Controller. While the
- Controller interface is quite abstract,
- Spring offers a lot of Controller
- implementations out of the box that already contain a lot of the
- functionality you might need. The
- Controller interface just defines the most
- basic responsibility required of every controller; namely handling a
- request and returning a model and a view.
-
-
- AbstractController and
- WebContentGenerator
-
- To provide a basic infrastructure, all of Spring's various
- Controller inherit from
- AbstractController, a class offering caching
- support and, for example, the setting of the mimetype.
-
-
- Features offered by the
- AbstractController
-
-
-
-
-
-
-
- Feature
- Explanation
-
-
-
-
-
- supportedMethods
-
- indicates what methods this controller should accept.
- Usually this is set to both GET and
- POST, but you can modify this to reflect the
- method you want to support. If a request is received with a
- method that is not supported by the controller, the client will
- be informed of this (expedited by the throwing of a
- ServletException).
-
-
-
- requireSession
-
- indicates whether or not this controller requires a HTTP
- session to do its work. If a session is not present when such a
- controller receives a request, the user is informed of this by a
- ServletException being thrown.
-
-
-
- synchronizeOnSession
-
- use this if you want handling by this controller to be
- synchronized on the user's HTTP session.
-
-
-
- cacheSeconds
-
- when you want a controller to generate a caching
- directive in the HTTP response, specify a positive integer here.
- By default the value of this property is set to
- -1 so no caching directives will be
- included in the generated response.
-
-
-
- useExpiresHeader
-
- tweaks your controllers to specify the HTTP 1.0
- compatible "Expires" header in the
- generated response. By default the value of this property is
- true.
-
-
-
- useCacheHeader
-
- tweaks your controllers to specify the HTTP 1.1
- compatible "Cache-Control" header in the
- generated response. By default the value of this property is
- true.
-
-
-
-
-
- When using the AbstractController as the
- baseclass for your controllers you only have to override the
- handleRequestInternal(HttpServletRequest,
- HttpServletResponse) method, implement your logic, and return
- a ModelAndView object. Here is short example
- consisting of a class and a declaration in the web application
- context.
-
- package samples;
-
-public class SampleController extends AbstractController {
-
- public ModelAndView handleRequestInternal(
- HttpServletRequest request,
- HttpServletResponse response) throws Exception {
-
- ModelAndView mav = new ModelAndView("hello");
+ @RequestMapping("/helloWorld")
+ public ModelAndView helloWorld() {
+ ModelAndView mac = new ModelAndView();
+ mav.setViewName("helloWorld");
mav.addObject("message", "Hello World!");
- return mav;
+ return mav;
}
}
- <bean id="sampleController" class="samples.SampleController">
- <property name="cacheSeconds" value="120"/>
-</bean>
+ As you can see, the @Controller and
+ @RequestMapping annotations allow for
+ flexible method names and signatures. In this particular example the
+ method has no parameters and returns a
+ ModelAndView, but various other (and better)
+ strategies exist, as will be explained later in this section.
+ ModelAndView,
+ @Controller, and
+ @RequestMapping form the basis for the
+ Spring MVC implementation. This section document these annotations and how
+ they are most commonly used in a Servlet environment.
- The above class and the declaration in the web application context
- is all you need besides setting up a handler mapping (see the section
- entitled ) to get this very simple
- controller working. This controller will generate caching directives
- telling the client to cache things for 2 minutes before rechecking. This
- controller also returns a hard-coded view (which is typically considered
- bad practice).
+
+ Defining a controller with
+ @Controller
+
+ The @Controller annotation
+ indicates that a particular class serves the role of a
+ controller. There is no need to extend any
+ controller base class or reference the Servlet API. You are of course
+ still able to reference Servlet-specific features if you need to.
+
+ The basic purpose of the
+ @Controller annotation is to act as a
+ stereotype for the annotated class, indicating its role. The dispatcher
+ will scan such annotated classes for mapped methods, detecting
+ @RequestMapping annotations (see the next
+ section).
+
+ Annotated controller beans may be defined explicitly, using a
+ standard Spring bean definition in the dispatcher's context. However,
+ the @Controller stereotype also allows
+ for autodetection, aligned with Spring general support for detecting
+ component classes in the classpath and auto-registering bean definitions
+ for them.
+
+ To enable autodetection of such annotated controllers, you have to
+ add component scanning to your configuration. This is easily achieved by
+ using the spring-context schema as shown in the
+ following XML snippet:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+ <context:component-scan base-package="org.springframework.samples.petclinic.web"/>
+
+ // ...
+
+</beans>
-
- Other simple controllers
+
+ Mapping requests with
+ @RequestMapping
- Although you can extend AbstractController,
- Spring provides a number of concrete implementations which offer
- functionality that is commonly used in simple MVC applications. The
- ParameterizableViewController is basically the
- same as the example above, except for the fact that you can specify the
- view name that it will return in the web application context (and thus
- remove the need to hard-code the viewname in the Java class).
+ The @RequestMapping annotation is
+ used to map URLs like /appointments onto an entire
+ class or a particular handler method. It can be used to annotate both a
+ class or method, Typically the class-level annotation maps a specific
+ request path (or path pattern) onto a form controller, with additional
+ method-level annotations 'narrowing' the primary mapping for a specific
+ HTTP method request method ("GET"/"POST") or specific HTTP request
+ parameters.
- The UrlFilenameViewController inspects the
- URL and retrieves the filename of the file request and uses that as a
- viewname. For example, the filename of
- http://www.springframework.org/index.html request is
- index.
-
+ The following example shows a controller from the PetClinic sample
+ application that uses this annotation:
-
- The MultiActionController
+ @Controller
+@RequestMapping("/appointments")
+public class AppointmentsController {
- Spring offers a MultiActionController class
- that supports the aggregation of multiple request-handling methods into
- one controller, which then allows you to group related functionality
- together. (If you are a Struts veteran you might recognize the
- similarity between the Struts DispatchAction and
- the Spring MVC MultiActionController.) The
- MultiActionController class is defined in a
- distinct package -
- org.springframework.web.servlet.mvc.multiaction - and
- it is capable of mapping requests to method names and then invoking the
- correct method to handle a particular request. Using the
- MultiActionController is especially handy when
- you have a lot of related functionality that would perhaps be nice to
- define all in a single class without having to implement one
- Controller for each bit of functionality.
- The MultiActionController typically is not
- appropriate for capturing very complex request-handling logic or use
- cases that address totally-different areas of functionality, and you are
- encouraged to stick with the standard 'one
- piece-of-functionality maps to one
- Controller' for such
- cases.
+ private AppointmentBook appointmentBook;
+
+ @Autowired
+ public AppointmentsController(AppointmentBook appointmentBook) {
+ this.appointmentBook = appointmentBook;
+ }
- There are two usage-styles for the
- MultiActionController. Either you subclass the
- MultiActionController and specify the methods
- that will be resolved by the
- MethodNameResolver on your subclass, or
- you define a delegate object, on which methods resolved by the
- MethodNameResolver will be invoked. If
- you choose the former style, you do not need to set a delegate, but for
- the latter style, you will need to inject your delegate object into the
- MultiActionController as a collaborator (either
- as a single constructor argument or via the
- 'setDelegate' method).
+ @RequestMapping(method = RequestMethod.GET)
+ public Appointments get() {
+ return appointmentBook.getAppointmentsForToday();
+ }
- The MultiActionController needs some
- strategy to determine which method to invoke when handling an incoming
- request: this strategy is defined by the
- MethodNameResolver interface. The
- MultiActionController class exposes the
- 'methodNameResolver' property so that you can inject
- a MethodNameResolver that is capable of
- doing that. The methods that you define on a
- MultiActionController (or on the class of the
- injected delegate object) must conform to the following
- signature:
+ @RequestMapping(value="/{day}", method = RequestMethod.GET)
+ public void getForDay(@PathVariable Date day, ExternalContext context) {
+ Appointments appts = appointmentBook.getAppointmentsForDay(day);
+ context.getModel().addAttribute(appts);
+ context.selectView("appointments");
+ if (context.isAjaxRequest()) {
+ //could activate a ViewHelper for component associated with main
+ context.renderFragment("main");
+ }
+ }
- // 'anyMeaningfulName' can be replaced by any method name
-public [ModelAndView | Map | void] anyMeaningfulName(HttpServletRequest, HttpServletResponse [,HttpSession] [,AnyObject])
+ @RequestMapping(value="/new", method = RequestMethod.GET)
+ public AppointmentForm getNewForm() {
+ return new AppointmentForm();
+ }
- The full details of this method signature are covered in the
- class-level
- Javadoc of the MultiActionController
- source itself. If you are planning to use the
- MultiActionController, you are highly encouraged
- to consult that Javadoc. However, below you will find some basic
- examples of valid MultiActionController method
- signatures.
-
- The standard signature (mirrors the
- Controller interface method).
-
- public ModelAndView displayCatalog(HttpServletRequest, HttpServletResponse)
-
- This signature accepts a Login argument
- that will be populated (bound) with parameters retrieved from the
- request.
-
- public ModelAndView login(HttpServletRequest, HttpServletResponse, Login)
-
- This signature requires that the request already have a valid
- session.
-
- public ModelAndView viewCart(HttpServletRequest, HttpServletResponse, HttpSession)
-
- This signature accepts a Product argument
- that will be populated (bound) with parameters retrieved from the
- request and requires that the request already have
- a valid session. Note that the order of arguments is important: the
- session must be the third argument, and an object to be bound must
- always be the final argument (fourth when a session is specified, or
- third otherwise).
-
- public ModelAndView updateCart(HttpServletRequest, HttpServletResponse, HttpSession, Product)
-
- This signature has a void return type
- indicating that the handler method assumes the responsibility of writing
- the response.
-
- public void home(HttpServletRequest, HttpServletResponse)
-
- This signature has a Map return
- type indicating that a view name translator will be responsible for
- providing the view name based upon the request, and the model will
- consist of the Map's entries (see the
- section entitled below).
-
- public Map list(HttpServletRequest, HttpServletResponse)
-
- The MethodNameResolver is
- responsible for resolving method names based on the specifics of the
- incoming HttpServletRequest. A number of
- MethodNameResolver implementations are
- provided for you, and of course you can always write your own. Please
- also note that the InternalPathMethodNameResolver
- is the default MethodNameResolver that
- will be used if you don't inject one explicitly.
-
-
-
- InternalPathMethodNameResolver -
- interprets the final filename from the request path and uses that as
- the method name/
-
- For example,
- 'http://www.sf.net/testing.view' will result in
- the method testing(HttpServletRequest,
- HttpServletResponse) being invoked.
-
-
-
- ParameterMethodNameResolver -
- interprets a request parameter as the name of the method that is to
- be invoked.
-
- For example,
- 'http://www.sf.net/index.view?method=testIt' will
- result in the method testIt(HttpServletRequest,
- HttpServletResponse) being invoked. The
- 'paramName' property specifies the name of the
- request parameter that is to be used.
-
-
-
- PropertiesMethodNameResolver - uses a
- user-defined Properties object with request
- URLs mapped to method names. For example, when the
- Properties contain
- '/index/welcome.html=doIt' and a request to
- /index/welcome.html comes in, the
- doIt(HttpServletRequest,
- HttpServletResponse) method will be invoked. This
- particular MethodNameResolver uses
- the Spring PathMatcher class internally, so
- if the Properties contained
- '/**/welcom?.html', the example would also have
- worked.
-
-
-
- You may also declare custom methods for handling
- Exceptions that occur during request handling.
- The valid signature for such a method is similar to the request handling
- methods in that the HttpServletRequest
- and HttpServletResponse must be provided
- as the first and second parameters respectively. Unlike request handling
- methods however, the method's name is irrelevant. Instead, when
- determining which Exception handling method to
- invoke, the decision is based upon the most specific possible match
- among the methods whose third argument is some type of
- Exception. Here is an example signature for one
- such Exception handling method.
-
- public ModelAndView processException(HttpServletRequest, HttpServletResponse, IllegalArgumentException)
-
- Let's look at an example showing the delegate-style of
- MultiActionController usage in conjunction with
- the ParameterMethodNameResolver.
-
- <bean id="paramMultiController"
- class="org.springframework.web.servlet.mvc.multiaction.MultiActionController">
-
- <property name="methodNameResolver">
- <bean class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
- <property name="paramName" value="method"/>
- </bean>
- </property>
-
- <property name="delegate">
- <bean class="samples.SampleDelegate"/>
- </property>
-
-</bean>
-}
-
- public class SampleDelegate {
-
- public ModelAndView retrieveIndex(HttpServletRequest req, HttpServletResponse resp) {
- return new ModelAndView("index", "date", new Long(System.currentTimeMillis()));
+ @RequestMapping(method = RequestMethod.POST)
+ public String post(AppointmentForm form) {
+ appointmentBook.createAppointment(form);
+ return "redirect:/appointments";
}
}
- When using the delegate shown above, we could also configure the
- PropertiesMethodNameResolver to match any number
- couple of URLs to the method we defined:
+ In the example, above, we see that the
+ @RequestMapping is used in a number of
+ places. The first usage is on the type (class) level, which indicates
+ that all handling methods on this controller will be relative to the
+ /appointments path. Next, we see that the
+ get() method has a further
+ @RequestMapping refinement: it only
+ accepts GET requests, meaning that an HTTP GET for
+ /appointments will result in this method being
+ invoked. The post() has a similar refinement,
+ and the getNewForm() combines the definition of
+ HTTP method and path into one, so that GET requests for
+ appointments/new are handled by that method.
- <bean id="propsResolver"
- class="org....mvc.multiaction.PropertiesMethodNameResolver">
- <property name="mappings">
- <value>
-/index/welcome.html=retrieveIndex
-/**/notwelcome.html=retrieveIndex
-/*/user?.html=retrieveIndex
- </value>
- </property>
+ The getForDay() method shows another
+ usage of @RequestMapping: URI templates.
+ We will discuss these in the next section
+ .
+
+ A @RequestMapping on the class
+ level is not required. Without it, all paths are simply absolute, and
+ not relative. The following is an example of a multi-action controller
+ from the PetClinic sample application using
+ @RequestMapping:
+
+ @Controller
+public class ClinicController {
+
+ private final Clinic clinic;
+
+ @Autowired
+ public ClinicController(Clinic clinic) {
+ this.clinic = clinic;
+ }
+
+ @RequestMapping("/")
+ public void welcomeHandler() {
+ }
+
+ @RequestMapping("/vets")
+ public ModelMap vetsHandler() {
+ return new ModelMap(this.clinic.getVets());
+ }
+
+}
+
+
+ URI Templates
+
+ To easily access (parts of) a request URL in your handling
+ methods, Spring MVC allows for the use of URI
+ templates in the
+ @RequestMapping path value.
+
+
+ URI Templates
+
+ A URI Template is a URI-like string, containing one or more
+ variable names. When these variables are substituted for values, the
+ template becomes a URI The proposed
+ RFC for URI Templates defines how an 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", then 'expanding' the URI Template gives.
+
+ http://www.example.com/users/fred
+
+ When processing a request the URI can be compared to an
+ expected URI Template in order to extract a collection of
+ variables.
+
+
+ The @PathVariable method
+ parameter annotation is used to indicate that a method parameter
+ should be bound to the value of a URI template variable.
+
+ The following code snippet shows the use of a single
+ @PathVariable in a controller
+ method:
+
+ @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
+public String findOwner(@PathVariable String ownerId, Model model) {
+ Owner owner = ownerService.findOwner(ownerId);
+ model.addAttribute("owner", owner);
+ return "displayOwner";
+}
+
+
+ The URI Template "/owners/{ownerId}"
+ specifies the variable name ownerId. When the controller handles this
+ request, the value of ownerId is set 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 have not debugging enabled, you must specify the
+ name of the URI Template variable name to bind to in the @PathVariable
+ annotation. For example:
+
+ @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
+public String findOwner(@PathVariable("ownerId") String ownerId, Model model) {
+ // implementation omitted
+}
+
+
+ The name of the method parameter does not matter in this case,
+ so you may also use a controller method with the signature shown
+ below
+
+ @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
+public String findOwner(@PathVariable("ownerId") String theOwner, Model model) {
+ // implementation omitted
+}
+
+ Multiple @PathVariable annotations can be used to bind to
+ multiple URI Template variables as shown below:
+
+ @RequestMapping(value="/owners/{ownerId}/pets/{petId}", method=RequestMethod.GET)
+public String findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
+ Owner owner = ownerService.findOwner(ownderId);
+ Pet pet = owner.getPet(petId);
+ model.addAttribute("pet", pet);
+ return "displayPet";
+}
+
+
+ The following code snippet shows the use of path variables on a
+ relative path, so that the findPet() method
+ will be invoked for /owners/42/pets/21, for
+ instance.
+
+ @Controller
+@RequestMapping("/owners/{ownerId}")
+public class RelativePathUriTemplateController {
+
+ @RequestMapping("/pets/{petId}")
+ public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
+ // implementation omitted
+ }
+}
+
+
+
+ Method parameters that are decorated with the
+ @PathVariable annotation can be of
+ any simple type such as int, long,
+ Date... Spring automatically converts to the appropriate type and
+ throws a TypeMismatchException if the type is
+ not correct. You can further customizing this conversion process by
+ customizing the data binder, see .
+
+
+
+
+ Advanced @RequestMapping
+ options
+
+ In addition to URI templates, the
+ @RequestMapping annotation also
+ supports Ant-style path patterns (e.g.
+ /myPath/*.do). A combination of URI templates and
+ Ant-style globs is also supported (e.g.
+ /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).
+ 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.
+
+ 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.
+
+ Path mappings can be narrowed 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
+@RequestMapping("/owners/{ownerId}")
+public class RelativePathUriTemplateController {
+
+ @RequestMapping(value = "/pets/{petId}", 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: @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) {
+ // implementation omitted
+ }
+}
+ In the above example, the addPet
+ will only be invoked when the Content-Type is in the
+ text/* range, for instance
+ text/xml.
+
+
+
+ Supported handler method arguments and return types
+
+ Handler methods which are annotated with
+ @RequestMapping are allowed to have very
+ flexible signatures. They may have arguments of the following types,
+ in arbitrary order (except for validation results, which need to
+ follow right after the corresponding command object, if desired):
+
+
+ Request and/or response objects (Servlet API). You may
+ choose any specific request/response type, e.g.
+ ServletRequest /
+ HttpServletRequest.
+
+
+
+ Session object (Servlet API): of type
+ HttpSession. An argument of this
+ type will enforce the presence of a corresponding session. As a
+ consequence, such an argument will never be
+ null.
+
+
+ Note that session access may not be thread-safe, in
+ particular in a Servlet environment: Consider switching the
+ AnnotationMethodHandlerAdapter's
+ "synchronizeOnSession" flag to "true" if multiple requests are
+ allowed to access a session concurrently.
+
+
+
+
+ org.springframework.web.context.request.WebRequest
+ or
+ org.springframework.web.context.request.NativeWebRequest.
+ Allows for generic request parameter access as well as
+ request/session attribute access, without ties to the native
+ Servlet/Portlet API.
+
+
+
+ java.util.Locale for the current
+ request locale (determined by the most specific locale resolver
+ available, i.e. the configured
+ LocaleResolver in a Servlet
+ environment).
+
+
+
+ java.io.InputStream /
+ java.io.Reader for access to the
+ request's content. This will be the raw InputStream/Reader as
+ exposed by the Servlet API.
+
+
+
+ java.io.OutputStream /
+ java.io.Writer for generating the
+ response's content. This will be the raw OutputStream/Writer as
+ exposed by the Servlet API.
+
+
+
+ @PathVariabe annotated parameters
+ for access to URI template variables, see .
+
+
+
+ @RequestParam annotated parameters
+ for access to specific Servlet request parameters. Parameter
+ values will be converted to the declared method argument type.
+ See .
+
+
+
+ @RequestHeader annotated parameters
+ for access to specific Servlet request HTTP headers. Parameter
+ values will be converted to the declared method argument
+ type.
+
+
+
+ @RequestBody annotated parameters
+ for access to the request HTTP body. Parameter values will be
+ converted to the declared method argument type using
+ HttpMessageConverters. See .
+
+
+
+ java.util.Map /
+ org.springframework.ui.Model /
+ org.springframework.ui.ModelMap for
+ enriching the implicit model that will be exposed to the web
+ view.
+
+
+
+ Command/form objects to bind parameters to: as bean
+ properties or fields, with customizable type conversion,
+ depending on @InitBinder methods and/or
+ the HandlerAdapter configuration - see the
+ "webBindingInitializer" property on
+ AnnotationMethodHandlerAdapter. 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 (e.g. "orderAddress" for
+ type "mypackage.OrderAddress"). Specify a parameter-level
+ ModelAttribute annotation for declaring a
+ specific model attribute name.
+
+
+
+ org.springframework.validation.Errors
+ /
+ org.springframework.validation.BindingResult
+ validation results for a preceding command/form object (the
+ immediate preceding argument).
+
+
+
+ org.springframework.web.bind.support.SessionStatus
+ status handle for marking form processing as complete
+ (triggering the cleanup of session attributes that have been
+ indicated by the @SessionAttributes
+ annotation at the handler type level).
+
+
+
+ The following return types are supported for handler methods:
+
+
+ A ModelAndView object, with the
+ model implicitly enriched with command objects and the results
+ of @ModelAttribute annotated reference data
+ accessor methods.
+
+
+
+ A Model object, with the
+ view name implicitly determined through a
+ RequestToViewNameTranslator and
+ the model implicitly enriched with command objects and the
+ results of @ModelAttribute annotated
+ reference data accessor methods.
+
+
+
+ A Map object for exposing a
+ model, with the view name implicitly determined through a
+ RequestToViewNameTranslator and
+ the model implicitly enriched with command objects and the
+ results of @ModelAttribute annotated
+ reference data accessor methods.
+
+
+
+ A View object, with the
+ model implicitly determined through command objects and
+ @ModelAttribute annotated reference data
+ accessor methods. The handler method may also programmatically
+ enrich the model by declaring a
+ Model argument (see
+ above).
+
+
+
+ A String value which is interpreted
+ as view name, with the model implicitly determined through
+ command objects and @ModelAttribute annotated
+ reference data accessor methods. The handler method may also
+ programmatically enrich the model by declaring a
+ Model argument (see
+ above).
+
+
+
+ void if the method handles the response
+ itself (by writing the response content directly, declaring an
+ argument of type ServletResponse
+ / HttpServletResponse for that
+ purpose) or if the view name is supposed to be implicitly
+ determined through a
+ RequestToViewNameTranslator (not
+ declaring a response argument in the handler method
+ signature).
+
+
+
+ If the method is annotated with
+ @ResponseBody, the return type
+ will be written to the response HTTP body. The return value will
+ be converted to the declared method argument type using
+ HttpMessageConverters. See .
+
+
+
+ Any other return type will be considered as single model
+ attribute to be exposed to the view, using the attribute name
+ specified through @ModelAttribute at the
+ method level (or the default attribute name based on the return
+ type's class name otherwise). The model will be implicitly
+ enriched with command objects and the results of
+ @ModelAttribute annotated reference data
+ accessor methods.
+
+
+
+
+
+ Binding request parameters to method parameters with
+ @RequestParam
+
+ The @RequestParam annotation is used to
+ bind request parameters to a method parameter in your
+ controller.
+
+ The following code snippet shows the usage:
+
+ @Controller
+@RequestMapping("/pets")
+@SessionAttributes("pet")
+public class EditPetForm {
+
+ // ...
+
+ @RequestMapping(method = RequestMethod.GET)
+ public String setupForm(@RequestParam("petId") int petId, ModelMap model) {
+ Pet pet = this.clinic.loadPet(petId);
+ model.addAttribute("pet", pet);
+ return "petForm";
+ }
+
+ // ...
+
+
+ Parameters using this annotation are required by default, but
+ you can specify that a parameter is optional by setting
+ @RequestParam's
+ required attribute to false
+ (e.g., @RequestParam(value="id",
+ required="false")).
+
+
+
+ Mapping the request body with the @RequestBody
+ annotation
+
+ The @RequestBody method parameter
+ annotation is used to indicate that a method parameter should be bound
+ to the value of the HTTP request body. For example,
+
+ @RequestMapping(value = "/something", method = RequestMethod.PUT)
+public void handle(@RequestBody String body, Writer writer) throws IOException {
+ writer.write(body);
+}
+
+ The conversion of the request body to the method argument is
+ done using a HttpMessageConverter.
+ HttpMessageConverter is responsible for
+ converting from the HTTP request message to an object and converting
+ from an object to the HTTP response body.
+ DispatcherServlet supports annotation based
+ processing using the
+ DefaultAnnotationHandlerMapping and
+ AnnotationMethodHandlerAdapter. In Spring 3 the
+ AnnotationMethodHandlerAdapter has been
+ extended to support the @RequestBody and has
+ several HttpMessageConverters
+ registered by default, these are
+
+
+
+ ByteArrayHttpMessageConverter -
+ converts byte arrays
+
+
+
+ StringHttpMessageConverter - converts
+ strings
+
+
+
+ FormHttpMessageConverter - converts
+ form data to/from a MultiValueMap<String, String>
+
+
+
+ SourceHttpMessageConverter - converts
+ to/from a javax.xml.transform.Source;
+
+
+
+ MarshallingHttpMessageConverter -
+ converts to/from an object using the
+ org.springframework.oxm package.
+
+
+
+ More information on these converters can be found in the section
+ Message
+ Converters.
+
+ The MarshallingHttpMessageConverter
+ requires a Marshaller and
+ Unmarshaller from the
+ org.springframework.oxm package to be
+ configured on an instance of
+ AnnotationMethodHandlerAdapter in the
+ application context. For example
+
+ <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
+ <property name="messageConverters">
+ <util:list id="beanList">
+ <ref bean="stringHttpMessageConverter"/>
+ <ref bean="marshallingHttpMessageConverter"/>
+ </util:list>
+ </property
</bean>
-<bean id="paramMultiController" class="org....mvc.multiaction.MultiActionController">
+<bean id="stringHttpMessageConverter"
+ class="org.springframework.http.converter.StringHttpMessageConverter"/>
- <property name="methodNameResolver" ref="propsResolver"/>
- <property name="delegate">
- <bean class="samples.SampleDelegate"/>
+<bean id="marshallingHttpMessageConverter"
+ class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
+ <property name="marshaller" ref="castorMarshaller" />
+ <property name="unmarshaller" ref="castorMarshaller" />
+</bean>
+
+<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
+
+
+
+
+ Mapping the response body with the @ResponseBody
+ annotation
+
+ Similar to @RequestBody, there is
+ the @ResponseBody annotation. This
+ annotation can be put on a method and indicates that the return type
+ should be written straight to the HTTP response body (and not placed
+ in a Model, or interpreted as a view name). For example,
+
+ @RequestMapping(value = "/something", method = RequestMethod.PUT)
+@ResponseBody
+public String helloWorld() {
+ return "Hello World";
+}
+
+ The example above will result in the text Hello
+ World being written to the HTTP response stream.
+
+ Just like @RequestBody, the
+ conversion of the returned object to response body is done using a
+ HttpMessageConverter. More information
+ on these converters can be found in the previous section, or in the
+ section Message
+ Converters.
+
+
+
+ Providing a link to data from the model with
+ @ModelAttribute
+
+ @ModelAttribute has two usage scenarios
+ in controllers. When placed on a method parameter,
+ @ModelAttribute is used to map a model
+ attribute to the specific, annotated method parameter (see the
+ processSubmit() method below). This is how the
+ controller gets a reference to the object holding the data entered in
+ the form.
+
+ @ModelAttribute is also used at the
+ method level to provide reference data for the
+ model (see the populatePetTypes() method below).
+ For this usage the method signature can contain the same types as
+ documented above for the @RequestMapping
+ annotation.
+
+
+ Note:
+ @ModelAttribute annotated methods will be
+ executed before the chosen
+ @RequestMapping annotated handler method.
+ They effectively pre-populate the implicit model with specific
+ attributes, often loaded from a database. Such an attribute can then
+ already be accessed through @ModelAttribute
+ annotated handler method parameters in the chosen handler method,
+ potentially with binding and validation applied to it.
+
+
+ The following code snippet shows these two usages of this
+ annotation:
+
+ @Controller
+@RequestMapping("/owners/{ownerId}/pets/{petId}/edit")
+@SessionAttributes("pet")
+public class EditPetForm {
+
+ // ...
+
+ @ModelAttribute("types")
+ public Collection<PetType> populatePetTypes() {
+ return this.clinic.getPetTypes();
+ }
+
+ @RequestMapping(method = RequestMethod.POST)
+ public String processSubmit(
+ @ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) {
+
+ new PetValidator().validate(pet, result);
+ if (result.hasErrors()) {
+ return "petForm";
+ }
+ else {
+ this.clinic.storePet(pet);
+ status.setComplete();
+ return "redirect:owner.do?ownerId=" + pet.getOwner().getId();
+ }
+ }
+
+}
+
+
+
+ Specifying attributes to store in a Session with
+ @SessionAttributes
+
+ The type-level @SessionAttributes
+ annotation declares session attributes used by a specific handler.
+ This will typically list the names of model attributes which should be
+ transparently stored in the session or some conversational storage,
+ serving as form-backing beans between subsequent requests.
+
+ The following code snippet shows the usage of this
+ annotation:
+
+ @Controller
+@RequestMapping("/editPet.do")
+@SessionAttributes("pet")
+public class EditPetForm {
+ // ...
+}
+
+
+
+
+ Mapping cookie values with the @CookieValue annotation
+
+ The @CookieValue annotation
+ allows a method parameter to be bound to the value of an HTTP
+ cookie.
+
+ Let us consider that the following cookie has been received with
+ an http request:
+
+ JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84
+
+ The following code sample allows you to easily get the value of
+ the "JSESSIONID"cookie:
+
+ @RequestMapping("/displayHeaderInfo.do")
+public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie) {
+
+ //...
+
+}
+
+ This annotation is supported for annotated handler methods in
+ Servlet and Portlet environments.
+
+
+
+ Mapping request header attributes with the @RequestHeader
+ annotation
+
+ The @RequestHeader annotation
+ allows a method parameter to be bound to a request header.
+
+ Here is a request header sample:
+
+
+Host localhost:8080
+Accept text/html,application/xhtml+xml,application/xml;q=0.9
+Accept-Language fr,en-gb;q=0.7,en;q=0.3
+Accept-Encoding gzip,deflate
+Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
+Keep-Alive 300
+
+
+ The following code sample allows you to easily get the value of
+ the "Accept-Encoding" and "Keep-Alive" headers:
+
+ @RequestMapping("/displayHeaderInfo.do")
+ public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding,
+ @RequestHeader("Keep-Alive") long keepAlive) {
+
+ //...
+
+}
+
+ This annotation is supported for annotated handler methods in
+ Servlet and Portlet environments.
+
+
+
+ Customizing WebDataBinder
+ initialization
+
+ To customize request parameter binding with PropertyEditors,
+ etc. via Spring's WebDataBinder, you can either
+ use @InitBinder-annotated methods
+ within your controller or externalize your configuration by providing
+ a custom WebBindingInitializer.
+
+
+ Customizing data binding with
+ @InitBinder
+
+ Annotating controller methods with
+ @InitBinder allows you to configure
+ web data binding directly within your controller class.
+ @InitBinder identifies methods which
+ initialize the WebDataBinder which will be
+ used for populating command and form object arguments of annotated
+ handler methods.
+
+ Such init-binder methods support all arguments that
+ @RequestMapping supports, except for
+ command/form objects and corresponding validation result objects.
+ Init-binder methods must not have a return value. Thus, they are
+ usually declared as void. Typical arguments
+ include WebDataBinder in combination with
+ WebRequest or
+ java.util.Locale, allowing code to register
+ context-specific editors.
+
+ The following example demonstrates the use of
+ @InitBinder for configuring a
+ CustomDateEditor for all
+ java.util.Date form properties.
+
+ @Controller
+public class MyFormController {
+
+ @InitBinder
+ public void initBinder(WebDataBinder binder) {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ dateFormat.setLenient(false);
+ binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
+ }
+
+ // ...
+}
+
+
+
+ Configuring a custom
+ WebBindingInitializer
+
+ To externalize data binding initialization, you can provide a
+ custom implementation of the
+ WebBindingInitializer interface,
+ which you then enable by supplying a custom bean configuration for
+ an AnnotationMethodHandlerAdapter, thus
+ overriding the default configuration.
+
+ The following example from the PetClinic application shows a
+ configuration using a custom implementation of the
+ WebBindingInitializer interface,
+ org.springframework.samples.petclinic.web.ClinicBindingInitializer,
+ which configures PropertyEditors required by several of the
+ PetClinic controllers.
+
+ <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
+ <property name="cacheSeconds" value="0" />
+ <property name="webBindingInitializer">
+ <bean class="org.springframework.samples.petclinic.web.ClinicBindingInitializer" />
</property>
-
-</bean>
-
-
-
- Command controllers
-
- Spring's command controllers are a
- fundamental part of the Spring Web MVC package. Command controllers
- provide a way to interact with data objects and dynamically bind
- parameters from the HttpServletRequest to
- the data object specified. They perform a somewhat similar role to the
- Struts ActionForm, but in Spring, your data
- objects don't have to implement a framework-specific interface. First,
- lets examine what command controllers are available straight out of the
- box.
-
-
-
- AbstractCommandController - a command
- controller you can use to create your own command controller,
- capable of binding request parameters to a data object you specify.
- This class does not offer form functionality; it does however offer
- validation features and lets you specify in the controller itself
- what to do with the command object that has been populated with
- request parameter values.
-
-
-
- AbstractFormController - an abstract
- controller offering form submission support. Using this controller
- you can model forms and populate them using a command object you
- retrieve in the controller. After a user has filled the form, the
- AbstractFormController binds the fields,
- validates the command object, and hands the object back to the
- controller to take the appropriate action. Supported features are:
- invalid form submission (resubmission), validation, and normal form
- workflow. You implement methods to determine which views are used
- for form presentation and success. Use this controller if you need
- forms, but don't want to specify what views you're going to show the
- user in the application context.
-
-
-
- SimpleFormController - a form
- controller that provides even more support when creating a form with
- a corresponding command object. The
- SimpleFormController let's you specify a
- command object, a viewname for the form, a viewname for page you
- want to show the user when form submission has succeeded, and
- more.
-
-
-
- AbstractWizardFormController - as the
- class name suggests, this is an abstract class - your wizard
- controller should extend it. This means you have to implement the
- validatePage(),
- processFinish() and
- processCancel() methods.
-
- You probably also want to write a contractor, which should at
- the very least call setPages() and
- setCommandName(). The former takes as its
- argument an array of type String. This array is the list of views
- which comprise your wizard. The latter takes as its argument a
- String, which will be used to refer to your command object from
- within your views.
-
- As with any instance of
- AbstractFormController, you are required to
- use a command object - a JavaBean which will be populated with the
- data from your forms. You can do this in one of two ways: either
- call setCommandClass() from the constructor with
- the class of your command object, or implement the
- formBackingObject() method.
-
- AbstractWizardFormController has a
- number of concrete methods that you may wish to override. Of these,
- the ones you are likely to find most useful are:
- referenceData(..) which you can use to pass model
- data to your view in the form of a
- Map;
- getTargetPage() if your wizard needs to change
- page order or omit pages dynamically; and
- onBindAndValidate() if you want to override the
- built-in binding and validation workflow.
-
- Finally, it is worth pointing out the
- setAllowDirtyBack() and
- setAllowDirtyForward(), which you can call from
- getTargetPage() to allow users to move backwards
- and forwards in the wizard even if validation fails for the current
- page.
-
- For a full list of methods, see the Javadoc for
- AbstractWizardFormController. There is an
- implemented example of this wizard in the jPetStore included in the
- Spring distribution:
- org.springframework.samples.jpetstore.web.spring.OrderFormController.
-
-
+</bean>
+
+
+ Handler mappings
- Using a handler mapping you can map incoming web requests to
- appropriate handlers. There are some handler mappings you can use out of
- the box, for example, the SimpleUrlHandlerMapping
- or the BeanNameUrlHandlerMapping, but let's first
- examine the general concept of a
- HandlerMapping.
-
- The functionality a basic
- HandlerMapping provides is the delivering
- of a HandlerExecutionChain, which must contain the
- handler that matches the incoming request, and may also contain a list of
- handler interceptors that are applied to the request. When a request comes
- in, the DispatcherServlet will hand it over to the
- handler mapping to let it inspect the request and come up with an
- appropriate HandlerExecutionChain. Then the
- DispatcherServlet will execute the handler and
- interceptors in the chain (if any).
-
- The concept of configurable handler mappings that can optionally
- contain interceptors (executed before or after the actual handler was
- executed, or both) is extremely powerful. A lot of supporting
- functionality can be built into custom
- HandlerMappings. Think of a custom handler
- mapping that chooses a handler not only based on the URL of the request
- coming in, but also on a specific state of the session associated with the
- request.
-
- This section describes two of Spring's most commonly used handler
- mappings. They both extend the AbstractHandlerMapping
- and share the following properties:
+ In previous versions of Spring MVC, users were required to define HandlerMappings in
+ the web application context
+ to map incoming web requests to
+ appropriate handlers. With the introduction of Spring 2.5, the DispatcherServlet enables the
+ DefaultAnnotationHandlerMapping, which looks for
+ @RequestMapping annotations on @Controllers.
+ Typically, you do not need to override this default mapping, except when overriding the properties.
+ These properties are:
+
@@ -1191,139 +1615,16 @@ public [ModelAndView | Map | void] anyMeaningfulName(HttpServletRequest, HttpSer
subclasses of
org.springframework.web.servlet.handler.AbstractUrlHandlerMapping).
-
- BeanNameUrlHandlerMapping
+ The following example shows how to override the default mapping, and add an interceptor:
- A very simple, but very powerful handler mapping is the
- BeanNameUrlHandlerMapping, which maps incoming
- HTTP requests to names of beans, defined in the web application context.
- Let's say we want to enable a user to insert an account and we've
- already provided an appropriate form controller (see for more information on command- and
- form controllers) and a JSP view (or Velocity template) that renders the
- form. When using the BeanNameUrlHandlerMapping,
- we could map the HTTP request with the URL
- http://samples.com/editaccount.form to the
- appropriate form Controller as
- follows:
+
+
+
+
+
+
- <beans>
- <bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
-
- <bean name="/editaccount.form" class="org.springframework.web.servlet.mvc.SimpleFormController">
- <property name="formView" value="account"/>
- <property name="successView" value="account-created"/>
- <property name="commandName" value="account"/>
- <property name="commandClass" value="samples.Account"/>
- </bean>
-<beans>
-
- All incoming requests for the URL
- /editaccount.form will now be handled by the form
- Controller in the source listing above.
- Of course we have to define a servlet-mapping in
- web.xml as well, to let through all the requests
- ending with .form.
-
- <web-app>
- ...
- <servlet>
- <servlet-name>sample</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <!-- maps the sample dispatcher to *.form -->
- <servlet-mapping>
- <servlet-name>sample</servlet-name>
- <url-pattern>*.form</url-pattern>
- </servlet-mapping>
- ...
-</web-app>
-
-
- If you want to use the
- BeanNameUrlHandlerMapping, you don't
- necessarily have to define it in the web application context (as
- indicated above). By default, if no handler mapping can be found in
- the context, the DispatcherServlet creates a
- BeanNameUrlHandlerMapping for you!
-
-
-
-
- SimpleUrlHandlerMapping
-
- A further - and much more powerful handler mapping - is the
- SimpleUrlHandlerMapping. This mapping is
- configurable in the application context and has Ant-style path matching
- capabilities (see the Javadoc for the
- org.springframework.util.PathMatcher class). Here
- is an example:
-
- <web-app>
- ...
- <servlet>
- <servlet-name>sample</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <!-- maps the sample dispatcher to *.form -->
- <servlet-mapping>
- <servlet-name>sample</servlet-name>
- <url-pattern>*.form</url-pattern>
- </servlet-mapping>
-
- <!-- maps the sample dispatcher to *.html -->
- <servlet-mapping>
- <servlet-name>sample</servlet-name>
- <url-pattern>*.html</url-pattern>
- </servlet-mapping>
- ...
-</web-app>
-
- The above web.xml configuration snippet enables
- all requests ending with .html and .form to be
- handled by the sample dispatcher servlet.
-
- <beans>
-
- <!-- no 'id' required, HandlerMapping beans are automatically detected by the DispatcherServlet -->
- <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
- <property name="mappings">
- <value>
- /*/account.form=editAccountFormController
- /*/editaccount.form=editAccountFormController
- /ex/view*.html=helpController
- /**/help.html=helpController
- </value>
- </property>
- </bean>
-
- <bean id="helpController"
- class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
-
- <bean id="editAccountFormController"
- class="org.springframework.web.servlet.mvc.SimpleFormController">
- <property name="formView" value="account"/>
- <property name="successView" value="account-created"/>
- <property name="commandName" value="Account"/>
- <property name="commandClass" value="samples.Account"/>
- </bean>
-<beans>
-
- This handler mapping routes requests for
- 'help.html' in any directory to the
- 'helpController', which is a
- UrlFilenameViewController (more about controllers
- can be found in the section entitled ).
- Requests for a resource beginning with 'view', and
- ending with '.html' in the directory
- 'ex' will be routed to the
- 'helpController'. Two further mappings are also
- defined for 'editAccountFormController'.
-
+]]>
Intercepting requests - the
@@ -1536,6 +1837,15 @@ public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter {
FreeMarkerView respectively and custom
subclasses of them.
+
+
+ ContentNegotiatingViewResolver
+
+ An implementation of the ViewResolver
+ interface that that resolves a view based on the request file name or Accept header.
+ See .
+
+
@@ -1757,6 +2067,156 @@ public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter {
happening in terms of handling the response.
+
+
+ ContentNegotiatingViewResolver
+
+ The ContentNegotiatingViewResolver
+ does not resolve views itself, but rather delegates to other
+ view resolvers, selecting the view that resembles the representation
+ requested by the client.
+ There are two strategies for a client to inform the server of
+ the representation it is interested in receiving.
+
+ The first strategy is to use a distinct URI for each resource.
+ This is typically done by using a different file extension in the URI.
+ For example the URI
+ http://www.example.com/users/fred.pdf requests a PDF
+ representation of the user fred while
+ http://www.example.com/users/fred.xml requests an XML
+ representation.
+
+ The second strategy is for the client to use the same URI to
+ locate the resource but set the Accept HTTP request
+ header to list the media
+ types that it understands. For example, a HTTP request for
+ http://www.example.com/users/fred with an
+ Accept header set to application/pdf
+ requests a PDF representation of the user fred while
+ http://www.example.com/users/fred with an
+ Accept header set to text/xml
+ requests an XML representation. This strategy is known as content
+ negotiation.
+
+
+ One issue with the Accept header is that is impossible to change
+ it in a web browser, in HTML. For instance, in Firefox, it's fixed
+ to
+
+ Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+
+
+ For this reason it is common to see the use of a distinct URI
+ for each representation.
+
+
+ To support multiple representations of a resource Spring provides
+ the ContentNegotiatingViewResolver to resolve a
+ view based on the file extension or Accept header of
+ the HTTP request. ContentNegotiatingViewResolver
+ does not perform the view resolution itself, but instead delegates to a
+ list of view resolvers set using the bean property
+ ViewResolvers.
+
+ The ContentNegotiatingViewResolver selects
+ an appropriate View to handle the request by
+ comparing the request media type(s) with the media type (a.k.a.
+ Content-Type) supported by the
+ View associated with each of its
+ ViewResolvers. The first
+ View in the list that has a compatible
+ Content-Type is used to return the representation to
+ the client. The Accept header may include wild cards,
+ for example 'text/*', in which case a View whose
+ Context-Type was 'text/xml' is a compatible match.
+
+ To support the resolution of a view based on a file extension,
+ ContentNegotiatingViewResolver's bean property
+ MediaTypes is used to specify a mapping of file
+ extensions to media types. For more information on the algorithm to
+ determine the request media type, refer to the API documentation for
+ ContentNegotiatingViewResolver..
+
+ Here is an example configuration of a
+ ContentNegotiatingViewResolver
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ The InternalResourceViewResolver handles
+ the translation of view names and JSP pages while the
+ BeanNameViewResolver returns a view based on the
+ name of a bean. (See "Resolving views - the ViewResolver
+ interface" for more details on how Spring looks up and
+ instantiates a view.) In this example, the content
+ bean is a class that inherits from
+ AbstractAtomFeedView which returns an Atom RSS
+ feed. For more information on creating an Atom Feed representation see
+ the section 'Atom Views'.
+
+ In this configuration, if a request is made with a .html extension
+ the view resolver will look for a view that matches the text/html media
+ type. The InternalResourceViewResolver provides
+ the matching view for text/html. If the request is made with the file
+ extension .atom, the view resolver will look for a view that matches the
+ application/atom+xml media type. This view is provided by the
+ BeanNameViewResolver that maps to the
+ SampleContentAtomView if the view name returned
+ is 'content'. Alternatively, client requests could be made without a
+ file extension and setting the Accept header to the preferred media-type
+ and the same resolution of request to views would occur.
+
+
+ If ContentNegotiatingViewResolver's list
+ of ViewResolvers is not configured explicitly, then it will
+ automatically use any ViewResolvers defined in the application
+ context.
+
+
+ The corresponding controller code that returns an Atom RSS feed
+ for a URI of the form http://localhost/content.atom
+ or http://localhost/content with an
+ Accept header of application/atom+xml is shown
+ below
+
+ @Controller
+ public class ContentController {
+
+ private List<SampleContent> contentList = new ArrayList<SampleContent>();
+
+ @RequestMapping(value="/content", method=RequestMethod.GET)
+ public ModelAndView getContent() {
+ ModelAndView mav = new ModelAndView();
+ mav.setViewName("content");
+ mav.addObject("sampleContentList", contentList);
+ return mav;
+ }
+
+ }
+
+
+
@@ -2059,9 +2519,9 @@ background=/themes/cool/img/coolBg.jpg
package. Out of the box, Spring provides a
MultipartResolver for use with
Commons FileUpload ().
- How uploading files is supported will be described in the rest of
- this chapter.
+ url="http://jakarta.apache.org/commons/fileupload">). How
+ uploading files is supported will be described in the rest of this
+ chapter.
By default, no multipart handling will be done by Spring, as some
developers will want to handle multiparts themselves. You will have to
@@ -2686,680 +3146,6 @@ public class FileUploadBean {
-
- Annotation-based controller configuration
-
- There is a current trend to favor annotations over XML files for
- some types of configuration data. To facilitate this, Spring is now (since
- 2.5) providing support for configuring the MVC framework components using
- annotations.
-
- Spring 2.5 introduces an annotation-based programming model for MVC
- controllers, using annotations such as
- @RequestMapping,
- @RequestParam,
- @ModelAttribute, etc. This annotation
- support is available for both Servlet MVC and Portlet MVC. Controllers
- implemented in this style do not have to extend specific base classes or
- implement specific interfaces. Furthermore, they do not usually have
- direct dependencies on Servlet or Portlet API's, although they can easily
- get access to Servlet or Portlet facilities if desired.
-
-
- The Spring distribution ships with the
- PetClinic sample, which is a web application that takes
- advantage of the annotation support described in this section, in the context
- of simple form processing. You can find the PetClinic
- application in the 'samples/petclinic' directory.
-
- For a further sample application that builds on annotation-based Web MVC,
- check out imagedb. The focus in that sample is on stateless
- multi-action controllers, including the processing of multipart file uploads.
- You can find the imagedb application in the
- 'samples/imagedb' directory.
-
-
- The following sections document these annotations and how they are
- most commonly used in a Servlet environment.
-
-
- Setting up the dispatcher for annotation support
-
- @RequestMapping will only be processed
- if a corresponding HandlerMapping (for type level annotations)
- and/or HandlerAdapter (for method level annotations) is
- present in the dispatcher. This is the case by default in both
- DispatcherServlet and DispatcherPortlet.
-
- However, if you are defining custom HandlerMappings or
- HandlerAdapters, then you need to make sure that a
- corresponding custom DefaultAnnotationHandlerMapping
- and/or AnnotationMethodHandlerAdapter is defined as well
- - provided that you intend to use @RequestMapping.
-
- <?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
- 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-3.0.xsd">
-
- <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
-
- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
-
- // ... (controller bean definitions) ...
-
-</beans>
-
-
- Defining a DefaultAnnotationHandlerMapping
- and/or AnnotationMethodHandlerAdapter explicitly
- also makes sense if you would like to customize the mapping strategy,
- e.g. specifying a custom PathMatcher or
- WebBindingInitializer (see below).
-
-
-
- Defining a controller with
- @Controller
-
- The @Controller annotation indicates
- that a particular class serves the role of a controller.
- There is no need to extend any controller base class or reference the
- Servlet API. You are of course still able to reference Servlet-specific
- features if you need to.
-
- The basic purpose of the @Controller
- annotation is to act as a stereotype for the annotated class, indicating
- its role. The dispatcher will scan such annotated classes for mapped
- methods, detecting @RequestMapping
- annotations (see the next section).
-
- Annotated controller beans may be defined explicitly,
- using a standard Spring bean definition in the dispatcher's context.
- However, the @Controller stereotype also
- allows for autodetection, aligned with Spring 2.5's general support for
- detecting component classes in the classpath and auto-registering bean
- definitions for them.
-
- To enable autodetection of such annotated controllers, you have to add
- component scanning to your configuration. This is easily achieved by using
- the spring-context schema as shown in the following
- XML snippet:
-
- <?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.0.xsd">
-
- <context:component-scan base-package="org.springframework.samples.petclinic.web"/>
-
- // ...
-
-</beans>
-
-
-
- Mapping requests with
- @RequestMapping
-
- The @RequestMapping annotation is used
- to map URLs like '/editPet.do' onto an entire class or a particular handler method.
- Typically the type-level annotation maps a specific request path (or path pattern)
- onto a form controller, with additional method-level annotations 'narrowing' the
- primary mapping for a specific HTTP method request method ("GET"/"POST") or
- specific HTTP request parameters.
-
-
- @RequestMapping at the type
- level may be used for plain implementations of the
- Controller interface as well.
- In this case, the request processing code would follow the
- traditional handleRequest signature,
- while the controller's mapping would be expressed through an
- @RequestMapping annotation.
- This works for pre-built Controller
- base classes, such as SimpleFormController,
- too.
-
- In the following discussion, we'll focus on controllers
- that are based on annotated handler methods.
-
-
- The following is an example of a form controller from the
- PetClinic sample application using this annotation:
-
- @Controller
-@RequestMapping("/editPet.do")
-@SessionAttributes("pet")
-public class EditPetForm {
-
- private final Clinic clinic;
-
- @Autowired
- public EditPetForm(Clinic clinic) {
- this.clinic = clinic;
- }
-
- @ModelAttribute("types")
- public Collection<PetType> populatePetTypes() {
- return this.clinic.getPetTypes();
- }
-
- @RequestMapping(method = RequestMethod.GET)
- public String setupForm(@RequestParam("petId") int petId, ModelMap model) {
- Pet pet = this.clinic.loadPet(petId);
- model.addAttribute("pet", pet);
- return "petForm";
- }
-
- @RequestMapping(method = RequestMethod.POST)
- public String processSubmit(
- @ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) {
-
- new PetValidator().validate(pet, result);
- if (result.hasErrors()) {
- return "petForm";
- }
- else {
- this.clinic.storePet(pet);
- status.setComplete();
- return "redirect:owner.do?ownerId=" + pet.getOwner().getId();
- }
- }
-}
-
- For a traditional multi-action controller the URLs are typically
- mapped directly on the methods since the controller responds to multiple
- URLs. The following is an example of a multi-action controller from the
- PetClinic sample application using
- @RequestMapping:
-
- @Controller
-public class ClinicController {
-
- private final Clinic clinic;
-
- @Autowired
- public ClinicController(Clinic clinic) {
- this.clinic = clinic;
- }
-
- /**
- * Custom handler for the welcome view.
- * Note that this handler relies on the RequestToViewNameTranslator to
- * determine the logical view name based on the request URL: "/welcome.do"
- * -> "welcome".
- */
- @RequestMapping("/welcome.do")
- public void welcomeHandler() {
- }
-
- /**
- * Custom handler for displaying vets.
- * Note that this handler returns a plain {@link ModelMap} object instead of
- * a ModelAndView, thus leveraging convention-based model attribute names.
- * It relies on the RequestToViewNameTranslator to determine the logical
- * view name based on the request URL: "/vets.do" -> "vets".
- * @return a ModelMap with the model attributes for the view
- */
- @RequestMapping("/vets.do")
- public ModelMap vetsHandler() {
- return new ModelMap(this.clinic.getVets());
- }
-
- /**
- * Custom handler for displaying an owner.
- * Note that this handler returns a plain {@link ModelMap} object instead of
- * a ModelAndView, thus leveraging convention-based model attribute names.
- * It relies on the RequestToViewNameTranslator to determine the logical
- * view name based on the request URL: "/owner.do" -> "owner".
- * @param ownerId the ID of the owner to display
- * @return a ModelMap with the model attributes for the view
- */
- @RequestMapping("/owner.do")
- public ModelMap ownerHandler(@RequestParam("ownerId") int ownerId) {
- return new ModelMap(this.clinic.loadOwner(ownerId));
- }
-}
-
-
- Advanced @RequestMapping options
-
- Ant-style path patterns are supported (e.g. "/myPath/*.do").
- At the method level, relative paths (e.g. "edit.do") are supported
- within the primary mapping expressed at the type level.
-
- 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).
- 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.
-
- 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.
-
- Path mappings can be narrowed 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.
- "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.
-
-
-
-
- Supported handler method arguments and return types
-
- Handler methods which are annotated with
- @RequestMapping are allowed to have very flexible
- signatures. They may have arguments of the following types, in arbitrary
- order (except for validation results, which need to follow right after
- the corresponding command object, if desired):
-
-
-
- Request and/or response objects (Servlet API). You may choose any
- specific request/response type, e.g. ServletRequest /
- HttpServletRequest.
-
-
-
- Session object (Servlet API): of type HttpSession.
- An argument of this type will enforce the presence of a corresponding session.
- As a consequence, such an argument will never be null.
- Note that session access may not be thread-safe, in particular
- in a Servlet environment: Consider switching the
- AnnotationMethodHandlerAdapter's
- "synchronizeOnSession" flag to "true" if multiple requests are allowed
- to access a session concurrently.
-
-
-
- org.springframework.web.context.request.WebRequest
- or org.springframework.web.context.request.NativeWebRequest.
- Allows for generic request parameter access as well as request/session
- attribute access, without ties to the native Servlet/Portlet API.
-
-
-
- java.util.Locale for the current request
- locale (determined by the most specific locale resolver available,
- i.e. the configured LocaleResolver
- in a Servlet environment).
-
-
-
- java.io.InputStream /
- java.io.Reader for access to the request's content.
- This will be the raw InputStream/Reader as exposed by the Servlet API.
-
-
-
- java.io.OutputStream /
- java.io.Writer for generating the response's content.
- This will be the raw OutputStream/Writer as exposed by the Servlet API.
-
-
-
- @RequestParam annotated parameters
- for access to specific Servlet request parameters. Parameter values
- will be converted to the declared method argument type.
-
-
-
- java.util.Map /
- org.springframework.ui.Model /
- org.springframework.ui.ModelMap for
- enriching the implicit model that will be exposed to the web view.
-
-
-
- Command/form objects to bind parameters to: as bean
- properties or fields, with customizable type conversion, depending
- on @InitBinder methods and/or the
- HandlerAdapter configuration - see the
- "webBindingInitializer" property on
- AnnotationMethodHandlerAdapter. 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 (e.g. "orderAddress" for
- type "mypackage.OrderAddress"). Specify a parameter-level
- ModelAttribute annotation for declaring a
- specific model attribute name.
-
-
-
- org.springframework.validation.Errors /
- org.springframework.validation.BindingResult
- validation results for a preceding command/form object (the
- immediate preceding argument).
-
-
-
- org.springframework.web.bind.support.SessionStatus
- status handle for marking form processing as complete (triggering
- the cleanup of session attributes that have been indicated by the
- @SessionAttributes annotation at the
- handler type level).
-
-
-
- The following return types are supported for handler methods:
-
-
-
- A ModelAndView object, with the model implicitly
- enriched with command objects and the results of @ModelAttribute
- annotated reference data accessor methods.
-
-
-
- A Model object, with the view name implicitly
- determined through a RequestToViewNameTranslator
- and the model implicitly enriched with command objects and the results of
- @ModelAttribute annotated reference data accessor methods.
-
-
-
- A Map object for exposing a model, with the view name
- implicitly determined through a RequestToViewNameTranslator
- and the model implicitly enriched with command objects and the results of
- @ModelAttribute annotated reference data accessor methods.
-
-
-
- A View object, with the model implicitly
- determined through command objects and @ModelAttribute
- annotated reference data accessor methods. The handler method may also
- programmatically enrich the model by declaring a Model
- argument (see above).
-
-
-
- A String value which is interpreted as view name,
- with the model implicitly determined through command objects and
- @ModelAttribute annotated reference data accessor methods.
- The handler method may also programmatically enrich the model by declaring a
- Model argument (see above).
-
-
-
- void if the method handles the response itself
- (by writing the response content directly, declaring an argument of type
- ServletResponse /
- HttpServletResponse for that purpose)
- or if the view name is supposed to be implicitly determined through a
- RequestToViewNameTranslator
- (not declaring a response argument in the handler method signature).
-
-
-
- Any other return type will be considered as single model attribute
- to be exposed to the view, using the attribute name specified through
- @ModelAttribute at the method level (or the default
- attribute name based on the return type's class name otherwise). The model
- will be implicitly enriched with command objects and the results of
- @ModelAttribute annotated reference data accessor methods.
-
-
-
-
-
- Binding request parameters to method parameters with
- @RequestParam
-
- The @RequestParam annotation is used to
- bind request parameters to a method parameter in your controller.
-
- The following code snippet from the PetClinic sample application
- shows the usage:
-
- @Controller
-@RequestMapping("/editPet.do")
-@SessionAttributes("pet")
-public class EditPetForm {
-
- // ...
-
- @RequestMapping(method = RequestMethod.GET)
- public String setupForm(@RequestParam("petId") int petId, ModelMap model) {
- Pet pet = this.clinic.loadPet(petId);
- model.addAttribute("pet", pet);
- return "petForm";
- }
-
- // ...
-
-
- Parameters using this annotation are required by default, but you
- can specify that a parameter is optional by setting
- @RequestParam's
- required attribute to false (e.g.,
- @RequestParam(value="id", required="false")).
-
-
-
- Providing a link to data from the model with
- @ModelAttribute
-
- @ModelAttribute has two usage scenarios in
- controllers. When placed on a method parameter,
- @ModelAttribute is used to map a model attribute
- to the specific, annotated method parameter (see the
- processSubmit() method below). This is how the
- controller gets a reference to the object holding the data entered in
- the form. In addition, the parameter can be declared as the specific
- type of the form backing object rather than as a generic
- java.lang.Object, thus increasing type
- safety.
-
- @ModelAttribute is also used at the method
- level to provide reference data for the model (see
- the populatePetTypes() method below). For this usage
- the method signature can contain the same types as documented above for
- the @RequestMapping annotation.
-
- Note:@ModelAttribute
- annotated methods will be executed before the
- chosen @RequestMapping annotated handler method.
- They effectively pre-populate the implicit model with specific attributes,
- often loaded from a database. Such an attribute can then already be
- accessed through @ModelAttribute annotated
- handler method parameters in the chosen handler method, potentially
- with binding and validation applied to it.
-
- The following code snippet shows these two usages of this
- annotation:
-
- @Controller
-@RequestMapping("/editPet.do")
-@SessionAttributes("pet")
-public class EditPetForm {
-
- // ...
-
- @ModelAttribute("types")
- public Collection<PetType> populatePetTypes() {
- return this.clinic.getPetTypes();
- }
-
- @RequestMapping(method = RequestMethod.POST)
- public String processSubmit(
- @ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) {
-
- new PetValidator().validate(pet, result);
- if (result.hasErrors()) {
- return "petForm";
- }
- else {
- this.clinic.storePet(pet);
- status.setComplete();
- return "redirect:owner.do?ownerId=" + pet.getOwner().getId();
- }
- }
-}
-
-
-
- Specifying attributes to store in a Session with
- @SessionAttributes
-
- The type-level @SessionAttributes
- annotation declares session attributes used by a specific handler. This
- will typically list the names of model attributes which should be
- transparently stored in the session or some conversational storage,
- serving as form-backing beans between subsequent requests.
-
- The following code snippet shows the usage of this
- annotation:
-
- @Controller
-@RequestMapping("/editPet.do")
-@SessionAttributes("pet")
-public class EditPetForm {
- // ...
-}
-
-
-
- Mapping cookie values with the @CookieValue annotation
-
- The @CookieValue annotation allows a method parameter to be bound to the value of an HTTP cookie.
-
-
- Let us consider that the following cookie has been received with an http request:
- JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84
- The following code sample allows you to easily get the value of the "JSESSIONID"cookie:
- @RequestMapping("/displayHeaderInfo.do")
-public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie) {
-
- //...
-
-}
- This annotation is supported for annotated handler methods in Servlet and Portlet environments.
-
-
-
- Mapping request header attributes with the @RequestHeader annotation
-
- The @RequestHeader annotation allows a method parameter to be bound to a request header.
-
-
- Here is a request header sample:
-
- The following code sample allows you to easily get the value of the "Accept-Encoding" and "Keep-Alive" headers:
- @RequestMapping("/displayHeaderInfo.do")
- public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding,
- @RequestHeader("Keep-Alive") long keepAlive) {
-
- //...
-
-}
- This annotation is supported for annotated handler methods in Servlet and Portlet environments.
-
-
-
-
- Customizing WebDataBinder
- initialization
-
- To customize request parameter binding with PropertyEditors, etc.
- via Spring's WebDataBinder, you can either use
- @InitBinder-annotated methods within your
- controller or externalize your configuration by providing a custom
- WebBindingInitializer.
-
-
- Customizing data binding with
- @InitBinder
-
- Annotating controller methods with
- @InitBinder allows you to configure web
- data binding directly within your controller class.
- @InitBinder identifies methods which
- initialize the WebDataBinder which will be used
- for populating command and form object arguments of annotated handler
- methods.
-
- Such init-binder methods support all arguments that
- @RequestMapping supports, except for
- command/form objects and corresponding validation result objects.
- Init-binder methods must not have a return value. Thus, they are
- usually declared as void. Typical arguments include
- WebDataBinder in combination with
- WebRequest or
- java.util.Locale, allowing code to register
- context-specific editors.
-
- The following example demonstrates the use of
- @InitBinder for configuring a
- CustomDateEditor for all
- java.util.Date form properties.
-
- @Controller
-public class MyFormController {
-
- @InitBinder
- public void initBinder(WebDataBinder binder) {
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
- dateFormat.setLenient(false);
- binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
- }
-
- // ...
-}
-
-
-
- Configuring a custom
- WebBindingInitializer
-
- To externalize data binding initialization, you can provide a
- custom implementation of the
- WebBindingInitializer interface, which
- you then enable by supplying a custom bean configuration for an
- AnnotationMethodHandlerAdapter, thus overriding
- the default configuration.
-
- The following example from the PetClinic application shows a
- configuration using a custom implementation of the
- WebBindingInitializer interface,
- org.springframework.samples.petclinic.web.ClinicBindingInitializer,
- which configures PropertyEditors required by several of the PetClinic
- controllers.
-
- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
- <property name="cacheSeconds" value="0" />
- <property name="webBindingInitializer">
- <bean class="org.springframework.samples.petclinic.web.ClinicBindingInitializer" />
- </property>
-</bean>
-
-
-
-
-
Further Resources
@@ -3373,15 +3159,15 @@ public class MyFormController {
MVC-based application using a step-by-step approach. This tutorial is
available in the 'docs' directory of the Spring
distribution. An online version can also be found on the Spring Framework website.
+ url="http://springframework.org/">Spring Framework
+ website.
- The book entitled Expert Spring Web MVC and
- Web Flow by Seth Ladd and others (published by Apress) is an
+ The book entitled Expert Spring Web MVC and Web
+ Flow by Seth Ladd and others (published by Apress) is an
excellent hardcopy source of Spring Web MVC goodness.
-
-
\ No newline at end of file
+
diff --git a/spring-framework-reference/src/remoting.xml b/spring-framework-reference/src/remoting.xml
index 6570e28d35e..bfb70195c04 100644
--- a/spring-framework-reference/src/remoting.xml
+++ b/spring-framework-reference/src/remoting.xml
@@ -68,7 +68,7 @@
While discussing the remoting capabilities of Spring, we'll use the
following domain model and corresponding services:
- public class Account implements Serializable{
private String name;
@@ -79,21 +79,21 @@
public void setName(String name) {
this.name = name;
}
-}]]>
+}
- public interface AccountService {
public void insertAccount(Account account);
- public List getAccounts(String name);
-}]]>
+ public List<Account> getAccounts(String name);
+}
- public interface RemoteAccountService extends Remote {
public void insertAccount(Account account) throws RemoteException;
- public List getAccounts(String name) throws RemoteException;
-}]]>
+ public List<Account> getAccounts(String name) throws RemoteException;
+}
// the implementation doing nothing at the moment
public class AccountServiceImpl implements AccountService {
@@ -174,7 +174,7 @@ public class AccountServiceImpl implements AccountService {
Our client is a simple object using the
AccountService to manage accounts:
- public class SimpleObject {
private AccountService accountService;
@@ -184,20 +184,20 @@ public class AccountServiceImpl implements AccountService {
// additional methods using the accountService
-}]]>
+}To link in the service on the client, we'll create a separate
Spring container, containing the simple object and the service linking
configuration bits:
-
-
-
+ <bean class="example.SimpleObject">
+ <property name="accountService" ref="accountService"/>
+</bean>
-
-
-
-]]>
+<bean id="accountService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
+ <property name="serviceUrl" value="rmi://HOST:1199/AccountService"/>
+ <property name="serviceInterface" value="example.AccountService"/>
+</bean>That's all we need to do to support the remote account service on
the client. Spring will transparently create an invoker and remotely
@@ -225,16 +225,16 @@ public class AccountServiceImpl implements AccountService {
application (this an excerpt from
'web.xml'):
-
- remoting
- org.springframework.web.servlet.DispatcherServlet
- 1
-
+ <servlet>
+ <servlet-name>remoting</servlet-name>
+ <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+</servlet>
-
- remoting
- /remoting/*
-]]>
+<servlet-mapping>
+ <servlet-name>remoting</servlet-name>
+ <url-pattern>/remoting/*</url-pattern>
+</servlet-mapping>You're probably familiar with Spring's
DispatcherServlet principles and if so, you know
@@ -284,10 +284,10 @@ public class AccountServiceImpl implements AccountService {
context (e.g. in
'WEB-INF/applicationContext.xml'):
-
-
-
-]]>
+ <bean name="accountExporter" class="org.springframework.remoting.caucho.HessianServiceExporter">
+ <property name="service" ref="accountService"/>
+ <property name="serviceInterface" value="example.AccountService"/>
+</bean>In the latter case, define a corresponding servlet for this
exporter in 'web.xml', with the same end result:
@@ -295,15 +295,15 @@ public class AccountServiceImpl implements AccountService {
/remoting/AccountService. Note that the servlet name
needs to match the bean name of the target exporter.
-
- accountExporter
- org.springframework.web.context.support.HttpRequestHandlerServlet
-
+ <servlet>
+ <servlet-name>accountExporter</servlet-name>
+ <servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
+</servlet>
-
- accountExporter
- /remoting/AccountService
-]]>
+<servlet-mapping>
+ <servlet-name>accountExporter</servlet-name>
+ <url-pattern>/remoting/AccountService</url-pattern>
+</servlet-mapping>
@@ -316,14 +316,14 @@ public class AccountServiceImpl implements AccountService {
SimpleObject is using the
AccountService to manage accounts:
-
-
-
+ <bean class="example.SimpleObject">
+ <property name="accountService" ref="accountService"/>
+</bean>
-
-
-
-]]>
+<bean id="accountService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
+ <property name="serviceUrl" value="http://remotehost:8080/remoting/AccountService"/>
+ <property name="serviceInterface" value="example.AccountService"/>
+</bean>
@@ -349,14 +349,14 @@ public class AccountServiceImpl implements AccountService {
Hessian/BurlapProxyFactoryBean level (similar to a
JDBC DataSource).
-
-
-
+ <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
+ <property name="interceptors" ref="authorizationInterceptor"/>
+</bean>
-
-
-]]>
+<bean id="authorizationInterceptor"
+ class="org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor">
+ <property name="authorizedRoles" value="administrator,operator"/>
+</bean>This an example where we explicitly mention the
BeanNameUrlHandlerMapping and set an interceptor
@@ -405,11 +405,11 @@ public class AccountServiceImpl implements AccountService {
following configuration needs to be in place in the dispatcher's
application context:
-
-
-
-
-]]>
+ <bean name="/AccountService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
+ <property name="service" ref="accountService"/>
+ <property name="serviceInterface" value="example.AccountService"/>
+</bean>
+Such an exporter definition will be exposed through the
DispatcherServlet's standard mapping facilities,
@@ -420,46 +420,46 @@ public class AccountServiceImpl implements AccountService {
application context (e.g. in
'WEB-INF/applicationContext.xml'):
-
-
-
-]]>
+ <bean name="accountExporter" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
+ <property name="service" ref="accountService"/>
+ <property name="serviceInterface" value="example.AccountService"/>
+</bean>In addition, define a corresponding servlet for this exporter in
'web.xml', with the servlet name matching the bean
name of the target exporter:
-
- accountExporter
- org.springframework.web.context.support.HttpRequestHandlerServlet
-
+ <servlet>
+ <servlet-name>accountExporter</servlet-name>
+ <servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
+</servlet>
-
- accountExporter
- /remoting/AccountService
-]]>
+<servlet-mapping>
+ <servlet-name>accountExporter</servlet-name>
+ <url-pattern>/remoting/AccountService</url-pattern>
+</servlet-mapping>f you are running outside of a servlet container and are using
Sun's Java 6, then you can use the built-in HTTP server implementation.
You can configure the SimpleHttpServerFactoryBean together with a
SimpleHttpInvokerServiceExporter as is shown in this example:
-
-
-
-
+ <bean name="accountExporter"
+ class="org.springframework.remoting.httpinvoker.SimpleHttpInvokerServiceExporter">
+ <property name="service" ref="accountService"/>
+ <property name="serviceInterface" value="example.AccountService"/>
+</bean>
-
-
-
-
-
-
-
-
-]]>
+<bean id="httpServer"
+ class="org.springframework.remoting.support.SimpleHttpServerFactoryBean">
+ <property name="contexts">
+ <util:map>
+ <entry key="/remoting/AccountService" value-ref="accountExporter"/>
+ </util:map>
+ </property>
+ <property name="port" value="8080" />
+</bean>
+
@@ -470,11 +470,11 @@ public class AccountServiceImpl implements AccountService {
will be able to translate your calls to HTTP POST requests to the URL
pointing to the exported service.
-
-
-
-
-]]>
+ <bean id="httpInvokerProxy" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
+ <property name="serviceUrl" value="http://remotehost:8080/remoting/AccountService"/>
+ <property name="serviceInterface" value="example.AccountService"/>
+</bean>
+As mentioned before, you can choose what HTTP client you want to
use. By default, the HttpInvokerProxy uses the
@@ -482,10 +482,10 @@ public class AccountServiceImpl implements AccountService {
HttpClient by setting the
httpInvokerRequestExecutor property:
-
-
-
-]]>
+ <property name="httpInvokerRequestExecutor">
+ <bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"/>
+</property>
+
@@ -609,13 +609,13 @@ public class AccountServiceEndpoint extends ServletEndpointSupport implements Re
support for web services requiring little coding efforts - most of the
setup is done in the Spring configuration file as usual:
-
-
-
-
-
-
-]]>
+ <bean id="accountWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
+ <property name="serviceInterface" value="example.RemoteAccountService"/>
+ <property name="wsdlDocumentUrl" value="http://localhost:8080/account/services/accountService?WSDL"/>
+ <property name="namespaceUri" value="http://localhost:8080/account/services/accountService"/>
+ <property name="serviceName" value="AccountService"/>
+ <property name="portName" value="AccountPort"/>
+</bean>Where serviceInterface is our remote business
interface the clients will use. wsdlDocumentUrl is
@@ -631,10 +631,10 @@ public class AccountServiceEndpoint extends ServletEndpointSupport implements Re
RemoteAccountService interface. We can wire this up
in Spring:
-
+ <bean id="client" class="example.AccountClientImpl">
...
-
-]]>
+ <property name="service" ref="accountWebService"/>
+</bean>From the client code we can access the web service just as if it
was a normal class, except that it throws
@@ -665,18 +665,18 @@ public class AccountServiceEndpoint extends ServletEndpointSupport implements Re
RemoteException. This requires that we
provide a non-RMI interface also. Our configuration is now:
-
-
-
+ <bean id="accountWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
+ <property name="serviceInterface" value="example.AccountService"/>
+ <property name="portInterface" value="example.RemoteAccountService"/>
...
-]]>
+</bean>Where serviceInterface is changed to our non
RMI interface. Our RMI interface is now defined using the property
portInterface. Our client code can now avoid handling
java.rmi.RemoteException:
- public class AccountClientImpl {
private AccountService service;
@@ -687,7 +687,7 @@ public class AccountServiceEndpoint extends ServletEndpointSupport implements Re
public void foo() {
service.insertAccount(...);
}
-}]]>
+}
Note that you can also drop the "portInterface" part and specify a
plain business interface as "serviceInterface". In this case,
@@ -717,7 +717,7 @@ public class AccountServiceEndpoint extends ServletEndpointSupport implements Re
We will use Axis to register bean mappings on the client side. To
do this we need to register the bean mappings programmatically:
- public class AxisPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {
protected void postProcessJaxRpcService(Service service) {
TypeMappingRegistry registry = service.getTypeMappingRegistry();
@@ -732,7 +732,7 @@ public class AccountServiceEndpoint extends ServletEndpointSupport implements Re
new BeanSerializerFactory(type, qName),
new BeanDeserializerFactory(type, qName));
}
-}]]>
+}
@@ -747,7 +747,7 @@ public class AccountServiceEndpoint extends ServletEndpointSupport implements Re
javax.rpc.xml.handler.GenericHandler that we will
extend:
- public class AccountHandler extends GenericHandler {
public QName[] getHeaders() {
return null;
@@ -766,7 +766,7 @@ public class AccountServiceEndpoint extends ServletEndpointSupport implements Re
}
return true;
}
-}]]>
+}
What we need to do now is to register our AccountHandler to
JAX-RPC Service so it would invoke
@@ -777,7 +777,7 @@ public class AccountServiceEndpoint extends ServletEndpointSupport implements Re
override the postProcessJaxRpcService(..)
method that is designed for this:
- public class AccountHandlerJaxRpcPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {
protected void postProcessJaxRpcService(Service service) {
QName port = new QName(this.getNamespaceUri(), this.getPortName());
@@ -785,14 +785,14 @@ public class AccountServiceEndpoint extends ServletEndpointSupport implements Re
list.add(new HandlerInfo(AccountHandler.class, null, null));
logger.info("Registered JAX-RPC AccountHandler on port " + port);
}
-}]]>
+}
The last thing we must remember to do is to change the Spring
configuration to use our factory bean:
-
+ <bean id="accountWebService" class="example.AccountHandlerJaxRpcPortProxyFactoryBean">
...
-]]>
+</bean>
@@ -870,15 +870,15 @@ public class AccountServiceEndpoint extends SpringBeanAutowiringSupport {
injection through @Autowired will work as
well.
-
-
-
+ <bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter">
+ <property name="baseAddress" value="http://localhost:8080/"/>
+</bean>
-
+<bean id="accountServiceEndpoint" class="example.AccountServiceEndpoint">
...
-
+</bean>
-...]]>
+...The AccountServiceEndpoint may derive from
Spring's SpringBeanAutowiringSupport but doesn't
@@ -887,7 +887,7 @@ public class AccountServiceEndpoint extends SpringBeanAutowiringSupport {
any superclass declared - and Spring's @Autowired
configuration annotation still being honored:
- @WebService(serviceName="AccountService")
public class AccountServiceEndpoint {
@Autowired
@@ -899,10 +899,10 @@ public class AccountServiceEndpoint {
}
@WebMethod
- public List getAccounts(String name) {
+ public List<Account> getAccounts(String name) {
return biz.getAccounts(name);
}
-}]]>
+}
@@ -945,13 +945,13 @@ public class AccountServiceEndpoint {
a proxy for the AccountService endpoint
(again):
-
-
-
-
-
-
-]]>
+ <bean id="accountWebService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
+ <property name="serviceInterface" value="example.AccountService"/>
+ <property name="wsdlDocumentUrl" value="http://localhost:8888/AccountServiceEndpoint?WSDL"/>
+ <property name="namespaceUri" value="http://example/"/>
+ <property name="serviceName" value="AccountService"/>
+ <property name="portName" value="AccountServiceEndpointPort"/>
+</bean>Where serviceInterface is our business
interface the clients will use. wsdlDocumentUrl is
@@ -966,15 +966,15 @@ public class AccountServiceEndpoint {
factory for it that will expose it as AccountService
interface. We can wire this up in Spring:
-
+ <bean id="client" class="example.AccountClientImpl">
...
-
-]]>
+ <property name="service" ref="accountWebService"/>
+</bean>From the client code we can access the web service just as if it
was a normal class:
- public class AccountClientImpl {
private AccountService service;
@@ -985,7 +985,7 @@ public class AccountServiceEndpoint {
public void foo() {
service.insertAccount(...);
}
-}]]>
+}
NOTE: The above is slightly simplified in
that JAX-WS requires endpoint interfaces and implementation classes to
@@ -1008,10 +1008,10 @@ public class AccountServiceEndpoint {
WebApplicationContext containing the
services you will be exposing:
-
- xfire
- org.springframework.web.servlet.DispatcherServlet
-]]>
+ <servlet>
+ <servlet-name>xfire</servlet-name>
+ <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+</servlet>You also have to link in the XFire configuration. This is done by
adding a context file to the contextConfigLocations
@@ -1019,14 +1019,14 @@ public class AccountServiceEndpoint {
ContextLoaderListener (or
ContextLoaderServlet for that matter).
-
- contextConfigLocation
- classpath:org/codehaus/xfire/spring/xfire.xml
-
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>classpath:org/codehaus/xfire/spring/xfire.xml</param-value>
+</context-param>
-
- org.springframework.web.context.ContextLoaderListener
-]]>
+<listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+</listener>After you added a servlet mapping (mapping /*
to the XFire servlet declared above) you only have to add one extra bean
@@ -1068,43 +1068,43 @@ public class AccountServiceEndpoint {
The following interface is used on both the server and the client
side.
- package com.foo;
public interface CheckingAccountService {
public void cancelAccount(Long accountId);
-}]]>
+}
The following simple implementation of the above interface is used
on the server-side.
- package com.foo;
public class SimpleCheckingAccountService implements CheckingAccountService {
public void cancelAccount(Long accountId) {
System.out.println("Cancelling account [" + accountId + "]");
}
-}]]>
+}
This configuration file contains the JMS-infrastructure beans that
are shared on both the client and server.
-
-<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
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-3.0.xsd">
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
-
-
-
+ <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
+ <property name="brokerURL" value="tcp://ep-t43:61616"/>
+ </bean>
-
-
-
+ <bean id="queue" class="org.apache.activemq.command.ActiveMQQueue">
+ <constructor-arg value="mmm"/>
+ </bean>
-]]>
+</beans>
Server-side configuration
@@ -1112,30 +1112,30 @@ public class SimpleCheckingAccountService implements CheckingAccountService {
On the server, you just need to expose the service object using
the JmsInvokerServiceExporter.
-
-<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
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-3.0.xsd">
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
-
-
-
-
-
-
+ <bean id="checkingAccountService"
+ class="org.springframework.jms.remoting.JmsInvokerServiceExporter">
+ <property name="serviceInterface" value="com.foo.CheckingAccountService"/>
+ <property name="service">
+ <bean class="com.foo.SimpleCheckingAccountService"/>
+ </property>
+ </bean>
-
-
-
-
-
-
+ <bean class="org.springframework.jms.listener.SimpleMessageListenerContainer">
+ <property name="connectionFactory" ref="connectionFactory"/>
+ <property name="destination" ref="queue"/>
+ <property name="concurrentConsumers" value="3"/>
+ <property name="messageListener" ref="checkingAccountService"/>
+ </bean>
-]]>
+</beans>
- package com.foo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@@ -1144,7 +1144,7 @@ public class Server {
public static void main(String[] args) throws Exception {
new ClassPathXmlApplicationContext(new String[]{"com/foo/server.xml", "com/foo/jms.xml"});
}
-}]]>
+}
@@ -1157,22 +1157,22 @@ public class Server {
injected into other client side objects, and the proxy will take care of
forwarding the call to the server-side object via JMS.
-
-<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
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-3.0.xsd">
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
-
-
-
-
-
+ <bean id="checkingAccountService"
+ class="org.springframework.jms.remoting.JmsInvokerProxyFactoryBean">
+ <property name="serviceInterface" value="com.foo.CheckingAccountService"/>
+ <property name="connectionFactory" ref="connectionFactory"/>
+ <property name="queue" ref="queue"/>
+ </bean>
-]]>
+</beans>
- package com.foo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@@ -1185,7 +1185,7 @@ public class Client {
CheckingAccountService service = (CheckingAccountService) ctx.getBean("checkingAccountService");
service.cancelAccount(new Long(10));
}
-}]]>
+}
You may also wish to investigate the support provided by the
-
\ No newline at end of file
+
+
+ Accessing RESTful services on the Client
+
+ The RestTemplate is the core class for
+ client-side access to RESTful services. It is conceptually similar to
+ other template classes in Spring, such as
+ JdbcTemplate and JmsTemplate
+ and other template classes found in other Spring portfolio projects.
+ RestTemplate's behavior is customized by providing
+ callback methods and configuring the
+ HttpMessageConverter used to marshal
+ objects into the HTTP request body and to unmarshall any response back
+ into an object. As it is common to use XML as a message format, Spring
+ provides a MarshallingHttpMessageConverter that
+ uses the Object-to-XML framework that is part of the
+ org.springframework.oxm package. This gives you a
+ wide range of choices of XML to Object mapping technologies to choose
+ from.
+
+ This section describes how to use the
+ RestTemplate and its associated
+ HttpMessageConverters.
+
+
+ RestTemplate
+
+ Invoking RESTful services in Java is typically done using a helper
+ class such as Jakarta Commons HttpClient. For
+ common REST operations this approach is too low level as shown
+ below.
+
+ String uri = "http://example.com/hotels/1/bookings";
+
+PostMethod post = new PostMethod(uri);
+String request = // create booking request content
+post.setRequestEntity(new StringRequestEntity(request));
+
+httpClient.executeMethod(post);
+
+if (HttpStatus.SC_CREATED == post.getStatusCode()) {
+ Header location = post.getRequestHeader("Location");
+ if (location != null) {
+ System.out.println("Created new booking at :" + location.getValue());
+ }
+}
+
+ RestTemplate provides higher level methods that correspond to each
+ of the six main HTTP methods that make invoking many RESTful services a
+ one-liner and enforce REST best practices.
+
+
+
+ The names of RestTemplate methods follow a
+ naming convention, the first part indicates what HTTP method is being
+ invoked and the second part indicates what is returned. For example, the
+ method getForObject will perform a GET, convert
+ the HTTP response into an object type of your choice and return that
+ object. The method postForLocation will do a
+ POST, converting the given object into a HTTP request and return the
+ response HTTP Location header where the newly created object can be
+ found In case of an exception processing the HTTP request, an exception
+ of the type RestClientException will be
+ thrown.
+
+ Objects passed to and returned from these methods are converted to
+ and from HTTP messages by
+ HttpMessageConverter instances.
+ Converters for the main mime types are registered by default, but you
+ can also write your own converter and register it via the
+ messageConverters bean property. The default
+ converter instances registered with the template are
+ ByteArrayHttpMessageConverter,
+ StringHttpMessageConverter,
+ FormHttpMessageConverter and
+ SourceHttpMessageConverter. You can override
+ these defaults using the messageConverters bean
+ property as would be required if using the
+ MarshallingHttpMessageConverter.
+
+ Each method takes URI template arguments in two forms, either as a
+ String variable length argument or a
+ Map<String,String>. For example,
+
+ String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}",
+ String.class,"42", "21");
+
+
+ using variable length arguments and
+
+ Map<String, String> vars = Collections.singletonMap("hotel", "42");
+String result =
+ restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
+
+
+ using a Map<String,String>.
+
+ To create an instance of RestTemplate you
+ can simply call the default constructor. This will use standard Java
+ classes from the java.net package as the underlying
+ implementation to create HTTP requests. This can be overridden by
+ specifying an implementation of
+ ClientHttpRequestFactory. Spring provides
+ the implementation
+ CommonsClientHttpRequestFactory that uses the
+ Jakarta Commons HttpClient to create requests.
+ CommonsClientHttpRequestFactory is configured
+ using an instance of
+ org.apache.commons.httpclient.HttpClient which
+ can in turn be configured with credentials information or connection
+ pooling functionality.
+
+ The previous example using Jakarta Commons
+ HttpClient directly rewritten to use the
+ RestTemplate is shown below
+
+ uri = "http://example.com/hotels/{id}/bookings";
+
+RestTemplate template = new RestTemplate();
+
+Booking booking = // create booking object
+
+URI location = template.postForLocation(uri, booking, "1");
+
+
+ The general callback interface is
+ RequestCallback and is called when the
+ execute method is invoked.
+
+ public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
+ ResponseExtractor<T> responseExtractor,
+ String... urlVariables)
+
+
+// also has an overload with urlVariables as a Map<String, String>.
+
+ The RequestCallback interface is
+ defined as
+
+ public interface RequestCallback {
+ void doWithRequest(ClientHttpRequest request) throws IOException;
+}
+
+ and allows you to manipulate the request headers and write to the
+ request body. When using the execute method you do not have to worry
+ about any resource management, the template will always close the
+ request and handle any errors. Refer to the API documentation for more
+ information on using the execute method and the meaning of its other
+ method arguments.
+
+
+
+ HTTP Message Conversion
+
+ Objects passed to and returned from the methods
+ getForObject,
+ postForLocation, and
+ put are converted to HTTP requests and from
+ HTTP responses by HttpMessageConverters.
+ The HttpMessageConverter interface is
+ shown below to give you a better feel for its functionality
+
+ public interface HttpMessageConverter<T> {
+
+ // Indicate whether the given class is supported by this converter.
+ boolean supports(Class<? extends T> clazz);
+
+ // Return the list of MediaType objects supported by this converter.
+ List<MediaType> getSupportedMediaTypes();
+
+ // Read an object of the given type form the given input message, and returns it.
+ T read(Class<T> clazz, HttpInputMessage inputMessage) throws IOException,
+ HttpMessageNotReadableException;
+
+ // Write an given object to the given output message.
+ void write(T t, HttpOutputMessage outputMessage) throws IOException,
+ HttpMessageNotWritableException;
+
+ }
+
+ Concrete implementations for the main media (mime) types are
+ provided in the framework and are registered by default with the
+ RestTemplate on the client-side and with
+ AnnotationMethodHandlerAdapter on the
+ server-side.
+
+ The implementations of
+ HttpMessageConverters are described in the
+ following sections. For all converters a default media type is used but
+ can be overridden by setting the
+ supportedMediaTypes bean property
+
+
+ StringHttpMessageConverter
+
+ An HttpMessageConverter
+ implementation that can read and write Strings from the HTTP request
+ and response. By default, this converter supports all text media types
+ (text/*), and writes with a
+ Content-Type of
+ text/plain.
+
+
+
+ FormHttpMessageConverter
+
+ An HttpMessageConverter
+ implementation that can read and write form data from the HTTP request
+ and response. By default, this converter reads and writes the media
+ type application/x-www-form-urlencoded. Form data
+ is read from and written into a MultiValueMap<String,
+ String>.
+
+
+
+ ByteArrayMessageConverter
+
+ An HttpMessageConverter
+ implementation that can read and write byte arrays from the HTTP
+ request and response. By default, this converter supports all media
+ types (*/*), and writes with a
+ Content-Type of
+ application/octet-stream. This can be overridden by
+ setting the supportedMediaTypes property, and
+ overriding getContentType(byte[]).
+
+
+
+ MarshallingHttpMessageConverter
+
+ An HttpMessageConverter
+ implementation that can read and write XML using Spring's
+ Marshaller and
+ Unmarshaller abstractions from the
+ org.springframework.oxm package. This converter
+ requires a Marshaller and
+ Unmarshaller before it can be used.
+ These can be injected via constructor or bean properties. By default
+ this converter supports (text/xml) and
+ (application/xml).
+
+
+
+ SourceHttpMessageConverter
+
+ An HttpMessageConverter
+ implementation that can read and write
+ javax.xml.transform.Source from the HTTP
+ request and response. Only DOMSource,
+ SAXSource, and
+ StreamSource are supported. By default, this
+ converter supports (text/xml) and
+ (application/xml).
+
+
+
+ BufferedImageHttpMessageConverter
+
+ An HttpMessageConverter
+ implementation that can read and write
+ java.awt.image.BufferedImage from the HTTP
+ request and response. This converter reads and writes the media type
+ supported by the Java I/O API.
+
+
+
+
diff --git a/spring-framework-reference/src/rest.xml b/spring-framework-reference/src/rest.xml
index e6d33dadcc9..91d9f837ecc 100644
--- a/spring-framework-reference/src/rest.xml
+++ b/spring-framework-reference/src/rest.xml
@@ -38,368 +38,6 @@
configuration to understand the general programming model.
-
- Creating RESTful services
-
- Spring's annotation-based MVC framework serves as the basis for
- creating RESTful Web Services. As such, you configure your servlet
- container as you would for a Spring MVC application using Spring's DispatcherServlet.
-
-
- URI Templates
-
- RESTful services use URIs to name resources. To facilitate
- accessing the information contained in a URI, its structure follows
- conventions so that it can easily be described in a parameterized form.
- The proposed
- RFC for URI Templates defines how an 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", then 'expanding' the URI Template gives.
-
- http://www.example.com/users/fred
-
- When processing a request the URI can be compared to an expected
- URI Template in order to extract a collection of variables.
-
- Spring uses the @RequestMapping method
- annotation to define the URI Template for the request. The
- @PathVariable annotation is used to extract the
- value of the template variables and assign their value to a method
- variable. A Spring controller method to process above example is shown
- below;
-
- @RequestMapping(value="/users/{userId}", method=RequestMethod.GET)
-public String getUser(@PathVariable String userId) {
- // implementation omitted...
-}
-
- The request http://www.example.com/users/fred
- will bind the userId method parameter to the String value 'fred'.
-
-
- Mapping RESTful URLs with the @PathVariable annotation
-
- The @PathVariable method parameter
- annotation is used to indicate that a method parameter should be bound
- to the value of a URI template variable.
-
- The following code snippet shows the use of a single
- @PathVariable in a controller method:
-
- @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
-public String findOwner(@PathVariable String ownerId, Model model) {
- Owner owner = ownerService.findOwner(ownerId);
- model.addAttribute("owner", owner);
- return "displayOwner";
-}
-
-
- The URI Template "/owners/{ownerId}"
- specifies the variable name ownerId. When the controller handles this
- request, the value of ownerId is set 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 have not debugging enabled, you must specify the
- name of the URI Template variable name to bind to in the @PathVariable
- annotation. For example
-
- @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
-public String findOwner(@PathVariable("ownerId") String ownerId, Model model) {
- // implementation omitted
-}
-
-
- The name of the method parameter does not matter in this case,
- so you may also use a controller method with the signature shown
- below
-
- @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
-public String findOwner(@PathVariable("ownerId") String theOwner, Model model) {
- // implementation omitted
-}
-
- Multiple @PathVariable annotations can be used to bind to
- multiple URI Template variables as shown below:
-
- @RequestMapping(value="/owners/{ownerId}/pets/{petId}", method=RequestMethod.GET)
-public String findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
- Owner owner = ownerService.findOwner(ownderId);
- Pet pet = owner.getPet(petId);
- model.addAttribute("pet", pet);
- return "displayPet";
-}
-
-
- The following code snippet shows the use of path variables on a
- relative path
-
- @Controller
-@RequestMapping("/owners/{ownerId}/**")
-public class RelativePathUriTemplateController {
-
- @RequestMapping("/pets/{petId}")
- public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
- // implementation omitted
- }
-}
-
-
-
- method parameters that are decorated with the
- @PathVariable annotation can be of
- any simple type such as int, long,
- Date... Spring automatically converts to the appropriate type and
- throws a TypeMismatchException if the type is
- not correct.
-
-
-
-
- Mapping the request body with the @RequestBody
- annotation
-
- The @RequestBody method parameter
- annotation is used to indicate that a method parameter should be bound
- to the value of the HTTP request body. For example,
-
- @RequestMapping(value = "/something", method = RequestMethod.PUT)
-public void handle(@RequestBody String body, Writer writer) throws IOException {
- writer.write(body);
-}
-
- The conversion of the request body to the method argument is
- done using a HttpMessageConverter.
- HttpMessageConverter is responsible for
- converting from the HTTP request message to an object and converting
- from an object to the HTTP response body.
- DispatcherServlet supports annotation based
- processing using the
- DefaultAnnotationHandlerMapping and
- AnnotationMethodHandlerAdapter. In Spring 3 the
- AnnotationMethodHandlerAdapter has been
- extended to support the @RequestBody and has
- several HttpMessageConverters
- registered by default, these are
-
-
-
- ByteArrayHttpMessageConverter -
- converts byte arrays
-
-
-
- StringHttpMessageConverter - converts
- strings
-
-
-
- FormHttpMessageConverter - converts
- form data to/from a MultiValueMap<String, String>
-
-
-
- SourceHttpMessageConverter - converts
- to/from a javax.xml.transform.Source;
-
-
-
- MarshallingHttpMessageConverter -
- converts to/from an object using the
- org.springframework.oxm package.
-
-
-
- More information on these converters can be found in the section
- Message
- Converters.
-
- The MarshallingHttpMessageConverter
- requires a Marshaller and
- Unmarshaller from the
- org.springframework.oxm package to be
- configured on an instance of
- AnnotationMethodHandlerAdapter in the
- application context. For example
-
- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
- <property name="messageConverters">
- <util:list id="beanList">
- <ref bean="stringHttpMessageConverter"/>
- <ref bean="marshallingHttpMessageConverter"/>
- </util:list>
- </property
-</bean>
-
-<bean id="stringHttpMessageConverter"
- class="org.springframework.http.converter.StringHttpMessageConverter"/>
-
-<bean id="marshallingHttpMessageConverter"
- class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
- <property name="marshaller" ref="castorMarshaller" />
- <property name="unmarshaller" ref="castorMarshaller" />
-</bean>
-
-<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
-
-
-
-
-
- Returning multiple representations
-
- A RESTful architecture may expose multiple representations of a
- resource. There are two strategies for a client to inform the server of
- the representation it is interested in receiving.
-
- The first strategy is to use a distinct URI for each resource.
- This is typically done by using a different file extension in the URI.
- For example the URI
- http://www.example.com/users/fred.pdf requests a PDF
- representation of the user fred while
- http://www.example.com/users/fred.xml requests an XML
- representation.
-
- The second strategy is for the client to use the same URI to
- locate the resource but set the Accept HTTP request
- header to list the media
- types that it understands. For example, a HTTP request for
- http://www.example.com/users/fred with an
- Accept header set to application/pdf
- requests a PDF representation of the user fred while
- http://www.example.com/users/fred with an
- Accept header set to text/xml
- requests an XML representation. This strategy is known as content
- negotiation.
-
-
- One issue with the Accept header is that is impossible to change
- it in a web browser, in HTML. For instance, in Firefox, it's fixed
- to
-
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
-
-
- For this reason it is common to see the use of a distinct URI
- for each representation.
-
-
- To support multiple representations of a resource Spring provides
- the ContentNegotiatingViewResolver to resolve a
- view based on the file extension or Accept header of
- the HTTP request. ContentNegotiatingViewResolver
- does not perform the view resolution itself, but instead delegates to a
- list of view resolvers set using the bean property
- ViewResolvers.
-
- The ContentNegotiatingViewResolver selects
- an appropriate View to handle the request by
- comparing the request media type(s) with the media type (a.k.a.
- Content-Type) supported by the
- View associated with each of its
- ViewResolvers. The first
- View in the list that has a compatible
- Content-Type is used to return the representation to
- the client. The Accept header may include wild cards,
- for example 'text/*', in which case a View whose
- Context-Type was 'text/xml' is a compatible match.
-
- To support the resolution of a view based on a file extension,
- ContentNegotiatingViewResolver's bean property
- MediaTypes is used to specify a mapping of file
- extensions to media types. For more information on the algorithm to
- determine the request media type, refer to the API documentation for
- ContentNegotiatingViewResolver..
-
- Here is an example configuration of a
- ContentNegotiatingViewResolver
-
- <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
- <property name="mediaTypes">
- <map>
- <entry key="atom" value="application/atom+xml"/>
- <entry key="html" value="text/html"/>
- </map>
- </property>
- <property name="viewResolvers">
- <list>
- <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="prefix" value="/WEB-INF/jsp/"/>
- <property name="suffix" value=".jsp"/>
- </bean>
- </list>
- </property>
- </bean>
-
-
- <bean id="content" class="com.springsource.samples.rest.SampleContentAtomView"/>
-
- The InternalResourceViewResolver handles
- the translation of view names and JSP pages while the
- BeanNameViewResolver returns a view based on the
- name of a bean. (See "Resolving views - the ViewResolver
- interface" for more details on how Spring looks up and
- instantiates a view.) In this example, the content
- bean is a class that inherits from
- AbstractAtomFeedView which returns an Atom RSS
- feed. For more information on creating an Atom Feed representation see
- the section 'Atom Views'.
-
- In this configuration, if a request is made with a .html extension
- the view resolver will look for a view that matches the text/html media
- type. The InternalResourceViewResolver provides
- the matching view for text/html. If the request is made with the file
- extension .atom, the view resolver will look for a view that matches the
- application/atom+xml media type. This view is provided by the
- BeanNameViewResolver that maps to the
- SampleContentAtomView if the view name returned
- is 'content'. Alternatively, client requests could be made without a
- file extension and setting the Accept header to the preferred media-type
- and the same resolution of request to views would occur.
-
-
- If ContentNegotiatingViewResolver's list
- of ViewResolvers is not configured explicitly, then it will
- automatically use any ViewResolvers defined in the application
- context.
-
-
- The corresponding controller code that returns an Atom RSS feed
- for a URI of the form http://localhost/content.atom
- or http://localhost/content with an
- Accept header of application/atom+xml is shown
- below
-
- @Controller
-public class ContentController {
-
- private List<SampleContent> contentList = new ArrayList<SampleContent>();
-
- @RequestMapping(value="/content", method=RequestMethod.GET)
- public ModelAndView getContent() {
- ModelAndView mav = new ModelAndView();
- mav.setViewName("content");
- mav.addObject("sampleContentList", contentList);
- return mav;
- }
-
-}
-
-
- Views
@@ -638,333 +276,5 @@ public class SimpleController {
ModelAndView object. Please refer to the API
documentation for more details.
-
-
- Accessing RESTful services on the Client
-
- The RestTemplate is the core class for
- client-side access to RESTful services. It is conceptually similar to
- other template classes in Spring, such as
- JdbcTemplate and JmsTemplate
- and other template classes found in other Spring portfolio projects.
- RestTemplate's behavior is customized by providing
- callback methods and configuring the
- HttpMessageConverter used to marshal
- objects into the HTTP request body and to unmarshall any response back
- into an object. As it is common to use XML as a message format, Spring
- provides a MarshallingHttpMessageConverter that
- uses the Object-to-XML framework that is part of the
- org.springframework.oxm package. This gives you a
- wide range of choices of XML to Object mapping technologies to choose
- from.
-
- This section describes how to use the
- RestTemplate and its associated
- HttpMessageConverters.
-
-
- RestTemplate
-
- Invoking RESTful services in Java is typically done using a helper
- class such as Jakarta Commons HttpClient. For
- common REST operations this approach is too low level as shown
- below.
-
- String uri = "http://example.com/hotels/1/bookings";
-
-PostMethod post = new PostMethod(uri);
-String request = // create booking request content
-post.setRequestEntity(new StringRequestEntity(request));
-
-httpClient.executeMethod(post);
-
-if (HttpStatus.SC_CREATED == post.getStatusCode()) {
- Header location = post.getRequestHeader("Location");
- if (location != null) {
- System.out.println("Created new booking at :" + location.getValue());
- }
-}
-
- RestTemplate provides higher level methods that correspond to each
- of the six main HTTP methods that make invoking many RESTful services a
- one-liner and enforce REST best practices.
-
-
-
- The names of RestTemplate methods follow a
- naming convention, the first part indicates what HTTP method is being
- invoked and the second part indicates what is returned. For example, the
- method getForObject will perform a GET, convert
- the HTTP response into an object type of your choice and return that
- object. The method postForLocation will do a
- POST, converting the given object into a HTTP request and return the
- response HTTP Location header where the newly created object can be
- found In case of an exception processing the HTTP request, an exception
- of the type RestClientException will be
- thrown.
-
- Objects passed to and returned from these methods are converted to
- and from HTTP messages by
- HttpMessageConverter instances.
- Converters for the main mime types are registered by default, but you
- can also write your own converter and register it via the
- messageConverters bean property. The default
- converter instances registered with the template are
- ByteArrayHttpMessageConverter,
- StringHttpMessageConverter,
- FormHttpMessageConverter and
- SourceHttpMessageConverter. You can override
- these defaults using the messageConverters bean
- property as would be required if using the
- MarshallingHttpMessageConverter.
-
- Each method takes URI template arguments in two forms, either as a
- String variable length argument or a
- Map<String,String>. For example,
-
- String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}",
- String.class,"42", "21");
-
-
- using variable length arguments and
-
- Map<String, String> vars = Collections.singletonMap("hotel", "42");
-String result =
- restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
-
-
- using a Map<String,String>.
-
- To create an instance of RestTemplate you
- can simply call the default constructor. This will use standard Java
- classes from the java.net package as the underlying
- implementation to create HTTP requests. This can be overridden by
- specifying an implementation of
- ClientHttpRequestFactory. Spring provides
- the implementation
- CommonsClientHttpRequestFactory that uses the
- Jakarta Commons HttpClient to create requests.
- CommonsClientHttpRequestFactory is configured
- using an instance of
- org.apache.commons.httpclient.HttpClient which
- can in turn be configured with credentials information or connection
- pooling functionality.
-
- The previous example using Jakarta Commons
- HttpClient directly rewritten to use the
- RestTemplate is shown below
-
- uri = "http://example.com/hotels/{id}/bookings";
-
-RestTemplate template = new RestTemplate();
-
-Booking booking = // create booking object
-
-URI location = template.postForLocation(uri, booking, "1");
-
-
- The general callback interface is
- RequestCallback and is called when the
- execute method is invoked.
-
- public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
- ResponseExtractor<T> responseExtractor,
- String... urlVariables)
-
-
-// also has an overload with urlVariables as a Map<String, String>.
-
- The RequestCallback interface is
- defined as
-
- public interface RequestCallback {
- void doWithRequest(ClientHttpRequest request) throws IOException;
-}
-
- and allows you to manipulate the request headers and write to the
- request body. When using the execute method you do not have to worry
- about any resource management, the template will always close the
- request and handle any errors. Refer to the API documentation for more
- information on using the execute method and the meaning of its other
- method arguments.
-
-
-
- HTTP Message Conversion
-
- Objects passed to and returned from the methods
- getForObject,
- postForLocation, and
- put are converted to HTTP requests and from
- HTTP responses by HttpMessageConverters.
- The HttpMessageConverter interface is
- shown below to give you a better feel for its functionality
-
- public interface HttpMessageConverter<T> {
-
- // Indicate whether the given class is supported by this converter.
- boolean supports(Class<? extends T> clazz);
-
- // Return the list of MediaType objects supported by this converter.
- List<MediaType> getSupportedMediaTypes();
-
- // Read an object of the given type form the given input message, and returns it.
- T read(Class<T> clazz, HttpInputMessage inputMessage) throws IOException,
- HttpMessageNotReadableException;
-
- // Write an given object to the given output message.
- void write(T t, HttpOutputMessage outputMessage) throws IOException,
- HttpMessageNotWritableException;
-
-}
-
- Concrete implementations for the main media (mime) types are
- provided in the framework and are registered by default with the
- RestTemplate on the client-side and with
- AnnotationMethodHandlerAdapter on the
- server-side.
-
- The implementations of
- HttpMessageConverters are described in the
- following sections. For all converters a default media type is used but
- can be overridden by setting the
- supportedMediaTypes bean property
-
-
- StringHttpMessageConverter
-
- An HttpMessageConverter
- implementation that can read and write Strings from the HTTP request
- and response. By default, this converter supports all text media types
- (text/*), and writes with a
- Content-Type of
- text/plain.
-
-
-
- FormHttpMessageConverter
-
- An HttpMessageConverter
- implementation that can read and write form data from the HTTP request
- and response. By default, this converter reads and writes the media
- type application/x-www-form-urlencoded. Form data
- is read from and written into a MultiValueMap<String,
- String>.
-
-
-
- ByteArrayMessageConverter
-
- An HttpMessageConverter
- implementation that can read and write byte arrays from the HTTP
- request and response. By default, this converter supports all media
- types (*/*), and writes with a
- Content-Type of
- application/octet-stream. This can be overridden by
- setting the supportedMediaTypes property, and
- overriding getContentType(byte[]).
-
-
-
- MarshallingHttpMessageConverter
-
- An HttpMessageConverter
- implementation that can read and write XML using Spring's
- Marshaller and
- Unmarshaller abstractions from the
- org.springframework.oxm package. This converter
- requires a Marshaller and
- Unmarshaller before it can be used.
- These can be injected via constructor or bean properties. By default
- this converter supports (text/xml) and
- (application/xml).
-
-
-
- SourceHttpMessageConverter
-
- An HttpMessageConverter
- implementation that can read and write
- javax.xml.transform.Source from the HTTP
- request and response. Only DOMSource,
- SAXSource, and
- StreamSource are supported. By default, this
- converter supports (text/xml) and
- (application/xml).
-
-
-
- BufferedImageHttpMessageConverter
-
- An HttpMessageConverter
- implementation that can read and write
- java.awt.image.BufferedImage from the HTTP
- request and response. This converter reads and writes the media type
- supported by the Java I/O API.
-
-
-