SpringBoot使用REST源,HttpMessageConverter错误

时间:2016-09-04 04:45:36

标签: java spring spring-boot

我是网络编程的初学者。我很感兴趣,因为有很多视频游戏API可以作为URL使用。

我按照本指南使用springboot和maven,(https://spring.io/guides/gs/consuming-rest/

现在我正在尝试换出他们的网址并从视频游戏中添加一个(http://services.runescape.com/m=itemdb_rs/api/catalogue/detail.json?item=21787

以下代码会生成以下错误:

@SpringBootApplication
public class Application {

private static final Logger log = LoggerFactory.getLogger(Application.class);

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

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    builder.additionalMessageConverters(new FakeConverter());
    return builder.build();
}

@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
    return args -> {
        Quote quote = restTemplate.getForObject(
                "http://services.runescape.com/m=itemdb_rs/api/catalogue/detail.json?item=21787", Quote.class);
                //"http://gturnquist-quoters.cfapps.io/api/random", Quote.class);
        log.info(quote.toString());
    };
}



    java.lang.IllegalStateException: Failed to execute CommandLineRunner
   at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:801) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:782) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:769) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1185) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1174) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at hello.Application.main(Application.java:25) [classes/:na]
 Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class hello.Quote] and content type [text/html;charset=ISO-8859-1]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:109) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:622) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:287) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at hello.Application.lambda$0(Application.java:37) [classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
... 6 common frames omitted

听起来,Spring RestTemplate不支持URL链接“[text / html; charset = ISO-8859-1]”返回的格式。这让我感到很奇怪,因为charset是Java Charset类中的默认值,并且转到URL,文本看起来像普通文本。

我尝试手动添加StringHttpMessageConverter,但这不起作用。

我想也许代码不能识别它所说的“text / html”的部分,所以我做了一个'FakeConverter'包装了StringHttpMessageConverter,详情如下:

    public class FakeConverter implements HttpMessageConverter{

private StringHttpMessageConverter converter;
ArrayList<MediaType> list = new ArrayList();
public FakeConverter() {
    converter = new StringHttpMessageConverter(Charset.forName("ISO-8859-1"));
}

@Override
public boolean canRead(Class arg0, MediaType arg1) {
    // TODO Auto-generated method stub
    return true;
}

@Override
public boolean canWrite(Class arg0, MediaType arg1) {
    // TODO Auto-generated method stub
    return true;
}

@Override
public List getSupportedMediaTypes() {
    // TODO Auto-generated method stub
    list.add(new MediaType("*", "text/html", Charset.forName("ISO-8859-1")));
    //list.add(new MediaType("text/html", "*", Charset.forName("ISO-8859-1")));
    //list.add(new MediaType("*", "*", Charset.forName("ISO-8859-1")));

    return list;
}

@Override
public Object read(Class arg0, HttpInputMessage arg1) throws IOException, HttpMessageNotReadableException {
    // TODO Auto-generated method stub
    return converter.read(arg0, arg1);
}

@Override
public void write(Object arg0, MediaType arg1, HttpOutputMessage arg2)
        throws IOException, HttpMessageNotWritableException {
    // TODO Auto-generated method stub
    converter.write((String)arg0, arg1, arg2);

}

}

我正在使canRead / canWrite始终为true并尝试强制它来读取URL,我尝试了所有这些不同的MediaTypes以查看是否可以让程序支持我的URL。我在这里读了另一篇文章,“*”在MediaType类中用作通配符,所以我很惊讶地看到双通配符尝试失败。

现在我迷路了,我觉得阅读链接会更容易。

请提供您的任何见解,并提出您需要的任何澄清问题,以提供更好的答案。

由于

1 个答案:

答案 0 :(得分:1)

从Spring的角度来看,使用 RestTemplate注册的HttpMessageConverter实例都不能将text / html内容转换为Quote对象。感兴趣的方法是HttpMessageConverter#canRead(Class,MediaType) 。以上所有的实现都返回false,包括GsonHttpMessageConverter,MappingJackson2MessageConverter等。

由于没有HttpMessageConverter可以读取您的HTTP响应,因此处理失败并出现异常。

如果您可以修改服务器响应,请修改它以将Content-type设置为 application / json

如果你不能修改服务器响应,你需要编写和注册你自己的HttpMessageConverter(可以扩展Spring类,参见AbstractGenericHttpMessageConverterand它的子类),它可以读取和转换text / html。

或者您可以尝试将其他媒体类型的支持添加到GsonHttpMessageConverter,

public class GsonHttpMessageConverterDemo extends GsonHttpMessageConverter {
    public GsonHttpMessageConverterDemo () {
        List<MediaType> types = Arrays.asList(
                new MediaType("text", "html", DEFAULT_CHARSET),
                new MediaType("application", "json", DEFAULT_CHARSET),
                new MediaType("application", "*+json", DEFAULT_CHARSET)
        );
        super.setSupportedMediaTypes(types);
    }
}