无法在 Spring 引导应用程序中注入多个 ObjectMapper bean

Can't inject multiple ObjectMapper beans in Spring Boot application

我正在使用 @Bean 注释定义 bean 并尝试使用 name 连接它们,但收到异常。

完整示例

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import com.fasterxml.jackson.databind.ObjectMapper;

@SpringBootApplication
@ComponentScan({"com.example"})
public class SampleSpringBootApplication {

    public static void main(String[] args) {
        SpringApplication.run(SampleSpringBootApplication.class, args);
    }


    @Bean
    public ObjectMapper scmsObjectMapper() {
        com.fasterxml.jackson.databind.ObjectMapper responseMapper = new com.fasterxml.jackson.databind.ObjectMapper();
        return responseMapper;
    }

    @Bean
    public ObjectMapper scmsWriteObjectMapper() {
        com.fasterxml.jackson.databind.ObjectMapper responseMapper = new com.fasterxml.jackson.databind.ObjectMapper();
        return responseMapper;
    }
}

控制器

package com.example;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SampleController {

    @RequestMapping(method={RequestMethod.GET}, value="sample/hello", produces=MediaType.APPLICATION_JSON_VALUE)
    @ResponseStatus(HttpStatus.OK)
    public @ResponseBody ResponseEntity<String> getCart() {
        return new ResponseEntity<String>("Hello", HttpStatus.OK);
    }


}

build.gradle

buildscript {
    ext {
        springBootVersion = '1.2.7.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
        classpath('io.spring.gradle:dependency-management-plugin:0.5.2.RELEASE')
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot' 
apply plugin: 'io.spring.dependency-management' 

jar {
    baseName = 'Sample-SpringBoot'
    version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
    compile('org.springframework.boot:spring-boot-starter')
    testCompile('org.springframework.boot:spring-boot-starter-test') 
    compile("org.springframework.boot:spring-boot-starter-web:1.2.3.RELEASE")
    compile('com.fasterxml.jackson.core:jackson-databind:2.5.1')
}


eclipse {
    classpath {
         containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
         containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.7'
}

异常

 Caused by:
 org.springframework.beans.factory.NoUniqueBeanDefinitionException: No
 qualifying bean of type [com.fasterxml.jackson.databind.ObjectMapper]
 is defined: expected single matching bean but found 2:
 scmsObjectMapper,scmsWriteObjectMapper

默认情况下,Spring Boot 定义了一个类型为 MappingJackson2HttpMessageConverter 的 bean,并尝试向其中注入一个 ObjectMapper。这通常允许您简单地声明一个 ObjectMapper @Bean,按照您需要的方式配置它,然后让 Spring Boot 为您完成剩下的工作。

在这里,这适得其反,因为您声明了其中两个。

一种解决方案,as described in the documentation,是将要注入的 @Bean 定义注释为 @Primary

If you want to replace the default ObjectMapper completely, define a @Bean of that type and mark it as @Primary.

例如,

@Bean
@Primary
public ObjectMapper scmsObjectMapper() {
    com.fasterxml.jackson.databind.ObjectMapper responseMapper = new com.fasterxml.jackson.databind.ObjectMapper();
    return responseMapper;
}

Spring 引导将使用那个。

或者,您可以声明自己的 MappingJackson2HttpMessageConverter bean 定义并在内部配置所有内容。来自同一文档

Finally, if you provide any @Beans of type MappingJackson2HttpMessageConverter then they will replace the default value in the MVC configuration.

例如(取自here

@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    jsonConverter.setObjectMapper(objectMapper);
    return jsonConverter;
}