GVKun编程网logo

HttpMessageConverter异常:RestClientException:无法写入请求:未找到合适的HttpMessageConverter

6

本文的目的是介绍HttpMessageConverter异常:RestClientException:无法写入请求:未找到合适的HttpMessageConverter的详细情况,我们将通过专业的研究

本文的目的是介绍HttpMessageConverter异常:RestClientException:无法写入请求:未找到合适的HttpMessageConverter的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于android RestClientException:找不到合适的HttpMessageConverter、Contenty类型的边界被FormHttpMessageConverter覆盖、HttpMessageConverter、httpMessageConverter 初始化性能问题的知识。

本文目录一览:

HttpMessageConverter异常:RestClientException:无法写入请求:未找到合适的HttpMessageConverter

HttpMessageConverter异常:RestClientException:无法写入请求:未找到合适的HttpMessageConverter

我正在编写一个使用RESTful服务的客户端。我需要以键,值对的形式发送请求,他们建议我为此使用Map。我正在调用的RESTful服务将仅接受JSON,而我的客户端将使用Java。实际上,它将成为现有企业EJB项目的一部分。

我已经编写了一个客户端,并且能够成功调用RESTful服务。实际上,如果我以String(JSON格式)发送请求,那么我什至会得到响应。但是我想避免将Map转换为JSON格式的字符串然后在Request中发送出去的手动工作。

我已经将Content-Type设置为application / json并创建了一个包含KeyValue对的Map。

客户端代码段:

HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);headers.add(MyConstants.JWT_AUTH_TOK, restUtil.getJWTToken());restTemplate = new RestTemplate();ModelReqVO modVO = new ModelReqVO();Map<String, String> dataMap = new HashMap<String, String>();//Setting key,value into datamap (e.g. "key1", "value1")modVO.setDataMap(dataMap);ResponseEntity<ModelRspnsVO> result = restTemplate.postForEntity(mySrvcFN, new HttpEntity(modVO, headers), ModelRspnsVO.class);

请求(ModelReqVO)类:

public class ModelReqVO {private HashMap<String, String> dataMap;ModelReqVO() {    this.dataMap = new HashMap<String, String>();}//getter and setter generated}

这是我得到的例外-

RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [com.mycomp.myproj.ModelReqVO] and content type [application/json].

我检查了restTemplate上的HttpMessageConverters,并找到了MappingJacksonHttpMessageConverter。使用该转换器的代码中还需要我做些其他事情吗?

我在Spring.io论坛上找到了几个示例,但它们与需要www /
form内容而不是JSON的服务有关。令人惊讶的是,我找不到有关使用特定转换器将Map作为JSON发送的任何详细信息。

注意:这些代码段可能存在编译错误,我已经从手机中键入了代码。出于安全原因,我无法在我编写的机器上使用Internet。

答案1

小编典典

该错误消息说,没有适当HttpMessageConverter的请求类型找到,因此只需添加MappingJackson2HttpMessageConverterMediaTypeRestTemplate

MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); coverter.setSupportedMediaTypes(Arrays.asList(MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON); restTemplate.getMessageConverters().add(0, converter)

android RestClientException:找不到合适的HttpMessageConverter

android RestClientException:找不到合适的HttpMessageConverter

我正在使用 spring android rest模板并尝试将 JSON响应转换为java类,如图所示 here.

这是我试图完成工作的片段:

RestTemplate restTemplate = new RestTemplate();
    restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());

    //I have already tried to manually setting converters with no luck
    //List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
    //messageConverters.add(new MappingJacksonHttpMessageConverter());
    //messageConverters.add(new FormHttpMessageConverter());
    //messageConverters.add(new StringHttpMessageConverter());
    //restTemplate.setMessageConverters(messageConverters);

    Result result = restTemplate.getForObject(url,Result.class);

我想我已经完成了所需的一切,因为它在文件中被告知:

>我的classpath中有以下jar

> jackson-all-1.7.6.jar
> spring-android-rest-template-1.0.0.M2.jar

