【问题标题】:Can't inject multiple ObjectMapper beans in Spring Boot application无法在 Spring Boot 应用程序中注入多个 ObjectMapper bean
【发布时间】:2016-01-18 08:45:42
【问题描述】:

我正在使用 @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

【问题讨论】:

  • Sorry Nir,我在这里打字时打错了。我在我的代码中使用了正确的限定符。
  • 我无法重现这个。请发布一个完整的示例。
  • @SotiriosDelimanolis ,发布了完整的示例。服务器甚至没有启动,我点击 run as spring boot app 后出现错误。
  • 我没有看到你在任何地方手动注入ObjectMapper
  • 是的,我只是暂时排除了它,因为 Bean 定义本身导致服务器无法启动。

标签: jackson spring-boot


【解决方案1】:

默认情况下,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;
}

Spring Boot 将使用那个。

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

最后,如果您提供任何@Beans 类型 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 2023-02-01
    • 2019-07-27
    • 1970-01-01
    • 2018-07-28
    • 1970-01-01
    • 2018-01-02
    相关资源
    最近更新 更多