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

问题描述:

我正在使用@Bean注释定义bean,并尝试使用名称连接它们,但接收到异常。无法在Spring Boot应用程序中注入多个ObjectMapper bean

完整的例子

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 
+0

对不起尼尔,这是一个错字,当我输入在这里。我在我的代码中使用了正确的限定符。 –

+0

我无法复制此内容。请发布完整的示例。 –

+0

@SotiriosDelimanolis,发布完整的例子。该服务器甚至没有启动,我点击运行后弹出应用程序,我得到一个错误。 –

默认情况下,Spring Boot定义了一个类型为MappingJackson2HttpMessageConverter的bean并尝试向其中注入ObjectMapper。这通常可以让你简单地声明一个ObjectMapper@Bean,以任何你需要的方式进行配置,并让Spring Boot为你做其余的事情。

在这里,因为你声明了其中的两个,所以这已经不起作用。

一个解决方案,as described in the documentation,是注释@Bean的定义,你想注入的为@Primary

如果要替换默认ObjectMapper完全定义类型的 @Bean并将其标记为@Primary

例如,

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

春季启动将使用那一个。

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

最后,如果你提供任何@Bean S型 MappingJackson2HttpMessageConverter的那么他们将取代MVC配置默认 值。

例如(从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; 
} 
+0

非常感谢您的详细解释。这帮了我很多,解决了我的问题:-) –