> url确实返回了一个JSON对象.
> My Result类是一个包含所有必填字段的POJO

基本上我的类路径中有Jackson依赖项必须足以让它工作,因为它说:

The MappingJacksonHttpMessageConverter is conditionally loaded when you create a new RestTemplate instance. If the Jackson dependencies are found in your classpath,the message converter will be automatically added and available for use in REST operations.

那么我在这里缺少什么,我做错了什么?

谢谢

完整例外可以在这里找到:

04-20 04:25:52.706: ERROR/AndroidRuntime(9638): FATAL EXCEPTION: main
04-20 04:25:52.706: ERROR/AndroidRuntime(9638): java.lang.IllegalStateException: Could not execute method of the activity
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at android.view.View$1.onClick(View.java:2083)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at android.view.View.performClick(View.java:2421)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at android.view.View$PerformClick.run(View.java:8869)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at android.os.Handler.handleCallback(Handler.java:587)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at android.os.Handler.dispatchMessage(Handler.java:92)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at android.os.Looper.loop(Looper.java:143)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at android.app.ActivityThread.main(ActivityThread.java:5068)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at java.lang.reflect.Method.invokeNative(Native Method)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at java.lang.reflect.Method.invoke(Method.java:521)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at dalvik.system.NativeStart.main(Native Method)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638): Caused by: java.lang.reflect.InvocationTargetException
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at xxx.SamplePageActivity.doRest(SamplePageActivity.java:83)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at java.lang.reflect.Method.invokeNative(Native Method)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at java.lang.reflect.Method.invoke(Method.java:521)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at android.view.View$1.onClick(View.java:2078)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     ... 11 more
04-20 04:25:52.706: ERROR/AndroidRuntime(9638): Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [[Lxxx.SamplePageActivity$Result;] and content type [application/json;charset=UTF-8]
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:77)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:449)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:404)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:202)
04-20 04:25:52.706: ERROR/AndroidRuntime(9638):     ... 15 more

解决方法

我从来没有在Android上做过任何事情,但我知道转换者对于Content-Type是挑剔的.对于杰克逊来说,消息体需要有’Content-Type:application / json’.尝试检查响应中的所有标头.

Contenty类型的边界被FormHttpMessageConverter覆盖

Contenty类型的边界被FormHttpMessageConverter覆盖

我在Spring
Framework中使用FormHttpMessageConverter。为了通过restTemplate发送文件,我在项目中添加了FormHttpMessageConverter。

问题是服务器在哪里将文件询问的字符串加密为我的Content-type。我必须发送Content-type:multipart / form-
data的文件,但他们询问“ Content-type:multipart / form-data;”。和 boundary:XXXX

因此,我尝试在发送文件之前为边界值。但是,当RestTemplate.exchage()时,边界值被覆盖,原因是FormHttpMessageConverter。FormHttpMessageConverter捕获了转换请求。如果Content-
type为multipart / form-data,则FormHttpMessageConverter将此代码覆盖边界值。

https://github.com/spring-projects/spring-
framework/blob/5f4d1a4628513ab34098fa3f92ba03aa20fc4204/spring-
web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java#L336

我找不到避免该问题的方法,因此我在链接处复制了该代码,并制作了一个文件“ xxxFormHttpMessageConverter”,并修改了“
writeMultipart”方法。

有人知道如何避免这种覆盖吗?

HttpMessageConverter

HttpMessageConverter

一、HttpMessageConverter<T>  

作用:
它负责将请求信息转换为一个对象(类型为T),将该对象输出为响应信息。

其实:DispatcherServlet默认已经安装了AnnotationMethodHandlerAdapter作为HandlerAdapter组件的实现类,HttpMessageConverter即由AnnotationMethodHandlerAdapter使用,将请求信息转换为对象,或将对象转换为响应信息。

那么问题来了?
问题1:如何使用HttpMessageConverter<T>  将请求信息转化并绑定到处理方法的入参当中呢?

解答:      
1.使用@RequestBody/@ResponseBody对处理方法进行标注
         
