簡體   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