问题出现
今天在对接其他部门的接口时,发现对方提供了一个GET请求,但是参数却要求通过body传递json格式的数据。这可难住我了,GET请求还能通过body传递参数吗?带着疑问,先试一下吧。我们项目用的RestTemplate,我想起了RestTemplate的exchange方法有个参数HttpEntity,会不会是这里可以传参数进去呢?迅速写了代码
1 | public static String getForJson(String url, Map<String,Object> dataValue) { |
结果
1 | 2020-06-18 17:08:37.544|DEBUG|http-nio-8090-exec-2|org.apache.http.impl.conn.Wire|wire|73|http-outgoing-0 >> "GET /cross/appms-internal/v1/portal/app/config/search HTTP/1.1[\r][\n]" |
通过日志可以看到请求失败了,对方接口返回了参数无效
1 | {"code":4004,"message":"parameter invalid"} |
解决问题
在HTTP1.1中GET请求已经可以在body里发送数据,但是既然用了RestTemplate,就要看一下RestTemplate是否提供了实现,这里我们用的httpclient,默认用的HttpComponentsClientHttpRequestFactory工厂,查看了HttpComponentsClientHttpRequestFactory的createHttpUriRequest方法,发现GET请求是HttpGet,HttpGet继承HttpRequestBase,HttpRequestBase是不支持传递body的。
1 | protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) { |
查了资料发现HttpEntityEnclosingRequestBase是可以传递body的,那就自定义一个工厂继承HttpComponentsClientHttpRequestFactory,重写createHttpUriRequest方法,当发送的请求是GET请求时,创建自定义的继承HttpEntityEnclosingRequestBase的类,这样GET请求就可以传送body。
1 |
|
测试结果
再次测试结果,发现调用正确返回
1 | 2020-06-18 17:10:28.403|DEBUG|http-nio-8090-exec-1|org.apache.http.impl.conn.Wire|wire|73|http-outgoing-0 >> "GET /cross/appms-internal/v1/portal/app/config/search HTTP/1.1[\r][\n]" |
和第一次的请求相比,这一次请求日志中多了一句
1 | 2020-06-18 17:10:28.408|DEBUG|http-nio-8090-exec-1|org.apache.http.impl.conn.Wire|wire|87|http-outgoing-0 >> "{"devIdList":[164359,164893],"pageSize":10,"currentPage":1}" |
如果还没看出来,我在整理一下日志
1 | GET /cross/appms-internal/v1/portal/app/config/search HTTP/1.1[\r][\n] |
这个就是HTTP协议,可以看到最后一行就是body里的数据,问题也解决了。