繁体   English   中英

在 java/spring boot 中的 HTTP GET 请求中发送 JSON 正文

[英]Send JSON body in HTTP GET request in java/spring boot

我需要在 java/spring boot 中发送一个带有 json 主体的 GET 请求。 我知道反对它的建议,但是我必须这样做有几个原因: 1. 我使用的第 3 方 API 只允许 GET 请求,所以 POST 不是一个选项。 2. 我需要在正文中传递一个非常大的参数(一个大约 8-10k 个字符的逗号分隔列表),因此将查询参数添加到 url 上也不是一个选项。

我尝试了一些不同的事情:

  1. apache HttpClient 从这里: 使用 Java 中的 HTTP GET 请求发送内容正文 这直接从 API 本身给出了一些关于密钥错误的错误。

  2. URIComponentsBuilder 来自这里: Spring RestTemplate GET with parameters 这只是将参数附加到 url 上,正如我之前解释的那样,这不是一个选项。

  3. restTemplate.exchange。 这看起来最简单,但对象不会通过: https : //docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#exchange-java。 lang.String-org.springframework.http.HttpMethod-org.springframework.http.HttpEntity-java.lang.Class-java.util.Map-

以及可能还有一两件事我已经忘记了。

这就是我在 Postman 中所说的 我需要能够传递这里给出的两个参数。 如果通过 Postman 运行它可以正常工作,但我无法在 Java/Spring Boot 中弄清楚。

这是来自 restTemplate.exchange 尝试的代码片段:

public String makeMMSICall(String uri, List<String> MMSIBatchList, HashMap<String, String> headersList) {
    ResponseEntity<String> result = null;
    try {
        RestTemplate restTemplate = new RestTemplate();

        HttpHeaders headers = new HttpHeaders();
        for (String key : headersList.keySet()) {
            headers.add(key, headersList.get(key));
        }

        Map<String, String> params = new HashMap<String, String>();
        params.put("mmsi", String.join(",", MMSIBatchList));
        params.put("limit", mmsiBatchSize);

        HttpEntity<?> entity = new HttpEntity<>(headers);
        result = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class, params);

        System.out.println(result.getBody());

    } catch (RestClientException e) {
        LOGGER.error("Exception in makeGetHTTPCall :" + e.getMessage());
        throw e;
    } catch (Exception e) {
        LOGGER.error("Exception in makeGetHTTPCall :" + e.getMessage());
        throw e;
    }
    return result.getBody();
}

感谢您的帮助!

您可以尝试java.net.HttpUrlConnection ,它对我有用,但实际上我通常使用 POST

HttpURLConnection connection = null;
BufferedReader reader = null;
String payload = "body";

try {

    URL url = new URL("url endpoint");

    if (url.getProtocol().equalsIgnoreCase("https")) {
        connection = (HttpsURLConnection) url.openConnection();
    } else {
        connection = (HttpURLConnection) url.openConnection();
    }
    //  Set connection properties
    connection.setRequestMethod(method); // get or post
    connection.setReadTimeout(3 * 1000);
    connection.setDoOutput(true);
    connection.setUseCaches(false);        

    if (payload != null) {
        OutputStream os = connection.getOutputStream();

        os.write(payload.getBytes(StandardCharsets.UTF_8));

        os.flush();
        os.close();
    }

    int responseCode = connection.getResponseCode();
}

即使使用.exchange方法,也.exchange通过RestTemplate实现它。 即使我们在函数参数中传递实体,它也不会发送 GET 调用的请求正文。(通过拦截器日志测试)

您可以使用 Apache 客户端来解决此问题/请求(无论您想怎么称呼它)。 您需要的代码是以下几行。

  private static class HttpGetWithBody extends HttpEntityEnclosingRequestBase {

    JSONObject requestBody;

    public HttpGetWithBody(URI uri, JSONObject requestBody) throws UnsupportedEncodingException {
      this.setURI(uri);
      StringEntity stringEntity = new StringEntity(requestBody.toString());
      super.setEntity(stringEntity);
      this.requestBody = requestBody;
    }

    @Override
    public String getMethod() {
      return "GET";
    }
  }


  private JSONObject executeGetRequestWithBody(String host, Object entity) throws ClientProtocolException, IOException {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    try{
      JSONObject requestBody = new JSONObject(entity);
      URL url = new URL(host);
      HttpRequest request = new HttpGetWithBody(url.toURI(), requestBody);
      request.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
      request.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
      HttpResponse response;
      if(url.getPort() != 0) response = httpClient.execute(new HttpHost(url.getHost(), url.getPort()), request);
      else response = httpClient.execute(new HttpHost(url.getHost()), request);

      if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
        JSONObject res = new JSONObject(EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
        httpClient.close();
        return res;
      }
    }catch (Exception e){
      log.error("Error occurred in executeGetRequestWithBody. Error: ", e.getStackTrace());
    }
    httpClient.close();
    return null;
}

如果您检查甚至 Apache 客户端库不支持本机传递主体(通过HttpGet方法的代码实现检查),因为上下文请求主体对于 GET 请求不是一个好的和明显的做法。

尝试创建一个新的自定义 RequestFactory。 类似于通过正文获取请求

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM