java之SpringBoot消费REST源,HttpMessageConverter报错

Leo_wl 阅读:67 2023-09-06 19:40:43 评论:0

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

我遵循了本指南并使其与 springboot 和 maven 一起工作,( https://spring.io/guides/gs/consuming-rest/ )

现在我正在尝试换掉他们的 URL 并添加一个来自视频游戏的 URL ( 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]”返回的格式。这让我觉得很奇怪,因为该字符集是 Java 字符集类中的默认值,并且转到 URL,文本看起来像普通文本。

我尝试手动添加 StringHttpMessageConverter,但没有成功。

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

    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 类中用作通配符,所以我很惊讶地看到双通配符尝试失败。

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

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

谢谢

请您参考如下方法:

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

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

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

如果您不能修改服务器响应,则需要编写并注册您自己的 HttpMessageConverter(它可以扩展 Spring 类,请参阅 AbstractGenericHttpMessageConverter 及其子类)来读取和转换文本/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); 
    } 
} 


标签:Spring Boot
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号