76. Spring MVC

Spring Boot has a number of starters that include Spring MVC. Note that some starters
include a dependency on Spring MVC rather than include it directly. This section answers
common questions about Spring MVC and Spring Boot.

76.1 Write a JSON REST Service

Any Spring @RestController in a Spring Boot application should render JSON response by
default as long as Jackson2 is on the classpath, as shown in the following example:

As long as MyThing can be serialized by Jackson2 (true for a normal POJO or Groovy
object), then localhost:8080/thing serves a JSON representation of it by
default. Note that, in a browser, you might sometimes see XML responses, because browsers
tend to send accept headers that prefer XML.

76.2 Write an XML REST Service

If you have the Jackson XML extension (jackson-dataformat-xml) on the classpath, you
can use it to render XML responses. The previous example that we used for JSON would
work. To use the Jackson XML renderer, add the following dependency to your project:

You may also want to add a dependency on Woodstox. It is faster than the default StAX
implementation provided by the JDK and also adds pretty-print support and improved
namespace handling. The following listing shows how to include a dependency on
Woodstox:

If Jackson’s XML extension is not available, JAXB (provided by default in the JDK) is
used, with the additional requirement of having MyThing annotated as
@XmlRootElement, as shown in the following example:

To get the server to render XML instead of JSON, you might have to send an
Accept: text/xml header (or use a browser).

76.3 Customize the Jackson ObjectMapper

Spring MVC (client and server side) uses HttpMessageConverters to negotiate content
conversion in an HTTP exchange. If Jackson is on the classpath, you already get the
default converter(s) provided by Jackson2ObjectMapperBuilder, an instance of which
is auto-configured for you.

The ObjectMapper (or XmlMapper for Jackson XML converter) instance (created by
default) has the following customized properties:

MapperFeature.DEFAULT_VIEW_INCLUSION is disabled

DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES is disabled

SerializationFeature.WRITE_DATES_AS_TIMESTAMPS is disabled

Spring Boot also has some features to make it easier to customize this behavior.

You can configure the ObjectMapper and XmlMapper instances by using the environment.
Jackson provides an extensive suite of simple on/off features that can be used to
configure various aspects of its processing. These features are described in six enums (in
Jackson) that map onto properties in the environment:

Enum

Property

Values

com.fasterxml.jackson.databind.DeserializationFeature

spring.jackson.deserialization.<feature_name>

true, false

com.fasterxml.jackson.core.JsonGenerator.Feature

spring.jackson.generator.<feature_name>

true, false

com.fasterxml.jackson.databind.MapperFeature

spring.jackson.mapper.<feature_name>

true, false

com.fasterxml.jackson.core.JsonParser.Feature

spring.jackson.parser.<feature_name>

true, false

com.fasterxml.jackson.databind.SerializationFeature

spring.jackson.serialization.<feature_name>

true, false

com.fasterxml.jackson.annotation.JsonInclude.Include

spring.jackson.default-property-inclusion

always, non_null, non_absent, non_default, non_empty

For example, to enable pretty print, set spring.jackson.serialization.indent_output=true.
Note that, thanks to the use of relaxed binding, the case of indent_output does not have to match the case of the
corresponding enum constant, which is INDENT_OUTPUT.

This environment-based configuration is applied to the auto-configured
Jackson2ObjectMapperBuilder bean and applies to any mappers created by
using the builder, including the auto-configured ObjectMapper bean.

The context’s Jackson2ObjectMapperBuilder can be customized by one or more
Jackson2ObjectMapperBuilderCustomizer beans. Such customizer beans can be ordered
(Boot’s own customizer has an order of 0), letting additional customization be applied
both before and after Boot’s customization.

Any beans of type com.fasterxml.jackson.databind.Module are automatically registered
with the auto-configured Jackson2ObjectMapperBuilder and are applied to any ObjectMapper
instances that it creates. This provides a global mechanism for contributing custom
modules when you add new features to your application.

If you want to replace the default ObjectMapper completely, either define a @Bean of
that type and mark it as @Primary or, if you prefer the builder-based
approach, define a Jackson2ObjectMapperBuilder@Bean. Note that, in either case,
doing so disables all auto-configuration of the ObjectMapper.

If you provide any @Beans of type MappingJackson2HttpMessageConverter,
they replace the default value in the MVC configuration. Also, a convenience bean of type
HttpMessageConverters is provided (and is always available if you use the default MVC
configuration). It has some useful methods to access the default and user-enhanced
message converters.

76.4 Customize the @ResponseBody Rendering

Spring uses HttpMessageConverters to render @ResponseBody (or responses from
@RestController). You can contribute additional converters by adding beans of the
appropriate type in a Spring Boot context. If a bean you add is of a type that would have
been included by default anyway (such as MappingJackson2HttpMessageConverter for JSON
conversions), it replaces the default value. A convenience bean of type
HttpMessageConverters is provided and is always available if you use the default MVC
configuration. It has some useful methods to access the default and user-enhanced message
converters (For example, it can be useful if you want to manually inject them into a
custom RestTemplate).

