详解java如何实现带RequestBody传Json参数的GET请求
作者:DaveCui
在调试Fate平台时,我遇到了一个奇葩的接口类型。该接口为Get方式,入参是一个json类型在body中传递。我非常费解使用body中传参的话为什么不用POST请求而使用了GET请求?
在本篇文章中加入了自己对这个问题的一点理解,以及通过java请求这个接口的完整可使用案例。(包括返回string类型和文件流类型)
一、接口调用方法
当我看到这个接口的时候,我是有点懵的。Get请求为什么要采用这样的参数传递方式,一般来说GET请求就直接将参数拼接在URL中了。
二、传参方式的讨论
GET和POST请求和其常见的传参方式
我们知道GET和POST请求是HTTP协议中的两种最常用的请求方式,它们在处理参数和数据传输方面差距还是比较大的。
参数传递方式:GET请求的参数直接附加在URL的末尾,而POST请求的参数则包含在请求体中。
这意味着GET请求的参数是明文传输的,因此在请求过程中可能会被记录或泄露。而POST请求的参数则是加密的,相对更安全。
参数的数据类型:GET请求的参数只能发送简单的字符串,而POST请求可以发送复杂的数据类型,如表单数据、JSON数据等。
这使得POST请求相比GET请求在传递复杂数据时更为方便和灵活。
请求的语义:GET请求通常用于获取或检索数据,而POST请求则用于提交数据或执行某些操作。
缓存机制:GET请求默认开启浏览器缓存机制,因为它的主要目的是获取数据,而POST请求则默认禁用缓存机制,因为它可能对服务器上的资源进行修改。
参数长度限制:由于GET请求的参数附加在URL上,因此参数长度受到URL长度的限制。而POST请求的参数放在请求体中,理论上没有长度限制,但实际上服务器和客户端可能会有最大长度限制。
3、4、5意味着根据不同的需求,选择合适的请求方式是很重要的。
其实GET带使用body中传参,从请求方面讲符合了GET请求的语义(获取和检索数据)有能应用到混存机制。从参数方面讲有能突破长度和数据类型的限制,同时参数传递更安全。
GET使用请求体传参的合理性
对于GET请求通过body传参的情况可以说非常罕见,很多老java都没见过,也算是给我开了眼了。
根据以往的经验,我们约定俗成,GET传参通过URL拼接,POST传参通过body传输。于是有些HTTP库(如OkHttp)是不允许GET请求带有请求体的,默认通过post传请求体。
虽然官方不推荐这样做,但是,http(基于tcp的超文本传输协议)并没有规定Get请求不能加body。
所以这个请求自有其合理性。
三、java实现GET使用请求体传参请求的技术选型
在公司封装好的Http请求方法类中,我们采用的是OkHttp,很不幸的是他不支持GET使用请求体传参。
于是通过网络搜索,我们选定了两个方法。一个是AsyncHttpClient,另一个是apache.http.client。
参考文档:
httpclient实现HttpGet请求传body的json参数的
考虑到我们没有异步请求方面的需求,于是最后选定了apache.http.client
四、完整实现
1.pom引入关键依赖
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.6</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.5.6</version> </dependency>
2.定义HttpGet实体类
这个实体类主要供后续实现的方法类调用,可以单独作为一个类,也可以将其作为方法类的子类。
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import java.net.URI; public class HttpGetWithEntity extends HttpEntityEnclosingRequestBase { private final static String METHOD_NAME = "GET"; public HttpGetWithEntity() { super(); } public HttpGetWithEntity(final URI uri) { super(); setURI(uri); } HttpGetWithEntity(final String uri) { super(); setURI(URI.create(uri)); } @Override public String getMethod() { return METHOD_NAME; } }
3.实现方法类
这里实现了两个方法,都是通过GET请求传递请求体数据的(请求体数据已转换为为JsonString)。
区别在于一个是正常返回String类型Response。另一个是返回文件流并将文件流写入到文件中。
import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @Slf4j public class ApacheHttpUitls { public static String getResponseByJson(String url, String param, String encoding) throws Exception { String body = ""; //创建httpclient对象 CloseableHttpClient client = HttpClients.createDefault(); HttpGetWithEntity httpGetWithEntity = new HttpGetWithEntity(url); HttpEntity httpEntity = new StringEntity(param, ContentType.APPLICATION_JSON); httpGetWithEntity.setEntity(httpEntity); //执行请求操作,并拿到结果 CloseableHttpResponse response = client.execute(httpGetWithEntity); //获取结果实体 HttpEntity entity = response.getEntity(); if (entity != null) { //按指定编码转换结果实体为String类型 body = EntityUtils.toString(entity, encoding); } //释放链接 response.close(); return body; } public static boolean getStreamGetResponse(String url, String requestBody, String outputFilePath) throws Exception { InputStream inputStream = null; OutputStream outputStream = null; CloseableHttpResponse response = null; try{ //创建httpclient对象 CloseableHttpClient client = HttpClients.createDefault(); HttpGetWithEntity httpGetWithEntity = new HttpGetWithEntity(url); HttpEntity httpEntity = new StringEntity(requestBody, ContentType.APPLICATION_JSON); httpGetWithEntity.setEntity(httpEntity); //执行请求操作,并拿到结果 response = client.execute(httpGetWithEntity); //获取结果实体 HttpEntity entity = response.getEntity(); log.info("requestUrl: {}, requestBody: {}", url, requestBody); if (entity != null) { inputStream = entity.getContent(); Path path = Paths.get(outputFilePath); if (!Files.exists(path)) { try { Files.createFile(path); } catch (IOException e) { log.error("File create error ", e); // 处理异常,例如输出错误消息或退出程序 } } outputStream = Files.newOutputStream(path); byte[] buffer = new byte[1024]; // 可以根据需要调整缓冲区大小 int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } log.info("File downloaded and saved at " + outputFilePath); }else{ log.error("Http get Entity is null"); return false; } return true; } catch (Exception e){ log.error("File download error ", e); return false; } finally { //释放链接 if (response != null) response.close(); if (inputStream != null) inputStream.close(); if (outputStream != null) outputStream.close(); } } }
以上就是详解java如何实现带RequestBody传Json参数的GET请求的详细内容,更多关于java带RequestBody传Json参数的资料请关注脚本之家其它相关文章!