2.使用HttpEntity<T>/ResponseEntity<T>作为处理方法的入参或者返回值

问题2:处理方法如何知道请求消息的格式?在处理完成后又是根据什么确定响应消息的格式嗯?
解答:根据请求消息头的”Content-Type“及Accept属性确定。

 

1.只有当处理器方法使用到 @RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 时,SpringMVC才使用注册的HttpMessageConverter 对请求响应消息进行处理。

2.当控制器处理方法使用到 @RequestBody/@ResponseBody 或HttpEntity<T>/ResponseEntity<T> 时,Spring 首先根据请求头或响应头的 Accept 属性选择匹配的 HttpMessageConverter, 进而根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter,
若找不到可用的 HttpMessageConverter 将报错

3.@RequestBody 和 @ResponseBody 不需要成对出现。如果方法入参使用到了@RequestBody,SpringMVC将会选择匹配的HttpMessageConverter 将请求信息转换并绑定到该入参中。如果处理方法标注了@ResponseBody,SpringMVC选择匹配的HttpMessageConverter 将方法返回值转换并输出响应消息。

ResponseEntity< byte[]> re = new ResponseEntity<byte []>(bytes, headers, statusCode);


https://blog.csdn.net/u010834071/article/details/41773371

 

 

HttpMessageConverter主要针对那些不会返回view视图的response。其中StringHttpMessageConverter有两个构造函数。当你没有给它指定字符集时,使用默认的ISO-8859-1,这便是造成乱码的一个原因,由于我们经常使用utf-8,所以可以在构造它时指定一下字符集。

 

引言:如何在SpringMVC中统一对返回的Json进行加密?”。

大部分人的第一反应是通过SpringMVC拦截器(Interceptor)中的postHandler方法处理。实际这是行不通的,因为当程序运行到该方法,是在返回数据之后,渲染页面之前,所以这时候HttpServletResponse中的输出流已经关闭了,自然无法在对返回数据进行处理。

其实这个问题用几行代码就可以搞定,因为SpringMVC提供了非常丰富的扩展支持,无论是之前提到的MethodArgumentResolverHandlerMethodReturnValueHandler,还是接下来要提到的HttpMessageConverter

在SpringMVC的 Controller层经常会用到@RequestBody@ResponseBody,通过这两个注解,可以在Controller中直接使用Java对象作为请求参数和返回内容,而完成这之间转换作用的便是HttpMessageConverter

--------------------- 本文来自 若水三千-LOVE 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/lovesomnus/article/details/73918025?utm_source=copy 

 

 

@RequestBody作用:

  1. 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
  2. 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。

使用时机:

  1. GET、POST方式提时, 根据request header Content-Type的值来判断:
    application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据 @RequestParam, @ModelAttribute也可以处理,当然 @RequestBody也能处理);
    multipart/form-data, 不能处理(即使用 @RequestBody不能处理这种格式的数据);
    其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用 @RequestBody来处理);
  2. PUT方式提交时, 根据request header Content-Type的值来判断:
    application/x-www-form-urlencoded, 必须;
    multipart/form-data, 不能处理;
    其他格式, 必须;
    说明:request的body部分的数据编码格式由header部分的Content-Type指定;

@ResponseBody作用:
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
使用时机:
返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

https://www.cnblogs.com/cuiyf/p/6247862.html

 

json数据交互

☛ @RequestBody

@RequestBody注解用于读取 http 请求的内容(字符串),通过 SpringMVC 提供的 HttpMessageConverter 接口将读到的内容转换为 json、xml 等格式的数据并绑定到 controller 方法的参数上。

本例子的应用:@RequestBody 注解实现接收 http 请求的 json 数据,将 json 数据转换为 java 对象

List.action?id=1&name=zhangsan&age=12
复制代码

☛ @ResponseBody

作用:该注解用于将 Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的数据如:json,xml 等,通过 response 响应给客户端。

本例子的应用:@ResponseBody 注解实现将 controller 方法返回对象转换为 json 响应给客户端


