SoFunction
Updated on 2025-04-27

SpringBoot customizes three strategies to implement content negotiation

In project development, the same resource usually needs to be provided to different clients in multiple representations. For example, a browser may want to get HTML pages, while a mobile application may require JSON data. This mechanism of dynamically selecting the response format according to client needs is content negotiation.

Content negotiation can realize the need to serve multiple clients on the same API endpoint, greatly improving the flexibility and reusability of Web services. As the mainstream Java application development framework, SpringBoot provides powerful and flexible content negotiation support, allowing developers to easily implement resource expressions in multiple forms.

Content negotiation basis

What is content negotiation

Content negotiation is an important concept in the HTTP protocol, allowing the same resource URL to provide representations in different formats according to the client's preferences. This process is usually done by the server and the client: the client informs the server of its expected content type, and the server selects the most appropriate form of expression based on its own capabilities to return.

Content negotiation mainly relies on media type (Media Type), also known as MIME type, such asapplication/jsonapplication/xmltext/htmlwait.

Content Negotiation Structure in SpringBoot

SpringBoot is based on Spring MVC's content negotiation mechanism, which is implemented through the following components:

  • ContentNegotiationManager: Responsible for coordinating the content negotiation process
  • ContentNegotiationStrategy: Define how to determine the media type requested by the client
  • HttpMessageConverter: Responsible for converting between Java objects and HTTP request/responsive bodies

SpringBoot supports multiple content negotiation policies by default, which can be configured and combined according to needs.

Policy 1: Content negotiation based on request header

Principle analysis

Request header-based content negotiation is one of the most consistent ways to comply with the HTTP specification, which checks theAcceptHeader to determine the response format expected by the client. For example, when the client sendsAccept: application/jsonWhen header, the server will return data in JSON format first.

This strategyHeaderContentNegotiationStrategyImplementation is SpringBoot's default content negotiation strategy.

Configuration method

In SpringBoot, content negotiation based on request headers is enabled by default, without additional configuration. If explicit configuration is required, you canorAdded in:

spring:
  mvc:
    contentnegotiation:
      favor-parameter: false
      favor-path-extension: false

Or via Java configuration:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer
            .defaultContentType(MediaType.APPLICATION_JSON)
            .favorParameter(false)
            .favorPathExtension(false)
            .ignoreAcceptHeader(false);  // Make sure that Accept headers are not ignored    }
}

Practical examples

First, create a basic REST controller:

@RestController
@RequestMapping("/api/products")
public class ProductController {
    
    private final ProductService productService;
    
    public ProductController(ProductService productService) {
         = productService;
    }
    
    @GetMapping("/{id}")
    public Product getProduct(@PathVariable Long id) {
        return (id);
    }
    
    @GetMapping
    public List<Product> getAllProducts() {
        return ();
    }
}

The client can passAcceptHeader requests data in different formats:

// Request JSON formatGET /api/products HTTP/1.1
Accept: application/json

// Request XML formatGET /api/products HTTP/1.1
Accept: application/xml

// Request HTML formatGET /api/products HTTP/1.1
Accept: text/html

To support XML responses, you need to add relevant dependencies:

<dependency>
    <groupId></groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

Pros and cons analysis

advantage

  • Comply with HTTP specifications and is a recommended practice for RESTful API
  • No need to modify the URL, keep the URL simple
  • Applicable to all HTTP clients
  • Cache-friendly

shortcoming

  • Need to be correctly set by the clientAccepthead
  • It is not convenient to directly test different formats in the browser
  • Some proxy servers may modify or remove HTTP headers

Applicable scenarios

  • RESTful API Design
  • API interface for programmatic clients
  • When multiple clients need different representations of the same data

Strategy 2: Content negotiation based on URL path extension

Principle analysis

Content negotiation based on URL path extension determines the response format expected by the client through the file extension at the end of the URL. For example,/api/Request JSON format, and/api/Request XML format.

This strategyPathExtensionContentNegotiationStrategyTo implement, it is important to note that starting from Spring 5.3, this policy has been disabled by default for security reasons.

Configuration method

existorEnable in:

spring:
  mvc:
    contentnegotiation:
      favor-path-extension: true
      # Clearly specify the mapping relationship between path extension and media type      media-types:
        json: application/json
        xml: application/xml
        html: text/html

Or via Java configuration:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer
            .favorPathExtension(true)
            .ignoreAcceptHeader(false)
            .defaultContentType(MediaType.APPLICATION_JSON)
            .mediaType("json", MediaType.APPLICATION_JSON)
            .mediaType("xml", MediaType.APPLICATION_XML)
            .mediaType("html", MediaType.TEXT_HTML);
    }
}

Safety precautions

Since path expansion policy may lead to path traversal attacks, it is disabled by default after Spring 5.3. If necessary, it is recommended:

useUrlPathHelperSecurity configuration:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        (false);
        (urlPathHelper);
    }
}

Clearly define supported media types to avoid automatic detection

Practical examples

There is no need to modify the controller. After configuring the extension policy, the client can access it through the URL extension:

// Request JSON formatGET /api/

// Request XML formatGET /api/

To better support path extensions, you can use URL rewrite filters:

@Component
public class UrlRewriteFilter extends OncePerRequestFilter {
    
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                  HttpServletResponse response,
                                  FilterChain filterChain) throws ServletException, IOException {
        
        HttpServletRequest wrappedRequest = new HttpServletRequestWrapper(request) {
            @Override
            public String getRequestURI() {
                String uri = ();
                return urlRewrite(uri);
            }
        };
        
        (wrappedRequest, response);
    }
    
    private String urlRewrite(String url) {
        // Implement URL rewriting logic, such as adding missing file extensions        return url;
    }
}

Pros and cons analysis

advantage

  • Easy to test different formats in your browser
  • No special HTTP header required
  • The URL intuitively indicates the desired response format

shortcoming

  • Not in line with RESTful API design principles (the same resource has multiple URIs)
  • There is a security risk (path traversal attack)
  • After Spring 5.3, it is disabled by default and requires additional configuration
  • May conflict with certain web frameworks or routing systems

Applicable scenarios

  • Quickly switch different response formats in development and testing environment
  • Traditional web applications need to provide multiple formats at the same time
  • Need to support clients that cannot easily modify HTTP headers

Strategy 3: Content negotiation based on request parameters

Principle analysis

Based on the content negotiation of request parameters, the response format expected by the client is determined by querying parameters through URLs. For example,/api/products?format=jsonRequest JSON format, and/api/products?format=xmlRequest XML format.

This strategyParameterContentNegotiationStrategyImplementation, needs to be explicitly enabled.

Configuration method

existorConfiguration in:

spring:
  mvc:
    contentnegotiation:
      favor-parameter: true
      parameter-name: format  # Default is "format", customizable      media-types:
        json: application/json
        xml: application/xml
        html: text/html

Or via Java configuration:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer
            .favorParameter(true)
            .parameterName("format")
            .ignoreAcceptHeader(false)
            .defaultContentType(MediaType.APPLICATION_JSON)
            .mediaType("json", MediaType.APPLICATION_JSON)
            .mediaType("xml", MediaType.APPLICATION_XML)
            .mediaType("html", MediaType.TEXT_HTML);
    }
}

Practical examples

Using the previous controller, the client accesses different formats by adding query parameters:

// Request JSON formatGET /api/products?format=json

// Request XML formatGET /api/products?format=xml

Pros and cons analysis

advantage

  • Easy to test different formats in the browser
  • No modification to the resource's basic URL path
  • More secure than path extension
  • Simple configuration, easy to understand

shortcoming

  • Not fully compliant with RESTful API design principles
  • Increases the complexity of the URL
  • May be confused with other query parameters in the application
  • Not cache friendly (same URL returns different content)

Applicable scenarios

  • API documentation or test page for developers
  • You need to directly test different response formats in the browser
  • Public APIs require simple format switching mechanisms
  • Inconvenient to set up HTTP header environment

Combination strategy to achieve advanced content negotiation

Policy combination configuration

In practical applications, multiple strategies are often combined to provide maximum flexibility:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer
            .favorParameter(true)
            .parameterName("format")
            .ignoreAcceptHeader(false)  // Don't ignore Accept header            .defaultContentType(MediaType.APPLICATION_JSON)
            .mediaType("json", MediaType.APPLICATION_JSON)
            .mediaType("xml", MediaType.APPLICATION_XML)
            .mediaType("html", MediaType.TEXT_HTML);
    }
}

This configuration enables content negotiation based on parameters and request headers, and uses parameters first, and if there are no parameters, use Accept headers.

Customize content negotiation strategy

For more complex requirements, customizableContentNegotiationStrategy

public class CustomContentNegotiationStrategy implements ContentNegotiationStrategy {
    
    @Override
    public List&lt;MediaType&gt; resolveMediaTypes(NativeWebRequest request) throws HttpMediaTypeNotAcceptableException {
        String userAgent = ("User-Agent");
        
        // Content negotiation based on User-Agent        if (userAgent != null) {
            if (("Mozilla")) {
                return (MediaType.TEXT_HTML);
            } else if (("Android") || ("iPhone")) {
                return (MediaType.APPLICATION_JSON);
            }
        }
        
        // Return JSON by default        return (MediaType.APPLICATION_JSON);
    }
}

Register a custom policy:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        ((
            new CustomContentNegotiationStrategy(),
            new HeaderContentNegotiationStrategy()
        ));
    }
}

Response optimization practice

Provide optimized output for different manifestations:

@RestController
@RequestMapping("/api/products")
public class ProductController {
    
    private final ProductService productService;
    
    // General JSON/XML response    @GetMapping("/{id}")
    public ProductDto getProduct(@PathVariable Long id) {
        Product product = (id);
        return new ProductDto(product);  // Convert to DTO to avoid physical class exposure    }
    
    // Special treatment for HTML    @GetMapping(value = "/{id}", produces = MediaType.TEXT_HTML_VALUE)
    public ModelAndView getProductHtml(@PathVariable Long id) {
        Product product = (id);
        
        ModelAndView mav = new ModelAndView("product-detail");
        ("product", product);
        ("relatedProducts", (product));
        
        return mav;
    }
    
    // Simplified response to mobile clients    @GetMapping(value = "/{id}", produces = "application/+json")
    public ProductMobileDto getProductForMobile(@PathVariable Long id) {
        Product product = (id);
        return new ProductMobileDto(product);  // Contains streamlined information required by mobile terminal    }
}

in conclusion

SpringBoot provides a flexible and powerful content negotiation mechanism to meet the needs of various application scenarios. In actual development, appropriate policies or combination policies should be selected according to specific needs, while paying attention to security, performance and API design best practices.

This is the article about SpringBoot customization of content negotiation. For more relevant SpringBoot content negotiation content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!