Spring Boot 不使用配置的 Jackson ObjectMapper 和 @EnableWebMvc

Posted

技术标签:

【中文标题】Spring Boot 不使用配置的 Jackson ObjectMapper 和 @EnableWebMvc【英文标题】:Spring Boot not using configured Jackson ObjectMapper with @EnableWebMvc 【发布时间】:2018-01-25 19:25:59 【问题描述】:

我想在我的项目中使用 Jackson ObjectMapper 的配置版本(忽略空值和snake_case,也使用一些自定义模块)。

在我的大型项目中,我无法让 Spring MVC 实际使用此映射器。

build.gradle:

buildscript 
  ext 
    springBootVersion = '1.5.6.RELEASE'
  
  repositories 
    mavenCentral()
  
  dependencies 
    classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
  


apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'

version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories 
  mavenCentral()


dependencies 
  compile('org.springframework.boot:spring-boot-starter')
  compile("org.springframework.boot:spring-boot-starter-jetty:$springBootVersion")
  compile("org.springframework.boot:spring-boot-starter-web:$springBootVersion")

  compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.8.8'
  compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.8.8'

  testCompile('org.springframework.boot:spring-boot-starter-test')

我的应用程序.yml:

spring:
  application:
  name: Jackson test
jackson:
  property-naming-strategy: SNAKE_CASE
  default-property-inclusion: non_empty
debug: true

一个容器类:

public class MyLocationEntity 
    public String nameAndSnake;

一个配置类:

@Configuration
@EnableWebMvc
public class AppConfig 

还有一个控制器:

@RestController
@RequestMapping("/test")
public class TestController 

  @Autowired
  private ObjectMapper objectMapper;

  @RequestMapping(value = "/test", produces = "application/json")
  public MyLocationEntity test() throws JsonProcessingException 
    MyLocationEntity location = new MyLocationEntity();
    location.nameAndSnake = "hello world";
    String expexted = objectMapper.writeValueAsString(location);
    return location;
  

如果我现在在调试器中查看expected 的值,它是"name_and_snake":"hello world"。 但是如果我让控制器跑通实际响应是"nameAndSnake":"hello world"

当我删除 @EnableWebMvc 时,它可以工作。如何将已配置的映射器与 MVC 一起使用,而不删除 Web MVC 的其余自动配置?

【问题讨论】:

@EnableWebMvc 禁用 Spring Boot 的 Web 自动配置。你在说哪个配置的映射器?自动配置的实例有什么问题? 为什么要使用 EnableWebMvc? @JBNizet 这只是显示错误的演示项目。在这个项目中,它什么也不做。在较大的项目中需要它。 这根本不能回答我的问题。为什么在更大的项目中需要它? EnableWebMvc 禁用 web mvc 自动配置。它没有启用它。阅读文档:docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… M. Deinum 确实这么说,你不相信他……但无论如何,至少它让你阅读了文档。 【参考方案1】:

这在 Javadocs 中并不明显,但 @EnableWebMvc 禁用了 WebMvcAutoConfiguration 提供的 Spring Boot 默认 Web MVC 自动配置,包括使用由 application.yml 属性配置的 Jackson ObjectMapper bean。根据Spring Boot Reference Documentation:

9.4.7。关闭默认 MVC 配置

完全控制 MVC 配置的最简单方法是为您自己的 @Configuration 提供 @EnableWebMvc 注释。这样做会将所有 MVC 配置留在您的手中。

因此必须手动配置 MVC 配置,以便将 Spring Boot application.yml 属性与 @EnableWebMvc 注释一起使用。对此有几种不同的可能方法。

第一种方法是从WebMvcAutoConfiguration.EnableWebMvcConfiguration.configureMessageConverters() 复制Spring Boot 配置代码。这会将消息转换器(包括包含未配置的 ObjectMapperMappingJackson2HttpMessageConverter)替换为与默认 Spring Boot 配置一起使用的那些:

@Configuration
public class WebConfig implements WebMvcConfigurer 
    @Autowired
    private ObjectProvider<HttpMessageConverters> messageConvertersProvider;

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) 
        this.messageConvertersProvider
                .ifAvailable((customConverters) -> converters.addAll(customConverters.getConverters()));
    

或者,不使用默认的 Spring Boot 消息转换器列表,可以只交换 Spring Boot 提供的 ObjectMapperMappingJackson2HttpMessageConverter bean(应用了 application.yml 属性):

@Configuration
public class WebConfig implements WebMvcConfigurer 
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) 
        converters.stream()
                .filter(c -> c instanceof MappingJackson2HttpMessageConverter)
                .map(c -> (MappingJackson2HttpMessageConverter) c)
                .forEach(c -> c.setObjectMapper(objectMapper));

    

@Configuration
public class WebConfig implements WebMvcConfigurer 
    @Autowired
    private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) 
        for (int i = 0; i < converters.size(); i++) 
            if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) 
                converters.set(i, mappingJackson2HttpMessageConverter);
            
        
    

【讨论】:

以上是关于Spring Boot 不使用配置的 Jackson ObjectMapper 和 @EnableWebMvc的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot REST 端点忽略 Content-Type

初识Spring Boot (Spring Boot配置文件)

不使用spring-boot-starter-parent

使用 maven 插件设置时 Spring Boot 配置文件不活动

Spring Boot Logging 配置

Spring Boot 不使用配置的 Jackson ObjectMapper 和 @EnableWebMvc