作者:Jaybo
链接:https://juejin.im/post/5b83c4a151882542f105470e
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 

 

REST支持
除了典型的MVC场景之外,我们还可以使用框架来创建REST Web服务。
简而言之,我们可以接受Resource作为输入,指定POJO作为方法参数,并使用@RequestBody对其进行注释。也可以使用@ResponseBody注释方法本身,以指定其结果必须直接转换为HTTP响应:

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
@ResponseBody
@PostMapping("/message")
public MyOutputResource sendMessage(
@RequestBody MyInputResource inputResource) {
return new MyOutputResource("Received: "
+ inputResource.getRequestMessage());
}

 

归功于Spring MVC的可扩展性,这也是可行的。
为了将内部DTO编组为REST表示,框架使用HttpMessageConverter基础结构。例如,其中一个实现是MappingJackson2HttpMessageConverter,它可以使用Jackson库将模型对象转换为JSON或从JSON转换。

https://www.zhihu.com/question/38696452

 

SpringMVC返回JSON

参考:http://blog.icoolxue.com/springmvc-3%E4%BD%BF%E7%94%A8fastjson%E4%BB%A3%E6%9B%BFjackson/
http://my.oschina.net/haopeng/blog/324934
由于SpringMVC默认采用Jackson解析Json,所以首先添加Jackson相关依赖。



<jackson.version>1.8.9</jackson.version> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-core-lgpl</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-lgpl</artifactId> <version>${jackson.version}</version> </dependency>

然后进行如下步骤:
1、配置<mvc:annotation-driven/>启用
2、controller 配置@ResponseBody . @RequestBody注解的命令对象的转换,Spring会根据相应的HttpMessageConverter进行模型数据(处理方法的返回值)到JSON响应内容的转换。跳过View解析直接输出到客户端。

注意:使用@ResponseBody时不要忘记在@ReuqestMapping的属性中添加headers = "Accept=application/json"
注意:使用@RequestBody不要忘记在@ReuqestMapping的属性中添加headers = "Content-Type=application/json"
原因:当使用@RequestBody和@ResponseBody注解时,RequestMappingHandlerAdapter就使用HttpMessageConverter来进行读取或者写入相应格式的数据。
HttpMessageConverter匹配过程:
@RequestBody注解时: 根据Request对象header部分的Content-Type类型,逐一匹配合适的HttpMessageConverter来读取数据;
@ResponseBody注解时: 根据Request对象header部分的Accept属性(逗号分隔),逐一按accept中的类型,去遍历找到能处理的
@Controller public class LoginController { @RequestMapping(value="/validataUser.json" headers = "Accept=application/json") @ResponseBody public Map<String,Object> validataUser(@RequestParam String userName){ logger.info(" validata user : {}",userName); Map<String,Object> map = new HashMap<String,Object>(); map.put("code", true); return map; } }
## 使用FastJson替换Jackson
首先别忘了添加Fastjson的包,如果使用Maven,可使用如下设置
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.7</version> </dependency>
<!-- 启用默认配置 --> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <!-- 配置Fastjson支持 --> <bean> <!-- 避免IE执行AJAX时,返回JSON出现下载文件 --> <property name="supportedMediaTypes"> <list> <!-- 这里顺序不能反,一定先写text/html,不然ie下出现下载提示 --> <value>text/html;charset=UTF-8</value> <value>application/json</value> </list> </property> <!-- <property name="features"> <list> <value>WriteMapNullValue</value> <value>QuoteFieldNames</value> </list> </property> --> </bean> </mvc:message-converters> </mvc:annotation-driven>
## @RequestBody, @ResponseBody详解
详细介绍下@RequestBody、@ResponseBody的具体用法和使用时机;
@RequestBody
作用:
i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
ii) 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
使用时机:
A) GET、POST方式提时, 根据request header Content-Type的值来判断:
注意:使用@RequestBody不要忘记在@ReuqestMapping的属性中添加headers = "Content-Type=application/json"



 @RequestMapping(value = "/{username}", method = RequestMethod.PUT, headers = "Content-Type=application/json") // headers = "Content-Type=application/json"  @ResponseStatus(HttpStatus.NO_CONTENT) public void updateSpitter(@PathVariable String username, @RequestBody Spitter spitter) { // @RequestBody  spitterService.saveSpitter(spitter); }
  • application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
  • multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据);
  • 其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用@RequestBody来处理);
    B) PUT方式提交时, 根据request header Content-Type的值来判断:
    application/x-www-form-urlencoded, 必须;
    multipart/form-data, 不能处理;
    其他格式, 必须;
    说明:request的body部分的数据编码格式由header部分的Content-Type指定;