As in normal MVC usage, any WebMvcConfigurer beans that you provide can also
contribute converters by overriding the configureMessageConverters method. However, unlike
with normal MVC, you can supply only additional converters that you need (because Spring
Boot uses the same mechanism to contribute its defaults). Finally, if you opt out of the
Spring Boot default MVC configuration by providing your own @EnableWebMvc configuration,
you can take control completely and do everything manually by using
getMessageConverters from WebMvcConfigurationSupport.

76.5 Handling Multipart File Uploads

Spring Boot embraces the Servlet 3 javax.servlet.http.Part API to support uploading
files. By default, Spring Boot configures Spring MVC with a maximum size of 1MB per
file and a maximum of 10MB of file data in a single request. You may override these
values, the location to which intermediate data is stored (for example, to the /tmp
directory), and the threshold past which data is flushed to disk by using the properties
exposed in the MultipartProperties class. For example, if you want to specify that
files be unlimited, set the spring.servlet.multipart.max-file-size property to -1.

The multipart support is helpful when you want to receive multipart encoded file data as
a @RequestParam-annotated parameter of type MultipartFile in a Spring MVC controller
handler method.

76.6 Switch Off the Spring MVC DispatcherServlet

By default, All content is served from the root of your application (/) down. If you
would rather map to a different path, you can configure one as follows:

server.servlet.path=/acme

If you have additional servlets you can declare a @Bean of type Servlet or
ServletRegistrationBean for each and Spring Boot will register them transparently to the
container. Because servlets are registered that way, they can be mapped to a sub-context
of the DispatcherServlet without invoking it.

Configuring the DispatcherServlet yourself is unusual but if you really need to do it, a
@Bean of type DispatcherServletPath must be provided as well to provide the path of
your custom DispatcherServlet.

76.7 Switch off the Default MVC Configuration

The easiest way to take complete control over MVC configuration is to provide your own
@Configuration with the @EnableWebMvc annotation. Doing so leaves all MVC
configuration in your hands.

76.8 Customize ViewResolvers

A ViewResolver is a core component of Spring MVC, translating view names in
@Controller to actual View implementations. Note that ViewResolvers are mainly
used in UI applications, rather than REST-style services (a View is not used to render
a @ResponseBody). There are many implementations of ViewResolver to choose from, and
Spring on its own is not opinionated about which ones you should use. Spring Boot, on the
other hand, installs one or two for you, depending on what it finds on the classpath and
in the application context. The DispatcherServlet uses all the resolvers it finds in
the application context, trying each one in turn until it gets a result, so, if you
add your own, you have to be aware of the order and in which position your resolver is
added.

WebMvcAutoConfiguration adds the following ViewResolvers to your context:

An InternalResourceViewResolver named ‘defaultViewResolver’. This one locates
physical resources that can be rendered by using the DefaultServlet (including static
resources and JSP pages, if you use those). It applies a prefix and a suffix to the
view name and then looks for a physical resource with that path in the servlet context
(the defaults are both empty but are accessible for external configuration through
spring.mvc.view.prefix and spring.mvc.view.suffix). You can override it by
providing a bean of the same type.

A BeanNameViewResolver named ‘beanNameViewResolver’. This is a useful member of the
view resolver chain and picks up any beans with the same name as the View being
resolved. It should not be necessary to override or replace it.

A ContentNegotiatingViewResolver named ‘viewResolver’ is added only if there are
actually beans of type View present. This is a ‘master’ resolver, delegating to all
the others and attempting to find a match to the ‘Accept’ HTTP header sent by the
client. There is a useful
blog about
ContentNegotiatingViewResolver that you might like to study to learn more, and you
might also look at the source code for detail. You can switch off the auto-configured
ContentNegotiatingViewResolver by defining a bean named ‘viewResolver’.

If you use Thymeleaf, you also have a ThymeleafViewResolver named
‘thymeleafViewResolver’. It looks for resources by surrounding the view name with a
prefix and suffix. The prefix is spring.thymeleaf.prefix, and the suffix is
spring.thymeleaf.suffix. The values of the prefix and suffix default to
‘classpath:/templates/’ and ‘.php’, respectively. You can override
ThymeleafViewResolver by providing a bean of the same name.

If you use FreeMarker, you also have a FreeMarkerViewResolver named
‘freeMarkerViewResolver’. It looks for resources in a loader path (which is
externalized to spring.freemarker.templateLoaderPath and has a default value of
‘classpath:/templates/’) by surrounding the view name with a prefix and a suffix. The
prefix is externalized to spring.freemarker.prefix, and the suffix is externalized to
spring.freemarker.suffix. The default values of the prefix and suffix are empty and
‘.ftl’, respectively. You can override FreeMarkerViewResolver by providing a bean
of the same name.

If you use Groovy templates (actually, if groovy-templates is on your classpath), you
also have a GroovyMarkupViewResolver named ‘groovyMarkupViewResolver’. It looks for
resources in a loader path by surrounding the view name with a prefix and suffix
(externalized to spring.groovy.template.prefix and spring.groovy.template.suffix).
The prefix and suffix have default values of ‘classpath:/templates/’ and ‘.tpl’,
respectively. You can override GroovyMarkupViewResolver by providing a bean of the
same name.