详解java如何实现带RequestBody传Json参数的GET请求

 更新时间:2024年02月02日 09:04:51   作者:DaveCui  
在调试Fate平台时,遇到了一个奇葩的接口类型,该接口为Get方式,入参是一个json类型在body中传递,使用body中传参的话为什么不用POST请求而使用了GET请求,下面我们就来深入研究一下

在调试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

参考文档

解决HTTP GET方法调用带有body问题

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参数的资料请关注脚本之家其它相关文章!

相关文章

  • java实体对象与Map之间的转换工具类代码实例

    java实体对象与Map之间的转换工具类代码实例

    这篇文章主要介绍了java实体对象与Map之间的转换工具类代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • java图片对比度调整示例代码

    java图片对比度调整示例代码

    这篇文章主要给大家介绍了关于java图片对比度调整的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-07-07
  • Java阻塞队列必看类:BlockingQueue快速了解大体框架和实现思路

    Java阻塞队列必看类:BlockingQueue快速了解大体框架和实现思路

    这篇文章主要介绍了Java阻塞队列必看类:BlockingQueue快速了解大体框架和实现思路,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • Java abstract class 与 interface对比

    Java abstract class 与 interface对比

    这篇文章主要介绍了 Java abstract class 与 interface对比的相关资料,需要的朋友可以参考下
    2016-12-12
  • Java8 将List转换为用逗号隔开的字符串的多种方法

    Java8 将List转换为用逗号隔开的字符串的多种方法

    这篇文章主要介绍了Java8 将List转换为用逗号隔开的字符串的几种方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Java 内部类的定义与范例

    Java 内部类的定义与范例

    说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉。原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法。今天我们就来一探究竟
    2021-11-11
  • 深入理解Java中的Lambda表达式

    深入理解Java中的Lambda表达式

    这篇文章主要介绍了深入理解Java中的Lambda表达式,Lambda在各编程语言中都是非常重要的特性,而Java中则加入得有些太晚...需要的朋友可以参考下
    2015-07-07
  • SpringMVC Interceptor拦截器使用教程

    SpringMVC Interceptor拦截器使用教程

    SpringMVC中拦截器(Interceptor)用于对URL请求进行前置/后置过滤,Interceptor与Filter用途相似,但实现方式不同。Interceptor底层就是基于Spring AOP 面向切面编程实现
    2023-01-01
  • 基于Graphics2D drawImage图片失真的解决方案

    基于Graphics2D drawImage图片失真的解决方案

    这篇文章主要介绍了基于Graphics2D drawImage图片失真的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • ssm项目改造spring boot项目完整步骤

    ssm项目改造spring boot项目完整步骤

    Spring Boot现在已经成为Java开发领域的一颗璀璨明珠,它本身是包容万象的,可以跟各种技术集成,下面这篇文章主要给大家介绍了关于ssm项目改造spring boot项目的相关资料,需要的朋友可以参考下
    2023-04-04

最新评论