使用curl命令:
curl -u 591bf65f50057469f10b5fd9:0cf17f9b03d056ds0e11e48497e506a2 https://backend.tdk.com/api/devicetypes/59147fd79e93s12e61499ffe/messages
我收到了JSON回复:
{"data":[{"device":"18SE62","time":1494516023,"data":"3235","snr":"36.72",...
我将响应保存在txt文件中并使用jackson解析它,一切都很好
ObjectMapper mapper = new ObjectMapper();
File f = new File(getClass().getResource
("/result.json").getFile());
MessageList messageList = mapper.readValue(f, MessageList.class);
我认为我应该使用RestTemplate得到相同的结果,但事实并非如此
RestTemplate restTemplate = new RestTemplate();
MessageList messageList =
restTemplate.getForObject("http://592693f43c87815f9b8145e9:f099c85d84d4e325a2186c02bd0caeef@backend.tdk.com/api/devicetypes/591570373c87894b4eece34d/messages", MessageList.class);
我收到了错误
Exception in thread "main" org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.tdk.domain.backend.MessageList] and content type [text/html;charset=iso-8859-1]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:109)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:655)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:287)
at com.tdk.controllers.restful.client.RestTemplateExample.main(RestTemplateExample.java:27)
我尝试设置contentType:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
MessageList messageList =
restTemplate.getForObject(url, entity, MessageList.class);
然后我收到了编译错误
The method getForObject(String, Class<T>, Object...) in the type RestTemplate is not applicable for the arguments (String, HttpEntity<String>,
Class<MessageList>)
我还试图添加一个Jackson Message转换器
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
//Add the Jackson Message converter
messageConverters.add(new MappingJackson2HttpMessageConverter());
//Add the message converters to the restTemplate
restTemplate.setMessageConverters(messageConverters);
MessageList messageList =
restTemplate.getForObject(url, MessageList.class);
但后来我收到了这个错误:
Exception in thread "main" org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.tdk.domain.backend.MessageList] and content type [text/html;charset=iso-8859-1]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:109)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:655)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:287)
at com.tdk.controllers.restful.client.RestTemplateExample.main(RestTemplateExample.java:51)
我也尝试添加类
@Configuration
@EnableWebMvc
public class MvcConf extends WebMvcConfigurationSupport {
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(converter());
addDefaultHttpMessageConverters(converters);
}
@Bean
MappingJackson2HttpMessageConverter converter() {
MappingJackson2HttpMessageConverter converter
= new MappingJackson2HttpMessageConverter();
return converter;
}
}
但我得到了错误:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.tdk.domain.backend.MessageList] and content type [text/html;charset=iso-8859-1]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:109)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:655)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:287)
答案 0 :(得分:57)
这里的主要问题是从服务中收到的内容类型[text / html; charset = iso-8859-1] ,但实际内容类型应为 application / json; charset = iso-8859-1
为了克服这个问题,您可以引入自定义消息转换器。并为所有类型的响应注册它(即忽略响应内容类型标题)。就像这样
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
//Add the Jackson Message converter
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
// Note: here we are making this converter to process any kind of response,
// not only application/*json, which is the default behaviour
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
messageConverters.add(converter);
restTemplate.setMessageConverters(messageConverters);
答案 1 :(得分:18)
我遇到了一个非常类似的问题,结果很简单;我的客户端不包括Jackson依赖项,即使所有编译的代码正确,但JSON的自动魔术转换器未被包含在内。见this RestTemplate-related solution.
简而言之,我在我的pom.xml中添加了一个Jackson依赖项,它只是起作用了:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.1</version>
</dependency>
答案 2 :(得分:6)
虽然接受的答案解决了OP的原始问题,但我怀疑大多数人通过Google搜索找到此问题的可能性(从统计角度而言)可能是一个完全不同的问题,恰好抛出相同的没有合适的HttpMessageConverter找到异常。
幕后发生的事情是MappingJackson2HttpMessageConverter
吞噬了其canRead()
方法中发生的任何异常,该方法应该能够自动检测有效载荷是否适合json解码。该异常被一个简单的布尔值返回所代替,该布尔值基本上传达了抱歉,我不知道如何将该消息解码到更高级别的API(RestClient
)。只有在所有其他转换器的canRead()方法返回false之后,更高级别的API才会抛出找不到合适的HttpMessageConverter 异常,从而完全掩盖了真正的问题。
对于尚未找到根本原因的人(例如您和我,但不是OP),解决此问题的方法是在onMappingJackson2HttpMessageConverter.canRead()
上放置调试器断点,然后在任意位置启用通用断点例外,然后点击继续。下一个例外是真正的根本原因。
我的具体错误恰巧是其中一个bean引用了缺少正确的反序列化注释的接口。
答案 3 :(得分:3)
如果 @Ilya Dyoshin 的上述回复仍无法检索, 尝试将响应转换为String对象。
(我自己认为错误是由Ilya的代码片段解决的,检索到的响应是来自服务器的失败(错误)。)
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
ResponseEntity<String> st = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
并转换为ResponseObject DTO(Json)
Gson g = new Gson();
DTO dto = g.fromJson(st.getBody(), DTO.class);
答案 4 :(得分:2)
在我的情况下,@ Ilya Dyoshin的解决方案不起作用:不允许使用媒体类型“ *”。 我通过在MockRestServiceServer初始化期间以这种方式将新的转换器添加到restTemplate来解决此错误:
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter =
new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(
Arrays.asList(
MediaType.APPLICATION_JSON,
MediaType.APPLICATION_OCTET_STREAM));
restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
mockServer = MockRestServiceServer.createServer(restTemplate);
(基于Yashwant Chavan在名为Technicalkeeda的博客上提出的解决方案)
JN Gerbaux
答案 5 :(得分:1)
在我的情况下,这是由运行时类路径中缺少杰克逊核心,杰克逊注释和杰克逊数据绑定jar引起的。 它没有抱怨通常的ClassNothFoundException异常,而是最初问题中提到的错误。
答案 6 :(得分:1)
请添加具有 jackson databind 包的共享依赖项。希望这能解决问题。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
答案 7 :(得分:1)
通过这种方式,您可以使用 resttemplate 获取对象响应并使用 MediaType.APPLICATION_JSON
public List<Employee> getListofEmployee()
{
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<List<Employee>> response = restTemplate.exchange("http://hello-server/rest/employees",
HttpMethod.GET,entity, new ParameterizedTypeReference<List<Employee>>() {});
return response.getBody(); //this returns List of Employee
}
答案 8 :(得分:0)
其他可能的解决方案:我试图用私有类实例(在我的工作类内部定义)映射restTemplate.getForObject的结果。它不起作用,但是如果我在自己的文件中将对象定义为public,则它可以正常工作。
答案 9 :(得分:0)
当响应缺少该字段时,Spring会将默认内容类型设置为octet-stream
。您所需要做的就是添加一个消息转换器来解决此问题。
答案 10 :(得分:0)
我尝试使用Feign时遇到了同样的问题,据我了解,HTTP消息转换器会有所帮助,但想了解如何实现。
@FeignClient(name = "mobilesearch", url = "${mobile.search.uri}" ,
fallbackFactory = MobileSearchFallbackFactory.class,
configuration = MobileSearchFeignConfig.class)
public interface MobileSearchClient {
@RequestMapping(method = RequestMethod.GET)
List<MobileSearchResponse> getPhones();
}
您必须对解码器MobileSearchFeignConfig使用客户配置
public class MobileSearchFeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public Decoder feignDecoder() {
return new ResponseEntityDecoder(new SpringDecoder(feignHttpMessageConverter()));
}
public ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(new MappingJackson2HttpMessageConverter());
return new ObjectFactory<HttpMessageConverters>() {
@Override
public HttpMessageConverters getObject() throws BeansException {
return httpMessageConverters;
}
};
}
public class MappingJackson2HttpMessageConverter extends org.springframework.http.converter.json.MappingJackson2HttpMessageConverter {
MappingJackson2HttpMessageConverter() {
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.valueOf(MediaType.TEXT_HTML_VALUE + ";charset=UTF-8"));
setSupportedMediaTypes(mediaTypes);
}
}
}