diff --git a/spring-framework-reference/src/mvc.xml b/spring-framework-reference/src/mvc.xml index f320f099ea7..a20516bd740 100644 --- a/spring-framework-reference/src/mvc.xml +++ b/spring-framework-reference/src/mvc.xml @@ -1295,8 +1295,8 @@ public void handle(@RequestBody String body, Writer writer) throws IOException {
- Mapping the response body with the @ResponseBody - annotation + Mapping the response body with the @ResponseBody + annotation Similar to @RequestBody, there is the @ResponseBody annotation. This @@ -1550,15 +1550,15 @@ public class MyFormController {
Handler mappings - 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: - + 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: @@ -1615,16 +1615,17 @@ public class MyFormController { subclasses of org.springframework.web.servlet.handler.AbstractUrlHandlerMapping). - The following example shows how to override the default mapping, and add an interceptor: + The following example shows how to override the default mapping, and + add an interceptor: - - - - - - + <beans> + <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> + <property name="interceptors"> + <bean class="example.MyInterceptor"/> + </property> + </bean> -]]> +<beans>
Intercepting requests - the @@ -1841,10 +1842,11 @@ public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter { <row> <entry><classname>ContentNegotiatingViewResolver</classname></entry> - <entry>An implementation of the <interfacename>ViewResolver</interfacename> - interface that that resolves a view based on the request file name or <literal>Accept</literal> header. - See <xref linkend="mvc-multiple-representations"/>. - </entry> + <entry>An implementation of the + <interfacename>ViewResolver</interfacename> interface that that + resolves a view based on the request file name or + <literal>Accept</literal> header. See <xref + linkend="mvc-multiple-representations" />.</entry> </row> </tbody> </tgroup> @@ -2068,139 +2070,138 @@ public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter { </section> </section> - <section id="mvc-multiple-representations"> - <title><classname>ContentNegotiatingViewResolver</classname> +
+ <classname>ContentNegotiatingViewResolver</classname> - 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 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 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. + 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 + + 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 + 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. - + 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. + 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. + 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.. + 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 + 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'. + 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. + 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. - + + 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 + 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 + @Controller public class ContentController { private List<SampleContent> contentList = new ArrayList<SampleContent>(); @@ -2214,9 +2215,7 @@ public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter { } } - -
- +
@@ -2813,9 +2812,11 @@ public class FileUploadBean {
<interfacename>@ExceptionResolver</interfacename> - As an alternative to implementing the HandlerExceptionResolver, you - can use the @ExceptionHandler. The @ExceptionHandler method annotation is - used within a controller to specify which method will be invoked when an + As an alternative to implementing the + HandlerExceptionResolver, you can use the + @ExceptionHandler. The + @ExceptionHandler method annotation is used + within a controller to specify which method will be invoked when an exception of a specific type is thrown during the execution of controller methods. For example @@ -2851,7 +2852,6 @@ public class SimpleController { ModelAndView object. Please refer to the API documentation for more details.
-
@@ -3189,6 +3189,49 @@ public class SimpleController {
+
+ ETag support + + An ETag + (entity tag) is an HTTP response header returned by an HTTP/1.1 compliant + web server used to determine change in content at a given URL. It can be + considered to be the more sophisticated successor to the + Last-Modified header. When a server returns a + representation with an ETag header, the client can use this header in + subsequent GETs, in an If-None-Match header. If the + content has not changed, the server will return 304: Not + Modified. + + Support for ETags is provided by the servlet filter + ShallowEtagHeaderFilter. Since it is a plain + Servlet Filter, and thus can be used in combination with any web + framework. The ShallowEtagHeaderFilter filter + creates so-called shallow ETags (as opposed to deep ETags, more about that + later). The way it works is quite simple: the filter simply caches the + content of the rendered JSP (or other content), generates an MD5 hash over + that, and returns that as an ETag header in the response. The next time a + client sends a request for the same resource, it uses that hash as the + If-None-Match value. The filter notices this, renders + the view again, and compares the two hashes. If they are equal, a + 304 is returned. It is important to note that this + filter will not save processing power, as the view is still rendered. The + only thing it saves is bandwidth, as the rendered response is not sent + back over the wire. + + You configure the ShallowEtagHeaderFilter in + web.xml: + + <filter> + <filter-name>etagFilter</filter-name> + <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class> +</filter> + +<filter-mapping> + <filter-name>etagFilter</filter-name> + <servlet-name>petclinic</servlet-name> +</filter-mapping> +
+
Further Resources