问题发生的背景:
Feign在默认情况下使用的是JDK原生的URLConnection
发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection 。
我们可以用Apache的HTTP Client
替换Feign原始的http client, 从而获取连接池、超时时间
等与性能息息相关的控制能力。Spring Cloud从Brixtion.SR5版本开始支持这种替换,
首先在项目中声明Apache HTTP Client和feign-httpclient依赖:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpasyncclient</artifactId> </dependency> <dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-httpclient</artifactId> <version>8.17.0</version> </dependency>
修改application.properties配置
feign.httpclient.enabled=true
FeignService Post接口
@FeignClient(name="eureka-client") public interface UserFeignService { @RequestMapping(value = "/user/update",method = RequestMethod.POST) String updateUser(@RequestBody User user); }
报错如下:
java.lang.IllegalArgumentException: MIME type may not contain reserved characters
at org.apache.http.util.Args.check(Args.java:36) ~[httpcore-4.4.11.jar:4.4.11]
at org.apache.http.entity.ContentType.create(ContentType.java:227) ~[httpcore-4.4.11.jar:4.4.11]
at feign.httpclient.ApacheHttpClient.getContentType(ApacheHttpClient.java:159) ~[feign-httpclient-8.17.0.jar:8.17.0]
at feign.httpclient.ApacheHttpClient.toHttpUriRequest(ApacheHttpClient.java:140) ~[feign-httpclient-8.17.0.jar:8.17.0]
可以看出来是检测Content-Type不合法报的异常,但在代码中我们并没有指定Content-Type,所以应该是使用了默认值。
feign.httpclient.ApacheHttpClient
private ContentType getContentType(Request request) { ContentType contentType = ContentType.DEFAULT_TEXT; Iterator var3 = request.headers().entrySet().iterator(); while(var3.hasNext()) { Entry<String, Collection<String>> entry = (Entry)var3.next(); if(((String)entry.getKey()).equalsIgnoreCase("Content-Type")) { Collection values = (Collection)entry.getValue(); if(values != null && !values.isEmpty()) { contentType = ContentType.create((String)((Collection)entry.getValue()).iterator().next(), request.charset()); break; } } }
return contentType; }
import org.springframework.http.MediaType;
@FeignClient(name="eureka-client") public interface UserFeignService { @RequestMapping(value = "/user/update",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_VALUE) String updateUser(@RequestBody User user); }
通过给@RequestMapping设置consumes参数