no suitable HttpMessageConverter found for response type(给RestTemplate添加自定义的HttpMessageConverter)

  • Post author:
  • Post category:其他




异常信息

nested exception is org.springframework.web.client.RestClientException: Could not 
extract response: no suitable HttpMessageConverter found for response type [class 
java.util.Map] and content type [application/javascript;charset=utf-8]] with root cause



触发异常的代码

Map weatherMap = restTemplate.getForObject(url, Map.class);



分析原因

  • 异常信息说的是:没给content-type是[application/javascript;charset=utf-8]的response找到合适的HttpMessageConverter
  • 如果content-type=application/json就没问题
  • 所以异常是application/javascript导致的,即:RestTemplate自带的HttpMessageConverters中没用能处理content-type=application/javascript的response的HttpMessageConverter



解决方法

Map weatherMap = restTemplate.getForObject(url, Map.class);

url是别人的接口,所以无法修改response的content-type,只能给restTemplate加一个能处理content-type=application/javascript的response的HttpMessageConverter

  • RestTemplate默认自带了几个HttpMessageConverter(在RestTemplate的无参构造方法中)
	public RestTemplate() {
		this.messageConverters.add(new ByteArrayHttpMessageConverter());
		this.messageConverters.add(new StringHttpMessageConverter());
		this.messageConverters.add(new ResourceHttpMessageConverter(false));
		try {
			this.messageConverters.add(new SourceHttpMessageConverter<>());
		}
		catch (Error err) {
			// Ignore when no TransformerFactory implementation is available
		}
  	...
}
  • 自定义能处理content-type=application/javascript的response的HttpMessageConverter
**
 * 解决:RestTemplate自带的HttpMessageConverters中没用能处理
 * content-type=application/javascript的response的HttpMessageConverter
 */
public class MyApplicationJavascriptHttpMessageConverter extends AbstractHttpMessageConverter {
    /**
     * restTemplate获得的响应的content-type满足下面的条件
     * 才会被该HttpMessageConverter处理
     */
    public MyApplicationJavascriptHttpMessageConverter() {
        // application/javascript
        super(new MediaType("application", "javascript", Charset.forName("UTF-8")));
    }

    /**
     * 检查传入的字节码是否符合要求
     *
     * @param clazz
     * @return 返回true才会执行readInternal()
     */
    @Override
    protected boolean supports(Class clazz) {
        return true;
    }

    /**
     * 将restTemplate获得的响应转化成clazz对应的类型
     *
     * @param clazz
     * @param inputMessage restTemplate获得的响应
     * @return
     */
    @Override
    protected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        //restTemplate发送请求后获得的响应
        InputStream body = inputMessage.getBody();

        //将响应转成对应类型
        // 就是restTemplate.getForObject(url, Map.class)的返回值
        return JSON.parseObject(body, clazz);
    }

    /**
     * 还不知道该方法的功能
     * 该方法也不会被执行到
     *
     * @param o
     * @param outputMessage
     * @throws IOException
     * @throws HttpMessageNotWritableException
     */
    @Override
    protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        //do nothing
        System.out.println("do nothing");
    }
}
  • 将自定义的HttpMessageConverter加到restTemplate的HttpMessageConverters中
    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();

        //处理content-type=application/javascript的HttpMessageConverter
        restTemplate.getMessageConverters().add(new MyApplicationJavascriptHttpMessageConverter());

        return restTemplate;
    }



版权声明:本文为csdn17355456893原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。