@ResponseBody
作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
使用时机: 返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

注意:使用@ResponseBody时不要忘记在@ReuqestMapping的属性中添加headers = "Accept=application/json"



 @RequestMapping(value = "/{username}/spittles", method = RequestMethod.GET, headers = "Accept=application/json")//headers = "Accept=application/json"  public @ResponseBody List<Spittle> getSpittlesForSpitter(@PathVariable String username) { //@ResponseBody List<Spittle>  return spitterService.getSpittlesForSpitter(username); }

HttpMessageConverter

该接口定义了四个方法,分别是读取数据时的 canRead(), read() 和 写入数据时的canWrite(), write()方法。
在使用<mvc:annotation-driven />标签配置时:

  • 1、默认配置了RequestMappingHandlerAdapter(注意SpringMVC3.1之后是RequestMappingHandlerAdapter不是AnnotationMethodHandlerAdapter,详情查看Spring 3.1 document “16.14 Configuring Spring MVC”章节),
  • 2、并为他配置了一下默认的HttpMessageConverter

ByteArrayHttpMessageConverter: 负责读取二进制格式的数据和写出二进制格式的数据;
StringHttpMessageConverter: 负责读取字符串格式的数据和写出二进制格式的数据;

ResourceHttpMessageConverter:负责读取资源文件和写出资源文件数据;
FormHttpMessageConverter: 负责读取form提交的数据(能读取的数据格式为 application/x-www-form-urlencoded,不能读取multipart/form-data格式数据);负责写入application/x-www-from-urlencoded和multipart/form-data格式的数据;

MappingJacksonHttpMessageConverter: 负责读取和写入json格式的数据;

SouceHttpMessageConverter: 负责读取和写入 xml 中javax.xml.transform.Source定义的数据;
Jaxb2RootElementHttpMessageConverter: 负责读取和写入xml 标签格式的数据;

AtomFeedHttpMessageConverter: 负责读取和写入Atom格式的数据;
RssChannelHttpMessageConverter: 负责读取和写入RSS格式的数据;

当使用@RequestBody和@ResponseBody注解时,RequestMappingHandlerAdapter就使用它们来进行读取或者写入相应格式的数据。

HttpMessageConverter匹配过程:
@RequestBody注解时: 根据Request对象header部分的Content-Type类型,逐一匹配合适的HttpMessageConverter来读取数据;
@ResponseBody注解时: 根据Request对象header部分的Accept属性(逗号分隔),逐一按accept中的类型,去遍历找到能处理的

关于直接返回json格式字符串的注意:

MappingJacksonHttpMessageConverter 调用了 objectMapper.writeValue(OutputStream stream, Object)方法,使用@ResponseBody注解返回的对象就传入Object参数内。
方式一、若返回的对象为已经格式化好的json串时,不使用@ResponseBody注解,而应该这样处理:
''''1、response.setContentType("application/json; charset=UTF-8");
2、response.getWriter().print(jsonStr);''''
直接输出到body区,然后的视图为void。

方式二、不过也可以使用@ResponseBody,不过需要进行乱码配置:
直接返回字符串,使用@ResponseBody注解时,后台会调用StringHttpMessageConverter,它默认的字符集为ISO-8859-1,这会导致中文乱码。可以参考[[spring:springmvc_json乱码]]进行配置即可。

