Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/spring-projects/spring-boot/llms.txt

Use this file to discover all available pages before exploring further.

Spring Boot auto-configures Spring MVC with sensible defaults, but most production applications need to adjust behavior: tuning how HTTP messages are read and written, customizing serialization, rendering templates, handling exceptions globally, or uploading files. This guide walks through the most common Spring MVC customization tasks in a Spring Boot application.

Custom HttpMessageConverters

Spring MVC uses HttpMessageConverter instances to read HTTP request bodies and write HTTP response bodies. Spring Boot registers a set of converters automatically, and you can add to or replace them.
1

Declare a customizer bean

Declare a ServerHttpMessageConvertersCustomizer bean to add or override converters. The following example adds a converter before the default set:
import org.springframework.boot.http.converter.autoconfigure.ServerHttpMessageConvertersCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyHttpMessageConvertersConfiguration {

    @Bean
    public ServerHttpMessageConvertersCustomizer myCustomizer() {
        return customizers -> customizers.addCustomConverter(new MyCustomHttpMessageConverter());
    }

}
Use withJsonConverter(...) to replace the default JSON converter instead of adding a new one.
2

Inject converters into RestTemplate (optional)

If you need to inject the configured converters into a RestTemplate, use the HttpMessageConverters convenience bean that Spring Boot always provides:
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
import org.springframework.web.client.RestTemplate;

@Bean
public RestTemplate myRestTemplate(HttpMessageConverters converters) {
    RestTemplate template = new RestTemplate();
    template.setMessageConverters(converters.getConverters());
    return template;
}
If you declare a bean of type JacksonJsonHttpMessageConverter, it replaces the default Jackson converter rather than supplementing it.

Configure the Jackson ObjectMapper

Spring Boot auto-configures a JsonMapper (Jackson’s ObjectMapper equivalent) and exposes properties to tune it without writing code.

Property-based configuration

Jackson features map directly to application.properties or application.yaml properties:
Feature categoryProperty prefixExample values
Serializationspring.jackson.serialization.<feature>true, false
Deserializationspring.jackson.deserialization.<feature>true, false
Mapperspring.jackson.mapper.<feature>true, false
Default property inclusionspring.jackson.default-property-inclusionalways, non_null, non_empty
Date/timespring.jackson.datatype.datetime.<feature>true, false
For example, to enable pretty-printed JSON output:
spring:
  jackson:
    serialization:
      indent_output: true
Property names use relaxed binding, so indent_output matches the enum constant INDENT_OUTPUT. You can also use indent-output or INDENT_OUTPUT.

Programmatic customization

To customize the JsonMapper.Builder used by auto-configuration, declare a JsonMapperBuilderCustomizer bean. Boot’s own customizer has order 0; yours can run before or after it:
import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyJacksonConfiguration {

    @Bean
    public JsonMapperBuilderCustomizer myJsonMapperBuilderCustomizer() {
        return builder -> builder.enable(SerializationFeature.INDENT_OUTPUT);
    }

}
To register a custom JacksonModule application-wide, simply declare it as a Spring bean — it is automatically picked up and applied to all JsonMapper instances created by the builder.

Global exception handling with @ControllerAdvice

Use @ControllerAdvice to centralize exception handling across multiple controllers. Spring Boot integrates this with its own error infrastructure — unhandled exceptions fall through to ErrorController.
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice(basePackageClasses = SomeController.class)
public class MyControllerAdvice {

    @ResponseBody
    @ExceptionHandler(MyException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    MyErrorBody exceptionHandler(MyException exception) {
        return new MyErrorBody(exception.getMessage());
    }

}
Spring Boot also supports RFC 9457 Problem Details. Set spring.mvc.problemdetails.enabled=true to have Spring MVC produce application/problem+json responses automatically.
Place static HTML or template files under src/main/resources/public/error/ (or src/main/resources/templates/error/) named after the status code or a mask:
src/main/resources/
  public/
    error/
      404.html       # exact status code
  templates/
    error/
      5xx.ftlh       # 5xx series mask
To disable the default whitelabel error page entirely, set:
spring:
  web:
    error:
      whitelabel:
        enabled: false
You should then provide your own error view or controller, otherwise the servlet container’s default error page is shown.

Serving static files

By default, Spring Boot serves static content from these classpath locations (in order):
  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public/
All static files placed in src/main/resources/static/ or src/main/resources/public/ are automatically served. To change the URL path pattern for static resources:
spring:
  mvc:
    static-path-pattern: "/resources/**"
To override the source locations entirely:
spring:
  web:
    resources:
      static-locations:
        - "classpath:/custom-static/"
        - "classpath:/public/"
Do not place static content in src/main/webapp/ when packaging as a jar. This directory is only effective for war packaging and is silently ignored by most build tools for jars.
To enable content-hash-based cache busting:
spring:
  web:
    resources:
      chain:
        strategy:
          content:
            enabled: true
            paths: "/**"

Configuring Thymeleaf view resolution

Spring Boot auto-configures Thymeleaf when spring-boot-starter-thymeleaf is on the classpath. The ThymeleafViewResolver resolves view names by wrapping them with a prefix and suffix. Default settings:
PropertyDefault
spring.thymeleaf.prefixclasspath:/templates/
spring.thymeleaf.suffix.html
To customize:
spring:
  thymeleaf:
    prefix: "classpath:/views/"
    suffix: ".html"
    cache: false   # disable template caching during development
Templates are placed in src/main/resources/templates/ and are automatically picked up. A controller returning the string "home" renders src/main/resources/templates/home.html.
Set spring.thymeleaf.cache=false during development so that template changes are reflected without restarting the application.

Adding an MVC interceptor

Add interceptors by declaring a WebMvcConfigurer bean — this approach preserves all Spring Boot MVC auto-configuration.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyHandlerInterceptor())
                .addPathPatterns("/api/**");
    }

}
Do not annotate a WebMvcConfigurer configuration class with @EnableWebMvc. Doing so disables all Spring Boot MVC auto-configuration and requires you to configure everything manually.

Switching from Tomcat to Jetty

Spring Boot uses Tomcat by default. To switch to Jetty, exclude the Tomcat starter and add the Jetty starter.
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webmvc</artifactId>
    <exclusions>
        <!-- Exclude the Tomcat dependency -->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- Use Jetty instead -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
No other code changes are required. Spring Boot detects Jetty on the classpath and auto-configures it.

Configuring multipart file uploads

Spring Boot configures multipart support automatically using properties from MultipartProperties. Defaults: 1 MB per file, 10 MB per request.
1

Set limits in application properties

spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 10MB
      max-request-size: 50MB
      file-size-threshold: 2KB
      location: "/tmp"
Set max-file-size to -1 to allow unlimited file sizes.
2

Accept files in your controller

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
public class FileUploadController {

    @PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file) {
        // process file.getInputStream()
        return "Uploaded: " + file.getOriginalFilename();
    }

}
Use the container’s built-in multipart support (the default) rather than Apache Commons FileUpload. It avoids an extra dependency and integrates cleanly with the Servlet API’s jakarta.servlet.http.Part.

Build docs developers (and LLMs) love