我正在参加「金石计划」
写在前面
一看到这个标题,我总会在想,get请求,你还要在body里面传递formdata参数?
这究竟是怎样如此反人类的设计呢?能写出这样接口的人,究竟是多么的奇葩?
你要在body里面传递formdata参数,为啥不能用post请求?非得用get请求?
说实话,全网找了很久,也问过gpt了,java中的httpclient能实现get传递body参数的,也就只有在body中传递json字符串的实现,传递formdata的,好像还真的是没有相关实现。
一时之间都不知道怎么解决呀?头都大!!!
看到知乎有一篇文章:HTTP GET 请求可以有 body 吗?
有兴趣的小伙伴,可以去看看。
看到其中有python的一个实现,是这样的:
curl,postman,apifox等工具也是可以:
唯独java的okHttp是这样的:🤣😂
哥们,你倒是实现一下呀,java的相关实现方法!!!
好吧,还是没有相关的说明,头还是有点大喔!!!
httpclient实现get请求body传递json参数
上面说过,全网能找到的基本上都是,get请求body传递json字符串参数了,这里也贴一下相关的实现,如下:
- 创建HttpGetWithEntity
java
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import java.net.URI;
/**
* http get请求带body内容
*
* @author llsydn
*/
public class HttpGetWithEntity extends HttpEntityEnclosingRequestBase {
private final static String METHOD_NAME = "GET";
@Override
public String getMethod() {
return METHOD_NAME;
}
public HttpGetWithEntity() {
super();
}
public HttpGetWithEntity(final String uri) {
super();
setURI(URI.create(uri));
}
}
- 封装get请求
java
/**
* 执行http请求。
*
* @throws Exception
*/
private String sendRequest(String url,Map<String,Object> params) throws Exception {
String encoding = "UTF-8";
String param = JSONArray.toJSON(params).toString();
String body = "";
//创建httpclient对象
HttpGetWithEntity httpGetWithEntity = new HttpGetWithEntity(url);
HttpEntity httpEntity = new StringEntity(param, ContentType.APPLICATION_JSON);
httpGetWithEntity.setEntity(httpEntity);
//执行请求操作,并拿到结果(同步阻塞)
CloseableHttpClient client = HttpClientBuilder.create().build();
CloseableHttpResponse response = client.execute(httpGetWithEntity);
//获取结果实体
HttpEntity entity = response.getEntity();
if (entity != null) {
//按指定编码转换结果实体为String类型
body = EntityUtils.toString(entity, encoding);
}
//释放链接
response.close();
return body;
}
好了,以上就是httpclient实现get请求body传递json参数的相关实现。
但是还是没有实现:Java实现Get请求body传递formdata参数!!!
看到了知乎上面的相关说明,有些python工具类,是可以实现get请求body传递formdata参数的;
httpclient是不支持这种方式,那有没有其他工具包的实现方法呢?
找了很久,可算是找到了一个,那就是:AsyncHttpClient
AsyncHttpClient实现Get请求body传递formdata参数
HttpClient提供了两种I/O模型:经典的java阻塞I/O模型和基于Java NIO的异步非阻塞事件驱动I/O模型。
Java中的阻塞I/O是一种高效、便捷的I/O模型,非常适合并发连接数量相对适中的高性能应用程序。只要并发连接的数量在1000个以下并且连接大多忙于传输数据,阻塞I/O模型就可以提供最佳的数据吞吐量性能。
然而,对于连接大部分时间保持空闲的应用程序,上下文切换的开销可能会变得很大,这时非阻塞I/O模型可能会提供更好的替代方案。
异步I/O模型可能更适合于比较看重资源高效利用、系统可伸缩性、以及可以同时支持更多HTTP连接的场景。
参考的文章: get请求带body的formdata非json实现AsyncHttpClient解决
- pom.xml依赖
xml
<dependency>
<groupId>org.asynchttpclient</groupId>
<artifactId>async-http-client</artifactId>
<version>2.2.0</version>
</dependency>
- 最终实现
java
import org.asynchttpclient.*;
import org.asynchttpclient.proxy.ProxyServer;
import org.asynchttpclient.request.body.multipart.Part;
import org.asynchttpclient.request.body.multipart.StringPart;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import static org.asynchttpclient.proxy.ProxyType.HTTP;
/**
* @author lilinshen
*/
public class TestMain3 {
public static void main(String[] args) throws Exception {
String url = "http://127.0.0.1:8080/llsydn/testGet";
List<Part> params = new ArrayList<Part>();
params.add(new StringPart("name1", "lls1"));
params.add(new StringPart("name2", "lls2"));
String result = asyncRequest(url, params);
System.out.println("调用结果:" + result);
}
/**
* 执行异步HTTP请求
*/
public static String asyncRequest(String url, List<Part> params) throws Exception {
//ProxyServer proxy = new ProxyServer("127.0.0.1", 8888, 8888, null, null, HTTP);
AsyncHttpClient c = new DefaultAsyncHttpClient(new DefaultAsyncHttpClientConfig.Builder()//.setProxyServer(proxy)
.build());
Future<Response> f = c.prepareGet(url).setBodyParts(
params)
.execute(new AsyncCompletionHandler<Response>() {
@Override
public Response onCompleted(Response response) {
return response;
}
@Override
public void onThrowable(Throwable t) {
throw new RuntimeException("exception");
}
});
Response response = f.get();
String result = response == null ? "" : response.getResponseBody();
c.close(); // 关闭连接器,释放资源
if (c.isClosed()) {
System.out.println("已关闭");
}
return result;
}
}
这里,我加了proxy代理,本地可以用fiddler进行代理,就可以拦截到相应的请求。
由上图可以看到,该实现的方式,估计和httpclient上传文件,带额外参数的方式类似。
看到这,有人就会跳出来说,那我用HttpURLConnection,参考asynchttpclient的方法,自己拼接参数,可不可以呀?
相关实现如下:
不好意思,哥们也去试了一下,虽然定义的是GET请求,但是在发送请求的时候,还是被转成了POST请求了!!!
走不通的!!!
在编写文档的时候,好像还发现了其他的实现,httpclient在4.x之后开始提供基于nio的异步版本httpasyncclient, httpasyncclient借助了Java并发库和nio进行封装(虽说NIO是同步非阻塞IO,但是HttpAsyncClient提供了回调的机制,与netty类似,所以可以模拟类似于AIO的效果),其调用方式非常便捷.
有兴趣的小伙伴,可以查看这里:异步httpClient(Async HttpClient)
好了,废话不多说了,既然使用asynchttpclient实现了Get请求body传递formdata参数。
这里就不再深入研究了,毕竟这种反人类的接口,大家伙,还是少写一点,免得麻烦对接人员。
说实话,程序员,还是别难为程序员了吧!!!大家都不容易的!!!
写在最后
好了,以上就是我个人的实操了。可能有些不对,大家伙,轻点喷!!!
个人理解,可能也不够全面,班门弄斧了。
好了,今天就先到这里了!!!^_^
如果觉得有收获的,帮忙点赞、评论、收藏
一下,再走呗!!!