在Spring Boot中注册自定义MessageConverter

时间:2017-03-26 12:58:33

标签: java spring spring-boot

我想使用返回text/javascript内容类型的RESTful服务。

由于在Spring Boot中没有可以执行此操作的OOTB HttpMessageConverter,我想注册一个自定义转换器。

我发现这样做的一种方法是通过修改RestTemplate来自定义MappingJackson2HttpMessageConverter本身:

@Component
public class CustomRestTemplateProvider {
    public RestTemplate getCustomRestTemplate(MediaType mediaType) {
        MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
        jacksonConverter.setSupportedMediaTypes(Collections.singletonList(mediaType));
        List<HttpMessageConverter<?>> converters = new ArrayList<>();
        converters.add(jacksonConverter);
        return new RestTemplate(converters);
    }
}

然后,在我的服务中,只需致电getCustomRestTemplate(new MediaType("text", "javascript")

以上解决方案工作正常,但我也尝试根据Spring Boot Documentation (27.1.2)创建一个处理这一媒体类型的新转换器:

所以我创建了一个新的转换器:

@Component
public class TextJavascriptMessageConverter extends AbstractJackson2HttpMessageConverter {

    public TextJavascriptMessageConverter(ObjectMapper objectMapper) {
        super(objectMapper);
        setTextJavascriptAsSupportedMediaType();
    }

    private void setTextJavascriptAsSupportedMediaType() {
        List<MediaType> supportedMediaTypes = new ArrayList<>();
        supportedMediaTypes.add(new MediaType("text", "javascript"));
        setSupportedMediaTypes(supportedMediaTypes);
    }
}

然后尝试在文档中注册它:

@Configuration
public class ApplicationConfiguration {

    @Bean
    public HttpMessageConverters customConverters() {
        HttpMessageConverter<Object> converter = new TextJavascriptMessageConverter(new ObjectMapper());
        return new HttpMessageConverters(Collections.singletonList(converter));
    }
}

仍然,我收到一条消息,指出Could not extract response: no suitable HttpMessageConverter found for response type [class example.MyResponsee] and content type [text/javascript]

我甚至试图扩展MappingJackson2HttpMessageConverter,但这也不起作用。我错过了什么?另外,为此创建一个新的转换器是好的做法,还是可以接受现有的转换器(如我在第一个例子中所示)?

3 个答案:

答案 0 :(得分:1)

文档有点模糊,但你应该能够只注册你的HttpMessageConverter bean,它会得到适当的添加。

Source:

  

上下文中存在的任何HttpMessageConverter bean都将添加到转换器列表中

由于您已经将TextJavascriptMessageConverter注册为bean(通过@Component),因此您应该能够通过自动装配HttpMessageConverters来访问所有转换器。

虽然您最好能够自动装配RestTemplateBuilder来处理为您设置restTemplate(包括转换器)。

示例:

@SpringBootApplication
public class DemoApplication {

  @Component
  public static class TextJavascriptConverter extends AbstractJackson2HttpMessageConverter {
    public TextJavascriptConverter() {
      //can use overloaded constructor to set supported MediaType
      super(new ObjectMapper(), new MediaType("text", "javascript"));
    }
  }

  @Bean
  public ApplicationRunner demoRunner(RestTemplateBuilder builder, TextJavascriptConverter javascriptConverter) {
    return args -> {
      //can autowire RestTemplateBuilder for sensible defaults (including converters)
      RestTemplate restTemplate = builder.build();

      //confirm your converter is there
      if (restTemplate.getMessageConverters().contains(javascriptConverter)) {
        System.out.println("My custom HttpMessageConverter was registered!");
      }
    };
  }

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

此外,为此创建一个新的转换器是好的做法,还是可以接受现有的转换器(如我在第一个示例中所示)?

您可能最好创建自己的转换器,否则可能会失去对原始媒体类型的支持。

答案 1 :(得分:0)

我认为您应该使用其他构造函数来明确指定媒体类型。

n <- 4
x$b <- ave(x$a, rep(seq(1, nrow(x)), each = n, length.out = nrow(x)), 
                                      FUN = function(x) sum(x)/length(x))
x
#     a         b
#1  FALSE 0.2500000
#2  FALSE 0.2500000
#3  FALSE 0.2500000
#4   TRUE 0.2500000
#5  FALSE 0.5000000
#6   TRUE 0.5000000
#7   TRUE 0.5000000
#8  FALSE 0.5000000
#9   TRUE 0.6666667
#10  TRUE 0.6666667
#11 FALSE 0.6666667

答案 2 :(得分:0)

你应该能够定义一个新的MappingJackson2HttpMessageConverter bean,它将被Boot选中并加载到默认值上。

@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
     MappingJackson2HttpMessageConverter jacksonConverter = new 
           MappingJackson2HttpMessageConverter();
     jacksonConverter.setSupportedMediaTypes
          (Collections.singletonList(mediaType)); 
     return jacksonConverter;
}