参考:
http://blog.csdn.net/kobejayandy/article/details/12690555

http://www.xby1993.net/pages/dokuwiki/spring/springmvc%E8%BF%94%E5%9B%9Ejson.html

 

httpMessageConverter 初始化性能问题

httpMessageConverter 初始化性能问题

经过笨马性能检测工具,检测到 jacksonConverter 会初始化多次,很好 cpu

   /**
     * Feign请求的Decode/Encode所使用的缺省JacksonConvert配置处理。
     *
     * @return 根据配置产生的转换器。
     */
    private HttpMessageConverters getJacksonConverter() {
        Jackson2ObjectMapperBuilder objectMapperBuilder =
                Jackson2ObjectMapperBuilder
                        .json()
                        .serializerByType(Long.TYPE, ToStringSerializer.instance)
                        .serializerByType(Long.class, ToStringSerializer.instance)
                        .timeZone(jacksonTimeZone);
        if (Boolean.FALSE.equals(jacksonWriteDatesAsTimestamps)) {
            objectMapperBuilder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        }
        MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(
                objectMapperBuilder
                        .build()
                        .configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)
        );

        List<MediaType> mediaTypes = new ArrayList<>();
        // 放在第一个的,将作为FeignClient Request的默认Content-Type
        mediaTypes.add(MediaType.APPLICATION_JSON);
        mediaTypes.add(MediaType.TEXT_PLAIN);
        mediaTypes.add(MediaType.TEXT_HTML);
        mediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
        mediaTypes.add(MediaType.APPLICATION_XML);
        mediaTypes.add(new MediaType("text", "json"));
        jacksonConverter.setSupportedMediaTypes(mediaTypes);
        jacksonConverter.setDefaultCharset(StandardCharsets.UTF_8);

        log.info("{} HttpMessageConverters appended with MappingJackson2HttpMessageConverter({})", MicroSharedConstants.MICRO_SHARED_PACKAGE_LOG_PREFIX, jacksonConverter.getDefaultCharset());

        return new HttpMessageConverters(jacksonConverter);
    }
    /**
     * Feign请求的Decode/Encode所使用的缺省JacksonConvert配置处理。
     *
     * @return 根据配置产生的转换器。
     */
    private ObjectFactory<HttpMessageConverters> getJacksonConverterFactory() {
        if(httpMessageConverter == null) {
        	httpMessageConverter = getJacksonConverter();
        } 
//ObjectFactory的getObject方法在 SpringDecoder .decode 都会触发一次。如果这里每次都是new出来的对象,那么就会多次初始化,影响性能,那么如果这里是单例会不会有线程安全问题,这个取决于AbstractJackson2HttpMessageConverter的实现类
        return () -> httpMessageConverter;
    }


/**
 * @author Spencer Gibb
 */
public class SpringDecoder implements Decoder {

	private ObjectFactory<HttpMessageConverters> messageConverters;

	public SpringDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
		this.messageConverters = messageConverters;
	}

	@Override
	public Object decode(final Response response, Type type)
			throws IOException, FeignException {
		if (type instanceof Class || type instanceof ParameterizedType
				|| type instanceof WildcardType) {
			@SuppressWarnings({ "unchecked", "rawtypes" })
			HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(
                    //messageConverters.getObject() 这里会触发   return () -> httpMessageConverter;
                   //如果这里每次都是new出来的对象,那么就会多次初始化,影响性能
					type, this.messageConverters.getObject().getConverters());

			return extractor.extractData(new FeignResponseAdapter(response));
		}
		throw new DecodeException(response.status(),
				"type is not an instance of Class or ParameterizedType: " + type,
				response.request());
	}

 

关于HttpMessageConverter异常:RestClientException:无法写入请求:未找到合适的HttpMessageConverter的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于android RestClientException:找不到合适的HttpMessageConverter、Contenty类型的边界被FormHttpMessageConverter覆盖、HttpMessageConverter、httpMessageConverter 初始化性能问题等相关知识的信息别忘了在本站进行查找喔。

本文标签: