本文的目的是介绍HttpMessageConverter异常:RestClientException:无法写入请求:未找到合适的HttpMessageConverter的详细情况,我们将通过专业的研究
本文的目的是介绍HttpMessageConverter异常:RestClientException:无法写入请求:未找到合适的HttpMessageConverter的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于android RestClientException:找不到合适的HttpMessageConverter、Contenty类型的边界被FormHttpMessageConverter覆盖、HttpMessageConverter、httpMessageConverter 初始化性能问题的知识。
本文目录一览:- HttpMessageConverter异常:RestClientException:无法写入请求:未找到合适的HttpMessageConverter
- android RestClientException:找不到合适的HttpMessageConverter
- Contenty类型的边界被FormHttpMessageConverter覆盖
- HttpMessageConverter
- 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
的请求类型找到,因此只需添加MappingJackson2HttpMessageConverter
与MediaType
以RestTemplate
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); coverter.setSupportedMediaTypes(Arrays.asList(MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON); restTemplate.getMessageConverters().add(0, converter)
android RestClientException:找不到合适的HttpMessageConverter
这是我试图完成工作的片段:
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
解决方法
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<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提供了非常丰富的扩展支持,无论是之前提到的MethodArgumentResolver
和HandlerMethodReturnValueHandler
,还是接下来要提到的HttpMessageConverter
。
在SpringMVC的 Controller
层经常会用到@RequestBody
和@ResponseBody
,通过这两个注解,可以在Controller
中直接使用Java对象作为请求参数和返回内容,而完成这之间转换作用的便是HttpMessageConverter
。
--------------------- 本文来自 若水三千-LOVE 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/lovesomnus/article/details/73918025?utm_source=copy
@RequestBody作用:
- 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
- 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
使用时机:
- GET、POST方式提时, 根据request header Content-Type的值来判断:
application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据 @RequestParam, @ModelAttribute也可以处理,当然 @RequestBody也能处理);
multipart/form-data, 不能处理(即使用 @RequestBody不能处理这种格式的数据);
其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用 @RequestBody来处理); - 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 初始化性能问题
经过笨马性能检测工具,检测到 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 初始化性能问题等相关知识的信息别忘了在本站进行查找喔。
本文标签: