Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF o lee en línea desde Scribd
Está en la página 1/ 78
113723, 2207 17. Web MVC framework
17. Marco Web MVC.
Anterior Parte V. La Web Préximo
17. Marco Web MVC
17.1 Introduccién al marco Spring Web MVC
EI marco del controlador de vista de modelo (MVC) de Spring Web esté disefiado en toro a un
DispatcherServiet que envia solicitudes a los controladores, con asignaciones de controlador
configurables, resolucién de vista, resolucién de tema y configuracién regional, asi como soporte para
cargar archivos. El controlador predeterminado se basa en las anotaciones @Controller y
G@Requesttapping , lo que ofrece una amplia gama de métodos de manejo flexibles. Con la introduccién de
Spring 3.0, el @Control ler mecanismo también le permite crear aplicaciones y sitios web RESTful, a
través de la @PathVariable anotacién y otras funciones
“ Abierto para prérroga.
Un principio de disefio clave en Spring Web MVC y en Spring en general es el principio" Abierto para
extension, cerrado para modificacion " .
‘Aigunos métodos en las clases principales de Spring Web MVC estan marcados como final . Como
desarrollador, no puede anular estos métodos para proporcionar su propio comportamiento. Esto no
se ha hecho arbitrariamente, sino especificamente con este principio en mente.
Para obtener una explicacién de este principio, consulte Expert Spring Web MVC y Web Flow de Seth
Ladd y otros; ver especificamente la seccién "Una mirada al disefio", en la pagina 117 de la primera
edicién. Alternativamente, vea
1. Bob Martin, El principio abierto-cerrado (PDF)
No puede agregar consejos a los métodos finales cuando usa Spring MVC. Por ejemplo, no puede
agregar consejos al AbstractController. setSynchronizeOnSession() método. Consulte la
Seccién 9.6.1, "Comprensién de los proxies AOP” para obtener mas informacién sobre los proxies
AOP y por qué no puede agregar consejos a los métodos finales.
En Spring Web MVC puede usar cualquier objeto como comando u objeto de respaldo de formulario; no
necesita implementar una interfaz especifica del marco o una clase base. El enlace de datos de Spring es
muy flexible: por ejemplo, trata las discrepancias de tipos como errores de validacién que la aplicacién
puede evaluar, no como errores del sistema. Por lo tanto, no necesita duplicar las propiedades de sus
objetos comerciales como cadenas simples sin tipo en sus objetos de formulario simplemente para manejar
envios no validos 0 para convertir las cadenas correctamente. En su lugar, a menudo es preferible vincular
directamente a sus objetos comerciales
npe:idocs spring olspring-rameworkidocs/9.2xleprng ramework-eferencelimlimve htm we“13123, 2207 47. Web MVC framework
La resolucién de vista de Spring es extremadamente flexible. Por lo general, A Controller es responsable
de preparar un modelo Map con datos y seleccionar un nombre de vista, pero también puede escribir
directamente en el flujo de respuesta y completar la solicitud. La resolucién de nombre de vista es altamente
configurable a través de la extensién de archivo o la negociacién de tipo de contenido de encabezado
Aceptar, a través de nombres de bean, un archivo de propiedades o incluso una
ViewResolver implementacién personalizada. El modelo (la M en MVC) es una [Map interfaz que permite la
abstraccién completa de la tecnologia de visualizacién. Puede integrarse directamente con tecnologias de
representacién basadas en plantillas, como JSP, Velocity y Freemarker, o generar directamente XML, JSON,
‘Atom y muchos otros tipos de contenido. E] modelo Map simplemente se transforma en un formato
apropiado, como atributos de solicitud JSP, un modelo de plantilla de Velocity.
17.1.1 Caracteristicas de Spring Web MVC
Flujo web de primavera
Spring Web Flow (SWF) pretende ser la mejor solucién para la gestién del flujo de paginas de
aplicaciones web.
SWF se integra con marcos existentes como Spring MVC, Struts y JSF, tanto en entomos de servlet
‘como de portlet. Si tiene un proceso (0 procesos) de negocio que se beneficiaria de un modelo
‘conversacional en lugar de un modelo puramente de solicitud, entonces SWF puede ser la solucién.
SWF le permite capturar flujos de paginas légicas como médulos auténomos que se pueden reutilizar
en diferentes situaciones y, como tal, es ideal para crear médulos de aplicaciones web que guian al
usuario a través de navegaciones controladas que impulsan los procesos comerciales
Para obtener mas informacion sobre SWF, consulte el sitio web de Spring Web Flow
EI médulo web de Spring incluye muchas caracteristicas Unicas de soporte webs
+ Separacién clara de roles . Cada funcién (controlador, validador, objeto de comando, objeto de
formulario, objeto de modelo, DispatcherServlet mapeo de controlador, resolucién de vista, etc.)
puede ser cumplida por un objeto especializado.
+ Configuracién potente y sencilla de las clases de marco y aplicacién como JavaBeans . Esta capacidad
de configuracién incluye referencias sencillas entre contextos, como desde controladores web hasta
objetos comerciales y validadores,
+ Adaptabilidad, no intrusividad y flexibilidad. Defina cualquier firma de método de controlador que
necesite, posiblemente usando una de las anotaciones de parametros (como @RequestParam,
@RequestHeader, @PathVariable y més) para un escenario determinado.
+ Cédigo comercial reutilizable , sin necesidad de duplicacién . Utilice objetos comerciales existentes
‘como comandos 0 objetos de formulario en lugar de duplicarlos para ampliar una clase base de marco
particular,
+ Encuaderacién y validacion personalizables . Escriba las discrepancias como errores de validacién a
nivel de aplicacién que mantienen el valor infractor, la fecha localizada y el enlace numérico, etc., en
lugar de objetos de formulario de solo cadena con andlisis manual y conversién a objetos comerciales.
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html 278“13123, 2207 47. Web MVC framework
+ Resoluci6n de visualizacién y asignacién de controladores personalizables . Las estrategias de mapeo
de controladores y resolucién de vistas van desde una configuracién simple basada en URL hasta
estrategias de resolucién sofisticadas y disefiadas especificamente. Spring es més flexible que los
marcos web MVC que exigen una técnica particular.
+ Transferencia de modelo flexible . La transferencia de modelos con un nombre/valor Map admite una
facil integracién con cualquier tecnologia de visualizacién
+ Resolucién de tema y configuracién regional personalizable, compatibilidad con JSP con o sin biblioteca
de etiquetas Spring, compatibilidad con JSTL, compatibilidad con Velocity sin necesidad de puentes
adicionales, etc.
+ Una biblioteca de etiquetas JSP simple pero poderosa conocida como la biblioteca de etiquetas Spring
que brinda soporte para caracteristicas tales como enlace de datos y temas . Las etiquetas
personalizadas permiten la maxima flexibilidad en términos de cédigo de marcado. Para obtener
informacién sobre el descriptor de la biblioteca de etiquetas, consulte el apéndice titulado Apéndice G,
spring.tid
+ Una biblioteca de etiquetas de formulario JSP. introducida en Spring 2.0, que facilita mucho la escritura
de formularios en paginas JSP. Para obtener informacién sobre el descriptor de la biblioteca de
etiquetas, consulte el apéndice titulado Apéndice H, spring-formn.tid
+ Beans cuyo ciclo de vida se limita a la solicitud HTTP actual o HTTP Session). Esta no es una
caracteristica especifica de Spring MVC en si, sino de los WebApplicationContext contenedores que
utiliza Spring MVC. Estos Ambitos de bean se describen en la Seccién 5.5.4, “Ambitos de solicitud,
sesién y sesi6n global”
17.1.2 Capacidad de conexién de otras implementaciones de MVC
Las implementaciones que no son de Spring MVC son preferibles para algunos proyectos. Muchos equipos
esperan aprovechar su inversién existente en habilidades y herramientas. Existe una gran cantidad de
conocimiento y experiencia para el marco Struts. Si puede soportar las fallas arquitecténicas de Struts,
puede ser una opcién viable para la capa web; lo mismo se aplica a WebWork y otros frameworks web
ve.
Si no desea utilizar el MVC web de Spring, pero tiene la intencién de aprovechar otras soluciones que
ofrece Spring, puede integrar facilmente el marco MVC web de su eleccién con Spring. Simplemente inicie
un contexto de aplicacién raiz de Spring a través de su ContextLoaderListener | y acceda a él a través
de su ServietContext atributo (0 el método auxiliar respectivo de Spring) desde dentro de una accién de
Struts 0 WebWork. No hay "complementos" involucrados, por lo que no es necesaria una integraci6n
dedicada, Desde el punto de vista de la capa web, simplemente usa Spring como una biblioteca, con la
instancia de contexto de la aplicacién raiz como punto de entrada,
Sus beans registrados y los servicios de Spring pueden estar al alcance de su mano incluso sin Web MVC
de Spring. Spring no compite con Struts o WebWork en este escenario. Simplemente aborda las muchas
reas que los marcos MVC web puros no abordan, desde la configuracién de beans hasta el acceso a datos,
y el manejo de transacciones, Por lo tanto, puede enriquecer su aplicacién con un nivel intermedio de
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html are113723, 2207 17. Web MVC framework
Spring y/o un nivel de acceso a datos, incluso si solo desea utilizar, por ejemplo, la abstraccién de
transacciones con JDBC 0 Hibernate.
17.2 ElDispatcherServlet
El framework web MVC de Spring es, como muchos otros frameworks web MVC, impulsado por solicitudes,
disefiado alrededor de un Serviet central que envia solicitudes a los controladores y oftece otras
funcionalidades que faciltan el desarrollo de aplicaciones web. Sin embargo, Spring's
DispatcherServlet hace més que eso. Esté completamente integrado con el contenedor Spring oC y,
como tal, le permite usar todas las demas caracteristicas que tiene Spring.
EI flujo de trabajo de procesamiento de solicitudes de Spring Web MVC [DispatcherServlet se ilustra en
el siguiente diagrama. El lector experto en patrones reconoceré que [DispatcherServiet es una expresién
del patrén de disefio " Controlador frontal " (este es un patrén que Spring Web MVC comparte con muchos
otros marcos web lideres).
Delegate Handle
Incoming a request
request
——=>
-_——
Return = Create
response} rendering model
of response
Return
control Render
response
Servlet engine
(e.g. Tomcat)
El flujo de trabajo de procesamiento de solicitudes en Spring Web MVC (nivel alto)
El DispatcherServiet es real Servlet (se hereda dela HittpServlet clase base) y, como tal, se declara
en el web.xml de su aplicacién web. Debe asignar las solicitudes que desea que
DispatcherServlet gestione mediante una asignacién de URL en el mismo web.xml) archivo. Esta es la
configuracién estandar de Java EE Servlet; el siguiente ejemplo muestra tal
DispatcherServlet declaracién y mapeo:
npe:idocs spring otepring-rameworkidocs/9.2xlepring ramework-eferencelilimve htm ae+3723, 2207 17. Web MVC framework
ejemplo org.springframework.web. servlet .DispatcherServlet 1 ejemplo
/example/*
‘ »
En el ejemplo anterior, todas las solicitudes que comienzan con /example seran manejadas por la
DispatcherServiet instancia denominada example . En un entomno Servlet 3.0+, también tiene la opcién
de configurar el contenedor Servlet mediante programacién. A continuacién se muestra el equivalente
basado en cédigo del web.xml ejemplo anterior:
clase publica MyWebApplicationInitializer implementa WebApplicationInitializer {
Goverride
public void onStartup (contenedor ServietContext) {
ServietRegistration.Registro dinémico = container.addServlet( “dispatcher” , new Dis
registro. setLoadonStartup( 1);
registro.addMapping( “/ejemplo/*" );
WebapplicationInitializer es una interfaz proporcionada por Spring MVC que garantiza que su
configuracién basada en cédigo sea detectada y utilizada automaticamente para inicializar cualquier
contenedor Servlet 3. Una implementacién de clase base abstracta de esta interfaz denominada
AbstractDispatcherServiet initializer hace que sea atin més facil registrar
DispatcherServiet simplemente especificando su asignacién de servlet. Consulte Inicializacién del
contenedor de servlet basado en cédigo para obtener mds detalles.
Lo anterior es solo el primer paso para configurar Spring Web MVC. Ahora necesita configurar los diversos
beans utilizados por el marco Spring Web MVC (ademas del DispatcherServiet mismo).
Como se detalla en la Seccién 5.14, "Capacidades adicionales de ApplicationContext,
ApplicationContext las instancias en Spring pueden tener alcance. En el marco Web MVC, cada uno
DispatcherServiet tiene el suyo propio WebApplicationContext |, que hereda todos los beans ya
definidos en la raiz WebApplicationContext . Estos beans heredados se pueden anular en el Ambito
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html 878113723, 2207 17. Web MVC framework
especifico del servlet, y puede definir nuevos beans especificos del Ambito locales para una instancia de
Serviet determinada.
DispatcherServiet
{awaiting incoming HtipServitRequests)
WebApplicationContext
(containing controters, view resolvers,
locale resolvers and
other web-ralated beans)
conrotere | | "aerMappis
WebApplication
ViewResclver Context(s)
(containing middle-tier
services, datasources,
catera)
Jerarquia de contexto en Spring Web MVC.
Tras la inicializacién de un DispatcherServiet , Spring MVC busca un archivo con el nombre en el
directorio de su aplicacién web y crea los beans definidos alli, anulando las definiciones de cualquier beans
definido con el mismo nombre en el Ambito global. [servlet-name]-servlet.xml |NEB-INF
Considere la siguiente DispatcherServiet configuracién de Serviet (en el web. xml archivo)
«servlet>
golf
ong.springframework.web. servlet .DispatcherServiet
1 golf
/golfing/*
< »
Con la configuracién de Servlet anterior en su lugar, necesitara tener un archivo llamado
/WEB-INF/ golfing -servlet.xml en su aplicacién; este archivo contendré todos sus componentes
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html ere“13123, 2207 47. Web MVC framework
(beans) especificos de Spring Web MVC. Puede cambiar la ubicacién exacta de este archivo de
configuracién a través de un parémetro de inicializacién de Servlet (consutte los detalles a continuacién).
El WebApplicationContext es una extensién del plano ApplicationContext que tiene algunas
caracteristicas adicionales necesarias para las aplicaciones web. Se diferencia de un normal
ApplicationContext en que es capaz de resolver temas (ver Seccién 17.9, “Uso de temas” ), y que sabe
con qué Servlet esta asociado (al tener un enlace al ServletContext ). esté
WebapplicationContext Vinculado en el ServietContext y al usar métodos estaticos en la
RequestContextUtils clase, siempre puede buscar WebApplicationContext si necesita acceder a él
17.2.1 Tipos especiales de frijol en el WebApplicationContext
Spring DispatcherServiet usa beans especiales para procesar solicitudes y generar las vistas
apropiadas. Estos beans son parte de Spring MVC. Puede elegir qué beans especiales usar simplemente
configurando uno 0 mas de ellos en el archivo WebApplicationContext , Sin embargo, no necesita hacer
es0 inicialmente ya que Spring MVC mantiene una lista de beans predeterminados para usar si no configura
ninguno. Mas sobre eso en la siguiente seccién. Primero, consulte la siguiente tabla que enumera los tipos
de frjoles especiales DispatcherServiet en los que se basa
Tabla 17.1. Tipos especiales de frijol en el WebApplicationContext
tipo de frijol
Asigna solicitudes entrantes a controladores y una lista de
preprocesadores y posprocesadores (interceptores de controladores)
en funcién de algunos criterios cuyos detalles varian segin la
Mapeo de controlador = ; a
HandlerMapping implementacién. La implementacién més popular
admite controladores anotados, pero también existen otras
implementaciones.
Ayuda |DispatcherServiet a invocar un controlador asignado a una
solicitud, independientemente de que el controlador se invoque
realmente. Por ejemplo, invocar un controlador anotado requiere
resolver varias anotaciones. Por lo tanto, el propésito principal de a
HandlerAdapter es proteger al DispatcherServiet de tales
detalles
Adaptador de controlador
Asigna excepciones a las vistas y también permite un cédigo de
HandlerExceptionResolver .
manejo de excepciones mas complejo
Resuelve los nombres de vista lgicos basados en cadenas en
VerResolver
View tipos reales.
LocaleResolver Resuelve la configuracién regional que esta utlizando un cliente, para
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html 178“13123, 2207 17. Wed MYC framework
tipo de frijol Explicacion
poder ofrecer vistas intermacionalizadas
Resuelve temas que su aplicacién web puede usar, por ejemplo, para
ofrecer disefios personalizados
Resolucién de temas
Analiza solicitudes de varias partes, por ejemplo, para admit el
MultipartResolver
procesamiento de cargas de archivos desde formularios HTML.
Almacena y recupera la “entrada y la “salida” FlashMap que se
FlashMapManager pueden usar para pasar atributos de una solicitud a otra,
generalmente a través de una redireccién.
17.2.2 Configuracién predeterminada de DispatcherServlet
Como se mencioné en la seccién anterior, para cada bean especial, mantiene DispatcherServiet una
lista de implementaciones para usar de forma predeterminada, Esta informacién se guarda en el archivo
DispatcherServiet .properties| del paquete org. springframework.web. servlet
Todos los beans especiales tienen sus propios valores predeterminados razonables. Sin embargo, tarde 0
temprano necesitara personalizar una o més de las propiedades que proporcionan estos beans. Por
ejemplo, es bastante comin configurar una InternalResourceViewResolver configuracién de su
prefix propiedad en la ubicacién principal de los archivos de visualizacién.
Independientemente de los detalles, el concepto importante que debe comprender aqui es que una vez que
configura un bean especial como un InternalResourceViewResolver en su WebApplicationContext ,
anula efectivamente la lista de implementaciones predeterminadas que se habrian utilizado de otro modo
para ese tipo de bean especial. Por ejemplo, si configura un , se ignora
InternalResourceViewResolver la lista predeterminada de implementaciones. ViewResolver
En a Seccién 17.15, "Configuracién de Spring MVC", aprenderé sobre otras opciones para configurar
Spring MVC, incluida la configuracién Java de MVC y el espacio de nombres XML de MVC, que
proporcionan un punto de partida simple y asumen poco conocimiento de cémo funciona Spring MVC.
Independientemente de cémo elija configurar su aplicacién, los conceptos explicados en esta seccién son
fundamentales y deberian serle de ayuda
17.2.3 Secuencia de procesamiento de DispatcherServiet
Después de configurar un DispatcherServiet y llega una solicitud para ese DispatcherServiet ,
DispatcherServlet comienza a procesar la solicitud de la siguiente manera:
1. se WebApplicationContext busca y vincula en la solicitud como un atributo que el controlador y otros
elementos del proceso pueden usar. Esta enlazado por defecto bajo la clave
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencelilimve htm are“13123, 2207 417, Web MVC framework
DispatcherServlet .NEB_APPLICATION_CONTEXT_ATTRIBUTE
2. El solucionador de configuracién regional esta vinculado a la solicitud para permitir que los elementos
del proceso resuelvan la configuracién regional que se usara al procesar la solicitud (representar la
vista, preparar datos, etc.). Sino necesita resolver la configuracién regional, no la necesita,
3, El solucionador de temas esta vinculado a la solicitud para permitir que elementos como las vistas
determinen qué tema usar. Si no usa temas, puede ignorarto.
4, Si especifica una resolucién de archivos de varias partes, la solicitud se inspecciona en busca de varias
partes; si se encuentran varias partes, la solicitud se envuelve en un
MultiparthttpServletRequest para que otros elementos del proceso la procesen mas. Consulte la
Seccién 17.10, “Soporte de varias partes (carga de archivos) de Spring” para obtener més informacién
sobre el manejo de varias partes.
5, Se busca un controlador adecuado. Si se encuentra un controlador, la cadena de ejecucién asociada
con el controlador (preprocesadores, posprocesadores y controladores) se ejecuta para preparar un
modelo o representacién
6. Si se devuelve un modelo, se representa la vista. Sino se devuelve ningiin modelo (puede deberse a
que un preprocesador o posprocesador intercepts la solicitud, tal vez por razones de seguridad), no se
representa ninguna vista, porque la solicitud ya podria haberse cumplido.
Controladores de resolucién de excepciones que se deciaran en las NebApplicat ionContext excepciones
de recogida que se lanzan durante el procesamiento de la solicitud. El uso de estos solucionadores de
excepciones le permite definir comportamientos personalizados para abordar las excepciones.
Spring [DispatcherServiet también admite la devolucién de la ultima fecha de modificacién , seguin lo
especificado por la API de Servlet. El proceso de determinar la ditima fecha de modificacién para una
solicitud especifica es sencillo: |DispatcherServlet busca una asignacién de controlador adecuada y
prueba si el controlador que se encuentra implementa la LastModified interfaz. Si es asi, el valor del
long getLastModified(request) método de la LastModi fied interfaz se devuelve al cliente.
Puede personalizar |DispatcherServlet instancias individuales agregando parémetros de inicializacién de
Servlet ( init-param elementos) a la declaracién de Servlet en el web. xml archivo. Consulte la siguiente
tabla para ver la lista de pardmetros admitidos.
Tabla 17.2. DispatcherServiet parametros de inicializacién
Parametro Explicacién
Clase que implementa WebApplicationContext , que instancia el
contextClass contexto utilizado por este Servlet. De forma predeterminada,
XmlWebApplicat ionContext se utiliza el.
contextConfiglocation) Cadena que se pasa a la instancia de contexto (especificada por
contextClass)) para indicar dénde se pueden encontrar los,
contextos. La cadena consta potencialmente de varias cadenas
(usando una coma como delimitador) para admitir méitiples contextos.
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html ore113723, 2207 17. Web MVC framework
Parmetro Explicacién
En el caso de varias ubicaciones de contexto con beans definidos dos
veces, la ubicacién mas reciente tiene prioridad.
Espacio de nombres de WebApplicationContext . El valor
namespace
predeterminado es [servlet-name]-servlet ,
17.3 Controladores de implementacién
Controllers provide access to the application behavior that you typically define through a service interface.
Controllers interpret user input and transform it into a model that is represented to the user by the view.
Spring implements a controller in a very abstract way, which enables you to create a wide variety of
controllers.
Spring 2.5 introduced an annotation-based programming model for MVC controllers that uses annotations
such as @RequestMapping| @RequestParam, @ModelAttribute , and so on. 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 APIs, although you can easily configure access to Servlet or Portlet
facilities.
@ Available in the samples repository, a number of web applications leverage the annotation
support described in this section including MvcShowcase, MvcAjax, MvcBasic, PetClinic,
PetCare, and others.
GcontroLter
public class HelloWorldcontroller {
G@RequestMapping("/helLoworld")
public String helloWorld(Model model) {
model.addattribute("message", “Hello World!"
return "helloworld";
As you can see, the @ontroller and @RequestMapping) annotations allow flexible method names and
signatures. In this particular example the method accepts a Model and returns a view name as a String,
but various other method parameters and return values can be used as explained later in this section
@Controller and @RequestMapping) and a number of other annotations form the basis for the Spring
MVC implementation. This section documents these annotations and how they are most commonly used in a
Serviet environment
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html 10178w923,2207 17. web MVC famenor
17.3.1 Defining a controller with @controller
The @Controller| annotation indicates that a particular class serves the role of a controller. Spring does
not require you to extend any controller base class or reference the Servlet API. However, you can still
reference Serviet-specific features if you need to
The @Controller | annotation acts as a stereotype for the annotated class, indicating its role. The
dispatcher scans such annotated classes for mapped methods and detects @RequestMapping annotations
(see the next section)
You can define annotated controller beans 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 add component scanning to your configuration
Use the spring-context schema as shown in the following XML snippet
“http: //www. springframework .org/schema/beans
xmlns:xsis"http: //www.w3.org/2001/xMLSchena-instance
xmlns:p="http: //wmw. springframework.org/schema/p”
xmLns: context="http: //www. springframework.org/schema/context”
chenaLocat ion
http: //waa. springframework.org/schema/beans
http://www. springframework.org/schema/beans/spring-beans.xsd
http: //waa.springframework.org/schema/context
http: //wwu. springframework.org/schema/context/spring-context.xsd">
xsi:
17.3.2 Mapping Requests With @RequestMapping
You use the @RequestMapping annotation to map URLs such as /appointments onto an entire class or a
particular handler 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 etc.) o an HTTP request parameter condition.
The following example from the Petcare sample shows a controller in a Spring MVC application that uses
this annotation:
@controtler
@RequestMapping("/appointments")
public class AppointmentsController {
npe:idocs spring olepring-rameworkidocs/9.2xleprng ramework-eferencelilimve htm we+3723, 2207
17. Web MVC framework
private final AppointmentBook appointnentBook;
G@rutowired
public AppointmentsController(AppointnentBook appointmentBook) {
‘this. appointmentBook = appointmentBook;
?
@RequestMapping(method = RequestMethod.GET)
public Map get() {
return appointmentBook .getappointmentsForToday();
?
@RequestMapping(value="/{day)", method = RequestMethod.GET)
public Map getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Da
return appointmentBook. getAppointment'sForDay (day);
+
G@RequestMapping(value="/new", method = RequestMethod.GET)
Public AppointmentForm getNewForm() {
return new AppointmentForm();
}
@RequestMapping(method = RequestMethod.POsT)
public String add(@valid AppointmentForm appointment, BindingResult result) {
if (result.hastrrors()) {
return “appointments/ne
y
appointmentBook. addAppointment (appointment) ;
return “redirect: /appointnents”;
>
In the example, 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 are relative to the /appointments| path.
The| get () jmethodihasjaifurther| @Reques tMapp ing jrefinementsit(only/acceptsiGET requests, meaning »
that an HTTP GET for /appointments invokes this method. 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,
The (getForday() | method shows another usage of @RequestMapp ing : URI templates. (See the next
section ),
A @RequestMapping| on the class level is not required. Without i, all paths are simply absolute, and not
relative. The following example from the PetClinic sample application shows a multi-action controller using
@RequestMapping
@controtter
public class ClinicController {
npe:idoes spring olepring-rameworkidocs/9.2xleprng ramework-eferencellimve htm se113723, 2207
New
17. Web MVC framework
private final Clinic clinic;
G@rutowired
public ClinicController(Clinic clinic) {
‘this.clinic = clinics
?
@RequestMapping("/")
public void welconeHandler() {
?
@RequestMapping("/vets")
public ModelMap vetsHandler() {
return new ModelMap(this.clinic.getVets());
?
‘A.common pitfall when working with annotated controller classes happens when applying
functionality that requires creating a proxy for the controller object (e.g. @Transactional
methods). Usually you will introduce an interface for the controller in order to use JDK dynamic
proxies. To make this work you must move the @RequestMapping| annotations, as well as any
other type and method-level annotations (e.g. @ModelAttribute, @InitBinder ) to the
interface as well as the mapping mechanism can only "see" the interface exposed by the
proxy, Alternatively, you could activate proxy-target-class="true” in the configuration for
the functionality applied to the controller (in our transaction scenario in
). Doing so indicates that CGLIB-based subclass proxies should
be used instead of interface-based JDK proxies. For more information on various proxying
mechanisms see Section 9.6, “Proxying mechanisms".
Note however that method argument annotations, e.g. @RequestParam, must be present in
the method signatures of the controller class.
Support Classes for @RequestMapping methods in Spring MVC 3.1
Spring 3.1 introduced a new set of support classes for @RequestMapping methods called
RequestMappingHandlerMapping] and RequestMappingHandlerAdapter respectively. They are
recommended for use and even required to take advantage of new features in Spring MVC 3.1 and going
forward. The new support classes are enabled by default by the MVC namespace and the MVC Java config
but must be configured explicitly if using neither. This section describes a few important differences between
the old and the new support classes.
Prior to Spring 3.1, type and method-level request mappings were examined in two separate stages — a
controller was selected first by the DefaultAnnotationHandlerMapping and the actual method to invoke
was narrowed down second by the AnnotationMethodHandleradapter .
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html 1978“13123, 2207 417. Web MVC framework
With the new support classes in Spring 3.1, the RequestMappingHandlerMapping jis the only place where
a decision is made about which method should process the request. Think of controller methods as a
collection of unique endpoints with mappings for each method derived from type and method-level
@RequestMapping information.
This enables some new possibilities. For once a |HandlerInterceptor or a HandleréxceptionResolver
can now expect the Object-based handler to be a HandlerMethod , which allows them to examine the exact
method, its parameters and associated annotations. The processing for a URL no longer needs to be split
across different controllers.
There are also several things no longer possible:
+ Select a controller first with a SimpleUrlHandlerMapping or BeanNameUrlHandlerMapping and then
narrow the method based on @RequestMapping annotations
+ Rely on method names as a fall-back mechanism to disambiguate between two @RequestMapping
methods that don't have an explicit path mapping URL path but otherwise match equally, e.g. by HTTP
method. In the new support classes @RequestMapping methods have to be mapped uniquely.
+ Have a single default method (without an explicit path mapping) with which requests are processed if no
other controller method matches more concretely. In the new support classes if a matching method is
not found a 404 error is raised
The above features are still supported with the existing support classes. However to take advantage of new
Spring MVC 3.1 features you'll need to use the new support classes.
URI Template Patterns
URI templates can be used for convenient access to selected parts of a URL ina @RequestMapping.
method.
AURI Template is a URMlike string, containing one or more variable names. When you substitute values for
these variables, the template becomes a URI. The proposed RFC for URI Templates defines how a URI is
parameterized. For example, the URI Template http://www. example. com/users/{userId}, contains the
variable userid. Assigning the value fred to the variable yields http://www. example. com/users/fred
In Spring MVC you can use the @PathVariable annotation on a method argument to bind it to the value of
a URI template variable:
@RequestMapping(value="/owners/{onnerId}", 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 " /onners/{ownerId}" specifies the variable name |ownerTd . When the controller
handles this request, the value of ownerTd|is set to the value found in the appropriate part of the URI. For
example, when a request comes in for /owners/fred), the value of ownerid is fred
npe:idocs spring otepring-rameworkidocs/9.2 xlepring ramework-eferencalimlimve html aire113723, 2207 17. Web MVC framework
6 To process the @PathVariable annotation, Spring MVC needs to find the matching URI template
variable by name, You can specify it in the annotation:
G@RequestMapping(value="/owners/{ownerId}", method=RequestMethod. GET)
public String findOwner(@PathVariable("ownerId") String theOwner, Model model) {
// implementation omitted
?
Or if the URI template variable name matches the method argument name you can omit that
detail. As long as your code is not compiled without debugging information, Spring MVC will
match the method argument name to the URI template variable name:
G@RequestMapping(value="/owners/{ownerTd}", method=RequestMethod. GET)
public String findOwner(@PathVariable String ownerId, Model model) {
// implementation omitted
y
‘Amethod can have any number of (@PathVariable annotations:
GRequestMapping(value="/ouners/{ownerId}/pets/{petTd}", method-RequestMethod. GET)
public String findeet(@PathVariable String ownerId, @PathVariable String petId, Nodel nodel)
Owner owner = ownerService.findOwner(ownerId) ;
Pet pet = onner. getPet (petid);
model.addAttribute("pet", pet);
return “displayPet";
}
4 »
When a @PathVariable annotation is used on a Map) argument, the map is populated
with all URI template variables,
AUR! template can be assembled from type and path level @RequestMapping annotations. As a result the
findPet() method can be invoked with a URL such as /owners/42/pets/21
@ontrotter
@RequestMapping("/owners/{ownerId)")
public class RelativePathUriTemplateController {
@RequestMapping("/pets/{petId}")
public void findPet(@Pathvariable String ownerId, @PathVariable String petId, Model nodel)
// implenentation omitted
>
y
‘ »
A @athvariable| argument can be of any simple type such as int, long, Date, etc. Spring automatically
converts to the appropriate type or throws a TypeMismatchException if it fails to do so. You can also
register support for parsing additional data types. See the section called "Method Parameters And Type
Conversion” and the section called “Customizing WebDataBinder| initialization’.
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html 19178113723, 2207 17. Web MVC framework
URI Template Patterns with Regular Expressions
‘Sometimes you need more precision in defining URI template variables. Consider the URL
“/spring-web/[email protected]" . How do you break it down into multiple parts?
The @RequestMapping annotation supports the use of regular expressions in URI template variables. The
syntax is {varName:regex}| where the first part defines the variable name and the second - the regular
expression.For example:
@RequestMapping("/spring-web/ {symbol icName: [a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension: \\.[
public void handle(@PathVariable String version, @PathVariable String extension) {
Move
}
+
‘ »
Path Patterns
In addition to URI templates, the @RequestMapping annotation also supports Ant-style path patterns (for
example, |/myPath/* .do ). A combination of URI templates and Ant-style globs is also supported (for
example, /owners/*/pets/{petId) ).
Patterns with Placeholders
Pattems in @RequestMapping annotations support S...} placeholders against local properties and/or
system properties and environment variables. This may be useful in cases where the path a controller is,
mapped to may need to be customized through configuration. For more information on placeholders see the
Javadoc for |PropertyPlaceholderconfigurer
Matrix Variables
The URI specification RFC 3986 defines the possibilty of including name-value pairs within path segments.
There is no specific term used in the spec. The general "URI path parameters" could be applied although the
more unique "Matrix URIs", originating from an old post by Tim Bemers-Lee, is also frequently used and
fairly well known. Within Spring MVC these are referred to as matrix variables.
Matrix variables can appear in any path segment, each matrix variable separated with a." (semicolon). For
example: "/cars;color=red;year=2012" . Multiple values may be either *," (comma) separated
“color=red, green, blue" or the variable name may be repeated
"color=red;color=green; color=blue"
Ifa URL is expected to contain matrix variables, the request mapping pattern must represent them with a
URI template. This ensures the request can be matched correctly regardless of whether matrix variables are
present or not and in what order they are provided.
Below is an example of extracting the matrix variable “q"
npe:idocs spring otepring-rameworkidocs/9.2xlepring ramework-eferencellimve html 16178+3723, 2207 17. Web MVC framework
// GET /pets/42;q=11;r=22
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET)
public void findPet(@PathVariable String petId, @Matrixvariable int q) (
// petid
4
42
Since all path segments may contain matrix variables, in some cases you need to be more specific to
identify where the variable is expected to be:
// GET fonners/423.
1/pets/21;q=22
GRequestMapping(value = "/ouners/{onnerId}/pets/{petId}", method = RequestNethod. ET)
public void findPet(
GHotrixvarioble(value="q", pathVar="onnerTd") int a1,
@Matrixvariable(vatue="q", pathVar="petIa") int q2) {
U qt == 11
UU q2 == 22
‘Amatrix variable may be defined as optional and a default value specified:
// GET /pets/a2
@RequestMapping(value = "/pets/{petId)", method = RequestMethod. GET)
public void findPet(@Matrixvartable(required=true, defaultValue="1") int q) {
Mqzt
All matrix variables may be obtained in a Map:
UL GET Jowners/42;:
15
(2/pets/213q=225 5=23
@RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
public void findPet(
GMatrixvoriable MapeString, String> matrixvars,
GMatrixVoriable(pathVar="petTd"") Map petMatrixVars) {
J matrixvar:
// petMatrixvars: ["q
q” : [11,22], "r" : 12,"
a2, "s" : 23]
2 23]
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html site“13123, 2207 17. Wed MYC framework
Note that to enable the use of matrix variables, you must set the |removeSeni colonContent | property of
RequestMappingHandlerMapping) to false), By default itis set to false
In the MVC namespace, the ‘mvc:annotation-driven’ element has an “enableMatrixVariables’ attribute that
should be set to “true”. By default it is set to “false
Consumable Media Types
You can narrow the primary mapping by specifying a list of consumable media types. The request will be
matched only if the Content-Type request header matches the specified media type. For example:
ontrotter
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
public void addPet (@RequestBody Pet pet, Model model) {
// implenentation omitted
+
Consumable media type expressions can also be negated as in !text/plain to match to all requests other than
those with Content-Type of text/plain.
‘The consumes condition is supported on the type and on the method level. Unlike most other
conditions, when used at the type level, method-level consumable types override rather than
extend type-level consumable types.
Producible Media Types
You can narrow the primary mapping by specifying a list of producible media types. The request will be
matched only if the Accept request header matches one of these values. Furthermore, use of the produces
condition ensures the actual content type used to generate the response respects the media types specified
in the produces condition. For example:
@controtter
@RequestMapping(value = "/pets/{petId)", method = RequestMethod.GET, produces="application/j
@ResponseBody
public Pet getPet(@Pathvariable String petId, Model model) (
// inplenentation omitted
y
4 »
Just like with consumes, producible media type expressions can be negated as in /text/plain to match to all
requests other than those with an Accept header value of text/plain.
npe:idocs spring olspring-rameworkidocs/9.2xleprng ramework-eferencelimlimve htm 1878113723, 2207 17. Web MVC framework
‘The produces condition is supported on the type and on the method level. Unlike most other
conditions, when used at the type level, method-level producible types override rather than
extend type-level producible types.
Request Parameters and Header Values
You can narrow request matching through request parameter conditions such as “myParam"|, “!myParam"),
or “nyParam=myValue" . The first two test for request parameter presence/absence and the third for a
specific parameter value, Here is an example with a request parameter value condition:
@controLler
GRequestMapping("/owners/{ownerTd}")
public class RelativePathUritemplateController {
G@RequestMapping(value = "/pets/{petId}", method = RequestNethod.GET, params="nyParam=nyVal
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model)
// implementation omitted
)
y
>
The same can be done to test for request header presence/absence or to match based on a specific request
header value:
Gcontrotter
@RequestMapping("/owners/{ownerTd}")
public class RelativePathUriTemplateController {
@RequestMapping(value = “/pets", method = RequestMethod.GET, headers="nyHeader=myValue” )
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model)
// implementation omitted
}
+
G _Atrough you can match to Content-Type and Accept header values using media type wild
cards (for example “content-type=text*" will match to “text/plain” and "text/htm), itis
recommended to use the consumes and produces conditions respectively instead. They are
intended specifically for that purpose.
17.3.3 Defining @RequestMapping handler methods
‘An @RequestMapping handler method can have a very flexible signatures. The supported method
arguments and return values are described in the following section. Most arguments can be used in arbitrary
tps docs. spring iolsring-ramewarkldocel.2xlepringramework-ferencentmlinve Mtl 19178113723, 2207 17. Web MVC framework
order with the only exception of BindingResult arguments. This is described in the next section
@ _ Soring 3.1 introduced a new set of support classes for @RequestMapping) methods called
RequestMappingHandlerMapping and RequestMappingHandlerAdapter respectively.
‘They are recommended for use and even required to take advantage of new features in Spring
MVC 3.1 and going forward. The new support classes are enabled by default from the MVC
namespace and with use of the MVC Java config but must be configured explicitly if using
neither.
Supported method argument types
The following are the supported method arguments:
+ Request or response objects (Servlet API). Choose any specific request or response type, for example
ServietRequest or HttpServietRequest
+ Session object (Servlet API): of type HttpSession . An argument of this type enforces the presence of a
corresponding session. As a consequence, such an argument is never null
@ _ Session access may not be thread-safe, in particular in a Servlet environment. Consider
setting the |RequestMappingHandlerAdapter'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 Serviet/Portlet
API
+ java.util. Locale for the current request locale, determined by the most specific locale resolver
available, in effect, the configured |LocaleResolver in a Servlet environment.
+ java.io. Inputstream|/ java.io.Reader for access to the request’s content, This value is the raw
InputStream/Reader as exposed by the Servlet API.
+ java.io. OutputStream / java. io.Writer| for generating the response's content. This value is the
raw OutputStream/Writer as exposed by the Servlet API.
+ Java.security.Principal containing the currently authenticated user.
+ @athvariable annotated parameters for access to URI template variables. See the section called
“URI Template Patterns’,
+ @atrixvariable annotated parameters for access to name-value pairs located in URI path
segments. See the section called “Matrix Variables’
+ @RequestParam annotated parameters for access to specific Servlet request parameters. Parameter
values are converted to the declared method argument type. See the section called “Binding request
parameters to method parameters with @RequestParam?.
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html 2ore“13123, 2207 47. Web MVC framework
+ @RequestHeader | annotated parameters for access to specific Servet request HTTP headers.
Parameter values are converted to the declared method argument type.
+ @RequestBody | annotated parameters for access to the HTTP request body. Parameter values are
converted to the declared method argument type using HttpMessageConverter's, See the se
called “Mapping the request body with the @RequestBody annotation’.
+ @RequestPart| annotated parameters for access to the content of a "multipartform-data” request part
See Section 17.10.5, "Handling a file upload request from programmatic clients” and Section 17.10,
‘Spring's multipart (file upload) support”
+ Httpentity> parameters for access to the Servlet request HTTP headers and contents. The request
stream will be converted to the entity body using |HttpMessageConverter's, See the section called
“Using [HttpEntity>”
+ java.util.Map / org. springframework.ui.Model / org. springframework.ui.ModelMap for
enriching the implicit model that is exposed to the web view.
+ org. springframework.web.servlet.mvc. support .Redirectattributes to specify the exact set of
attributes to use in case of a redirect and also to add flash attributes (attributes stored temporarily on the
server-side to make them available to the request after the redirect). Redirectattributes| is used
instead of the implicit model if the method returns a “redirect:" prefixed view name or RedirectView
+ Command or form objects to bind request parameters to bean properties (via setters) or directly to fields,
with customizable type conversion, depending on @1nitBinder methods and/or the HandlerAdapter
configuration. See the webBindingInitializer | property on RequestMappingHandlerAdapter.
‘Such command objects along with their validation results will be exposed as model attributes by default,
using the command class class name - e.g. model attribute "orderAddress" for a command object of type
"some.package. OrderAddress”. The ModelAttribute annotation can be used on a method argument
to customize the model attribute name used.
+ org. springframework.validation.Errors /
org. springframework. validation. BindingResult| validation results for a preceding command or
form object (the immediately preceding method argument).
+ org. springframework.web. bind. support.SessionStatus status handle for marking form
processing as complete, which triggers the cleanup of session attributes that have been indicated by the
@SessionAttributes annotation at the handler type level
+ org. springframework.web.util.UriComponent sBuilder a builder for preparing a URL relative to
the current request’s host, port, scheme, context path, and the literal part of the servlet mapping
The Errors or BindingResult parameters have to follow the model object that is being bound
immediately as the method signature might have more that one model object and Spring will create a
separate BindingResult instance for each of them so the following sample won't work:
Example 17.1. Invalid ordering of BindingResult and @ModelAttribute
@RequestMapping(method = RequestMethod. POST)
public String processsubnit (@Nodelattribute("pet”) Pet pet,
Nodel model, BindingResult result) { . }
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html are“13123, 2207 17. Wed MYC framework
Note, that there is a Model parameter in between Pet and BindingResult . To get this working you have
to reorder the parameters as follows:
@RequestMapping(method = RequestMethod. POST)
public String processSubmit (@Modelattribute("pet") Pet pet,
BindingResult result, Model model) { ~ }
Supported method return types.
The following are the supported return types:
+ A ModelAndView object, with the model implicitly enriched with command objects and the results of
@odelattribute 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 that is interpreted as the logical 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 ifthe method handles the response itself (by writing the response content directly, declaring an
argument of type |ServletResponse /|HttpServletResponse for that purpose) or ifthe view name is
supposed to be implicitly determined through a Request ToViewNameTrans lator | (not declaring a
response argument in the handler method signature),
+ IF the method is annotated with @ResponseBody , the return type is written to the response HTTP body.
The return value will be converted to the declared method argument type using
HttpMessageConverter s. See the section called "Mapping the response body with the
@ResponseBody annotation’.
+ AlHttpentity> or ResponseEntity>| object to provide access to the Servlet response HTTP.
headers and contents. The entity body will be converted to the response stream using
HttpMessageConverter s. See the section called "Using Httpentity>”
+ A Callable> | can be retumed when the application wants to produce the return value
asynchronously in a thread managed by Spring MVC.
+ A DeferredResult> can be returned when the application wants to produce the return value from a
thread of its own choosing,
+ Any other return type is considered to be a 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
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html 2are113723, 2207 17. Web MVC framework
based on the retum type class name). The mode! is implicitly enriched with command objects and the
results of @ModelAttribute annotated reference data accessor methods.
Binding request parameters to method parameters with @RequestParam
Use the @RequestParam annotation to bind request parameters to a method parameter
your controller.
The following code snippet shows the usage:
@Controtter
GRequestMapping("/pets")
@SessionAttributes("pet")
public class EditPettorm {
Move
G@RequestMapping(method = RequestMethod. GET)
Public String setupForm(@RequestParam("petId") int petId, ModelMap model) {
Pet pet = this.clinic.loadPet (petId);
model.addattribute("pet", pet);
return “petForn";
}
Move
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.,
@RequestParam(value="id", required=false)
Type conversion is applied automatically if the target method parameter type is not String . See the section
called “Method Parameters And Type Conversion’.
Mapping the request body with the @RequestBody annotation
The @RequestBody method parameter annotation indicates that a method parameter should be bound to
the value of the HTTP request body. For example:
G@Requesthapping(value = "/something", method = RequestMethod. PUT)
public void handle(@nequestBody String body, Writer writer) throws IOException {
writer write body);
?
You convert the request body to the method argument by using an HttpMessageConverter .
HttpMessageConverter is responsible for converting from the HTTP request message to an object and
converting from an object to the HTTP response body. The RequestMappingHandleradapter supports the
@RequestBody | annotation with the following default |jHttpMessageConverters
+ ByteArraylttpMessageConverter converts byte arrays.
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html 2are“13123, 2207 47. Web MVC framework
+ StringhttpiessageConverter converts strings.
+ FormittpMessageConverter| converts form data toffrom a MultiValueMap
+ SourcettpMessageConverter converts to/from a javax.xml.transform.Source.
For more information on these converters, see Message Converters. Also note that if using the MVC
namespace or the MVC Java config, a wider range of message converters are registered by default. See
Enabling the MVC Java Config or the MVC XML Namespace for more information.
If you intend to read and write XML, you will need to configure the MarshallingHttpMessageConverter
with a specific Marshaller| and an Unmarshaller| implementation from the org. springframework.oxm
package. The example below shows how to do that directly in your configuration but if your application is
configured through the MVC namespace or the MVC Java config see Enabling the MVC Java Config or the
MVC XML Namespace instead.
The Httpentity is similar to @RequestBody and @ResponseBody |. Besides getting access to the request
and response body, |HttpEntity (and the response-specific subclass ResponseEntity ) also allows
access to the request and response headers, like so:
GRequestMapping(“/sonething")
Public Responseéntity handle(Httpentity requestentity) throws UnsupportedEnc
String requestHeader = requesténtity.getHeaders().getFirst("MyRequestHeader"));
byte[] requestBody = requestentity.getBody();
// do sonething with request header and body
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("MyResponselieader”, “MyValue")s
return new ResponseEntity("Hello World", responseHeaders, HttpStatus. CREATED) ;
The above example gets the value of the MyRequestHeader | request header, and reads the body as a byte
array. Itadds the MyResponseHeader to the response, writes Hello World) to the response stream, and
sets the response status code to 201 (Created).
‘As with @RequestBody and @ResponseBody , Spring uses HittpMessageConverter to convert from and to
the request and response streams. For more information on these converters, see the previous section and
Message Converters.
Using @modelattribute on a method
The @Modelattribute annotation can be used on methods or on method arguments, This section explains
its usage on methods while the next section explains its usage on method arguments.
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html 2si7e‘13123, 2207 47. Web MVC framework
An G@Modelattribute on a method indicates the purpose of that method is to add one or more model
attributes. Such methods support the same argument types as @RequestMapping methods but cannot be
mapped directly to requests. Instead @ModelAttribute| methods in a controller are invoked before
@RequestMapping methods, within the same controller. A couple of examples:
// Add one attribute
// The return value of the method is added to the model under the name “account
// You can customize the name via @ModeLAttribute("myAccount")
@ModeLattribute
Public Account addAccount (@RequestParam String number) {
return accountManager.findAccount (number) ;
y
// Add multiple attributes
@ModeLattribute
public void populateModel (@RequestParam String number, Model model) (
model. addAttribute(accountManager. FindAccount (number) ;
// add more ...
G@Modelattribute methods are used to populate the model with commonly needed attributes for example
to fill a drop-down with states or with pet types, or to retrieve a command object like Account in order to use
it to represent the data on an HTML form. The latter case is further discussed in the next section.
Note the two styles of @ModelAttribute| methods. In the first, the method adds an attribute implicitly by
returning it. In the second, the method accepts a Model and adds any number of model attributes to it. You
can choose between the two styles depending on your needs.
Acontroller can have any number of @ModelAttribute methods, All such methods are invoked before
@RequestMapping methods of the same controller.
@Modelattribute methods can also be defined in an @Control lerAdvice-annotated class and such
methods apply to all controllers, The @ControllerAdvice annotation is a component annotation allowing
implomentation classes to be autodetected through classpath scanning.
@ _What happens when a model attribute name is not explicitly specified? In such cases a default
name is assigned to the model attribute based on its type. For example if the method returns
an object of type Account |, the default name used is "account". You can change that through
the value of the @Modelattribute annotation. If adding attributes directly to the Model , use
the appropriate overloaded addattribute(..)) method - i.e, with or without an attribute
name.
The @ModelAttribute| annotation can be used on @RequestMapping methods as well. In that case the
retum value of the @RequestMapping) method is interpreted as a model attribute rather than as a view
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html 2078“13123, 2207 47. Web MVC framework
name. The view name is derived from view name conventions instead much like for methods returning void
— see Section 17.123, “The View- RequestToViewNameTranslator ”
Using @Modelattribute on a method argument
As explained in the previous section @ModelAattribute can be used on methods or on method arguments.
This section explains its usage on method arguments.
An @odelattribute on a method argument indi
tes the argument should be retrieved from the model. If
not present in the model, the argument should be instantiated first and then added to the model. Once
present in the model, the argument's fields should be populated from all request parameters that have
matching names, This is known as data binding in Spring MVC, a very useful mechanism that saves you
from having to parse each form field individually.
@RequestMapping (value="/ouners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit (@ModelAttribute Pet pet) {
?
Given the above example where can the Pet instance come from? There are several options:
+ Itmay already be in the model due to use of @SessionAttributes — see the section called “Using
@SessionAttributes to store model attributes in the HTTP session between requests
+ Itmay already be in the model due to an @ModelAttribute method in the same controller — as
explained in the previous section.
+ It may be retrieved based on a URI template variable and type converter (explained in more detail
below)
+ It may be instantiated using its default constructor.
An @MlodelAttribute method is a common way to to retrieve an attribute from the database, which may
optionally be stored between requests through the use of |@Sessionattributes | In some cases it may be
convenient to retrieve the attribute by using an URI template variable and a type converter. Here is an
example
@RequestMapping(value="/accounts/{account}", method = RequestMethod. PUT)
public String save(@ModelAttribute("account") Account account) {
}
In this example the name of the model attribute (i.e. "account" matches the name of a URI template
variable. If you register Converter) form tag.
In addition to data binding you can also invoke validation using your own custom validator passing the same
BindingResult that was used to record data binding errors. That allows for data binding and validation
errors to be accumulated in one place and subsequently reported back to the user:
@RequestMapping (value="/ouners/{onnerId}/pets/{petId}/edit", method = RequestMethod. POST)
public String processSubmit (@ModelAttribute("pet") Pet pet, BindingResult result) {
new PetValidator().validate(pet, result);
if (result.hastrrors()) {
return “petForn";
+
Mire
(Or you can have validation invoked automatically by adding the JSR-303 @val id) annotation:
@RequestMapping(value="/onners/{omnertd}/pets/{petid}/edit", method = RequestMethod. POST)
public String processSubnit (@Valid @ModelAttribute("pet") Pet pet, BindingResult result) {
if (result.hasErrors()) {
return “petForn”;
y
Moves
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html are“13123, 2207 17. Wed MYC framework
See Section 7.8, "Spring 3 Validation’ and Chapter 7, Validation, Data Binding, and Type Conversion for
details on how to configure and use validation
Using @Sessionattributes to store model attributes in the HTTP session between
requests
The type-level @SessionAttributes| annotation declares session attributes used by a specific handler.
This will typically list the names of model attributes or types 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, specifying the model attribute name:
controller
@RequestMapping("/editPet.do")
@sessionattributes("pet”)
public class EditPetForm {
Move
}
@ _ When using controller interfaces (¢.g., for AOP proxying), make sure to consistently put all
your mapping annotations - such as @RequestMapping and @SessionAttributes - on the
controller interface rather than on the implementation class.
Specifying redirect and flash attributes
By default all model attributes are considered to be exposed as URI template variables in the redirect URL.
Of the remaining attributes those that are primitive types or collections/arrays of primitive types are
automatically appended as query parameters.
In annotated controllers however the model may contain additional attributes originally added for rendering
purposes (e.g. drop-down field values). To gain precise control over the attributes used in a redirect scenario,
an @RequestMapping method can declare an argument of type RedirectAttributes and use it to add
attributes for use in RedirectView.. If the controller method does redirect, the content of
Redirectattributes is used, Otherwise the content of the default Model is used.
The RequestMappingHandlerAdapter provides a flag called “ignoreDefaultModelOnRedirect™ that
can be used to indicate the content of the default Model | should never be used if a controller method
redirects. Instead the controller method should declare an attribute of type Redirectattributes or ifit
doesn't do so no attributes should be passed on to RedirectView). Both the MVC namespace and the MVC.
Java config keep this flag set to False jin order to maintain backwards compatibility. However, for new
applications we recommend setting it to true.
The |Redirectattributes| interface can also be used to add flash attributes. Unlike other redirect
attributes, which end up in the target redirect URL, flash attributes are saved in the HTTP session (and
ntps:idocs sprig ilspng-Fameworldocsd2x/spang-famowork~ofarencaimline hk 20178“13123, 2207 47. Web MVC framework
hence do not appear in the URL). The model of the controller serving the target redirect URL automatically
receives these flash attributes after which they are removed from the session. See Section 17.6, “Using flash
attributes" for an overview of the general support for flash attributes in Spring MVC.
Working with "application/x-www-form-urlencoded" data
The previous sections covered use of @ModelAttribute| to support form submission requests from browser
clients. The same annotation is recommended for use with requests from non-browser clients as well.
However there is one notable difference when it comes to working with HTTP PUT requests. Browsers can
submit form data via HTTP GET or HTTP POST. Non-browser clients can also submit forms via HTTP PUT.
This presents a challenge because the Servlet specification requires the
ServletRequest..getParameter*() family of methods to support form field access only for HTTP POST,
not for HTTP PUT.
To support HTTP PUT and PATCH requests, the spring-web module provides the fier
HttpPutFormContentFilter , which can be configured in web.xml
httpPutFormFilter
org. springframework.web. filter .HttpPutFormContentFilter
#ilter>
httpPutFormFilterdispatcherServlet
#iltter-mapping>
dispatcherServletorg. springfranework.web. servlet .DispatcherServlet
The above filter intercepts HTTP PUT and PATCH requests with content type
appli cation/x-www- forn-urlencoded), reads the form data from the body of the request, and wraps the
ServletRequest in order to make the form data available through the
ServletRequest..getParameter*() family of methods.
@ As HetpputFormcontentFilter consumes the body of the request, it should not be
‘configured for PUT or PATCH URLS that rely on other converters for
application/x-www-form-urlencoded . This includes
@RequestBody MultiValueMap and
HttpEntity>
Mapping cookie values with the @CookieValue annotation
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html sore113723, 2207 17. Web MVC framework
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
JSESSTONID=415A4AC178CS9DACE@B2CICA727CDD84
The following code sample demonstrates how to get the value of the JSESSIONID cookie:
@RequestMapping("/dispLayHeaderInfo.do")
public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie) {
Ms
Type conversion is applied automatically if the target method parameter type is not String . See the section
called “Method Parameters And Type Conversion”.
This annotation is supported for annotated handler methods in Serviet 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 sample request header:
Host localhost :8080
Accept ‘text/html, application/xhtml+xnl, application/xml ;q=0.9
Accept -Language fr,en-gb3q=0-7,en;q-0.3
Accept-Encoding gzip,deflate
Accept-Charset 1S0-8859-1, utf-85
Keep-Alive 300
The following code sample demonstrates how to 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) {
Wave
Type conversion is applied automatically if the method parameter is not String. See the section called
"Method Parameters And Type Conversion’.
hitpsdocs. spring jolspring-rameworkdocs!3.2xiepring-
vework
awe113723, 2207 17. Web MVC framework
Built-in support is available for converting a comma-separated string into an array/collection of
strings or other types known to the type conversion system. For example a method parameter
annotated with @RequestHeader(“Accept") may be of type String) but also String[] or
List
This annotation is supported for annotated handler methods in Servlet and Portlet environments.
Method Parameters And Type Conversion
String-based values extracted from the request including request parameters, path variables, request
headers, and cookie values may need to be converted to the target type of the method parameter or field
(e.g., binding a request parameter to a field in an @ModelAttribute parameter) they're bound to. If the
target type is not String, Spring automatically converts to the appropriate type. All simple types such as
int, long, Date, etc. are supported. You can further customize the conversion process through a
WebDataBinder (see the section called “Customizing WebDataBinder initialization’) or by registering
Formatters| with the FormattingConversionService (see Section 7.6, “Spring 3 Field Formatting")
Custor
19 WebDataBinder initialization
To customize request parameter binding with PropertyEditors through Spring's WebDataBinder |, you can
use @InitBinder -annotated methods within your controller, @InitBinder] methods within an
@ControllerAdvice class, or provide 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 that initialize the WebDataBinder that will be used
to populate command and form object arguments of annotated handler methods.
Such init-binder methods support all arguments that @RequestMapping) supports, except for commandiform
objects and corresponding validation result objects. Init-binder methods must not have a retum value. Thus,
they are usually declared as void), Typical arguments include NebDataBinder| in combination with
WebRequest or java.util. Locale, allowing code to register context-specific editors.
The following example demonstrates the use of @InitBinder |to configure a CustonDateEditor for all
java.util.Date] form properties.
@ontrotter
public class MyFornController {
@1nitBinder
public void initBinder(WebDataBinder binder) {
SinplebateFormat dateFormat = new SimpleDateFormat(("yyyy-MM-dd");
dateFormat..setLenient(false);
binder. registerCustoneditor(Date.class, new CustonDateEditor(dateFormat, false));
npe:idoes spring olepring-rameworkidocs/9.2xleprng ramework-eferencellimve htm sare113723, 2207 17. Web MVC framework
Move
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.
processUpload(final MultipartFile file) {
return new Callablecstring>() {
public Object call() throws Exception {
We
return “soneView";
Asecond option is for the controller to return an instance of DeferredResult . In this case the return value
will also be produced from a separate thread. However, that thread is not known to Spring MVC. For
‘example the result may be produced in response to some external event such as a JMS message, a
scheduled task, etc, Here is an example controller method:
@RequestMapping("/quotes")
@ResponseBody
public DeferredResult quotes() {
DeferredResult deferredResult = new DeferredResult();
// Save the deferredResult in in-memory queue ...
return deferredResult;
+
// In some other thread...
deferredResult. setResult (data);
npe:idocs spring olepring-rameworkidocs/9.2xlepring ramework-eferencallinve htm sare“13123, 2207 47. Web MVC framework
This may be difficult to understand without any knowledge of the Servlet 3 async processing feature. It would
certainly help to read up on it. At a very minimum consider the following basic facts:
+ A/ServletRequest can be put in asynchronous mode by calling request.startAsync() - The main
effect of doing so is that the Servlet, as well as any Filters, can exit but the response will remain open
allowing some other thread to complete processing,
+ The call to request. startAsync()| retums an AsyncContext | which can be used for further control
‘over asyne processing, For example it provides the method dispatch , which can be called from an
application thread in order to “dispatch” the request back to the Servet container. An async dispatch is
similar to a forward except it is made from one (application) thread to another (Servlet container) thread
Whereas a forward occurs synchronously in the same (Servlet container) thread.
+ ServletRequest | provides access to the current DispatcherType , which can be used to distinguish it
a Servlet or a|Filter| is processing on the initial request processing thread and when it is
processing in an async dispatch,
With the above in mind, the following is the sequence of events for async request processing with a
Callable : (1) Controller returns a Cal lable , (2) Spring MVC starts async processing and submits the
Callable to a TaskExecutor for processing in a separate thread, (3) the DispatcherServiet and all
Filter's exit the request processing thread but the response remains open, (4) the Callable produces a
result and Spring MVC dispatches the request back to the Servlet container, (5) the DispatcherServlet is
invoked again and processing resumes with the asynchronously produced result from the Callable . The
exact sequencing of (2), (3), and (4) may vary depending on the speed of execution of the concurrent
threads.
The sequence of events for async request processing with a DeferredResult is the same in principal
except i's up to the application to produce the asynchronous result from some thread: (1) Controller returns
a DeferredResult and saves it in some in-memory queue or list where it can be accessed, (2) Spring
MVC starts async processing, (3) the DispatcherServlet_ and all configured Filters exit the request.
processing thread but the response remains open, (4) the application sets the DeferredResult from some
thread and Spring MVC dispatches the request back to the Servlet container, (5) the DispatcherServlet
is invoked again and processing resumes with the asynchronously produced result.
Explaining the motivation for async request processing and when or why to use it are beyond the scope of
this document. For further information you may wish to read this blog post series.
Exception Handling for Async Requests
What happens if a Callable returned from a controller method raises an Exception while being executed?
The effect is similar to what happens when any controller method raises an exception. It is handled by a
matching @ExceptionHandler method in the same controller or by one of the configured
HandleréxceptionResolver instances.
@ _ Under the covers, when a callable raises an Exception, Spring MVC stil dispatches to the
Servlet container to resume processing, The only difference is that the result of executing the
npe:idocs spring olepring-rameworkidocs/9.2xleprng ramework-eferencalilimve html ssi7e113723, 2207 17. Web MVC framework
Callable is an Exception that must be processed with the configured
HandleréxceptionResolver instances.
When using a DeferredResult , you have a choice of calling its setErrorResult (Object)) method and
provide an Exception) or any other Object you'd like to use as the result. If the result is an Exception, it
will be processed with a matching @ExceptionHandler method in the same controller or with any
configured HandlerExceptionResolver instance.
Intercepting Async Requests
An existing HandlerInterceptor | can implement AsyncHandlerInterceptor , which provides one
additional method afterConcurrentHandl ingStarted|. It is invoked after async processing starts and
‘when the initial request processing thread is being exited. See the Javadoc of AsyncHandlerInterceptor
for more details on that.
Further options for async request lifecycle callbacks are provided directly on DeferredResult |, which has
the methods onTimeout (Runnable) and |onCompletion (Runnable) . Those are called when the async
request is about to time out or has completed respectively, The timeout event can be handled by setting the
DeferredResult’ to some value. The completion callback however is final and the result can no longer be
set
Similar callbacks are also available with a Callable|. However, you will need to wrap the Callable in an
instance of WebAsyncTask and then use that to register the timeout and completion callbacks, Just like with
DeferredResult|, the timeout event can be handled and a value can be returned while the completion
event is final,
You can also register a CallableProcessingInterceptor ora
DeferredResultProcessinginterceptor globally through the MVC Java config or the MVC namespace
Those interceptors provide a full set of callbacks and apply every time a |Callable or a DeferredResult
is used.
Configuration for Async Request Proces:
Serviet 3 Asyne Config
To use Servlet 3 async request processing, you need to update web. xml_ to version 3.0:
has an sub-clement.
Those allow you to configure the default timeout value to use for async requests, which if not set depends on
the underlying Servlet container (e.g. 10 seconds on Tomcat). You can also configure an
AsyncTaskExecutor to use for executing Callable| instances returned from controller methods. It is
highly recommended to configure this property since by default Spring MVC uses
‘SimpleAsyncTaskExecutor . The MVC Java config and the MVC namespace also allow you to register
CallableprocessingInterceptor and DeferredResultProcessingInterceptor instances.
If you need to override the default timeout value for a specific DeferredResult , you can do so by using the
appropriate class constructor. Similarly, for a Callable|, you can wrap it in a WebAsyncTask and use the
appropriate class constructor to customize the timeout value. The class constructor of WebAsyncTask| also
allows providing an AsyncTaskExecutor
17.3.5 Testing Controllers
The spring-test module offers first class support for testing annotated controllers, See Section 11.3.6,
"Spring MVC Test Framework”.
17.4 Handler mappings
In previous versions of Spring, users were required to define one or more HandlerMapping) beans in the
web application context to map incoming web requests to appropriate handlers. With the introduction of
annotated controllers, you generally don't need to do that because the RequestMappingHandlerMapping
npe:idocs spring olepring-rameworkidocs/9,2xleprng ramework-eferencellimve html ane“13123, 2207 47. Web MVC framework
automatically looks for @RequestMapping) annotations on all /@ontroller| beans. However, do keep in
mind that all HandlerMapping classes extending from AbstractHandlerMapping have the following
properties that you can use to customize their behavior:
interceptors
List of interceptors to use. HandlerInterceptor s are discussed in Section 17.4.1, “Intercepting
requests with a HandlerInterceptor ”
defaultHandler
Default handler to use, when this handler mapping does not result in a matching handler.
order:
Based on the value of the order property (see the org. springframework. core. Ordered interface),
Spring sorts all handler mappings available in the context and applies the first matching handler.
alwaysUseFullpath
If true) , Spring uses the full path within the current Serviet context to find an appropriate handler. If
false (the default), the path within the current Servlet mapping is used. For example, if a Servlet is
mapped using /testing/*] and the |alwaysUseFul1Path property is set to true,
/testing/viewPage.html is used, whereas if the property is set to false, /viewPage.html is used.
urlDecode
Defaults to true, as of Spring 2.5. If you prefer to compare encoded paths, set this flag to false
However, the HttpServletRequest | always exposes the Serviet path in decoded form. Be aware that
the Servlet path will not match when compared with encoded paths.
The following example shows how to configure an interceptor:
package sanples;
public class TimeBasedAccessInterceptor extends HandlerInterceptordapter {
private int openingTime;
private int closingTine;
public void setOpeningTime(int openingTime) {
‘this.openingTime = openingTine;
public void setClosingTime(int closingTime) {
‘this.closingTime = closingTime;
public boolean pretandle(
npe:idoes spring olepring-rameworkidocs/9.2xleprng ramework-eferencellimve htm sore