【问题标题】:Adding value to path parameter in Java REST?在 Java REST 中为路径参数添加值?
【发布时间】:2020-01-14 03:19:22
【问题描述】:
NOTICE UPDATE!!

The problem got solved and i added my own answer in the thread

简而言之,我尝试添加参数“scan_id”值,但由于它是一个 POST,我无法直接在 url 路径中添加该值。

使用我已经拥有的代码,我将如何修改或添加以使 url 正确,也就是说,以便它接受我的 POST?。

不知何故,我找不到任何可以帮助我弄清楚我将如何去做的例子。

我知道如何使用有效负载进行 POST,使用参数进行 GET。但是 Params 的帖子让我很困惑。

感谢任何帮助。 (我想继续使用 HttpUrlConnection ,除非提供了另一个示例,该示例还告诉我如何发送请求而不仅仅是配置路径。

我已经尝试将它添加到有效负载中。 我已经尝试过 UriBuilder,但发现它令人困惑并且与我的其余代码形成对比,因此想寻求有关 HttpUrlConnection 的帮助。

URL url = new URL("http://localhost/scans/{scan_id}/launch");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("tmp_value_dont_mind_this", "432432");
        con.setRequestProperty("X-Cookie", "token=" + "43432");
        con.setRequestProperty("X-ApiKeys", "accessKey="+"43234;" + " secretKey="+"43234;");

        con.setDoInput(true);
        con.setDoOutput(true); //NOT NEEDED FOR GETS
        con.setRequestMethod("POST");
        con.setRequestProperty("Accept", "application/json");
        con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

                //First example of writing (works when writing a payload)
        OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
        writer.write(payload);
        writer.close();     

        //second attemp at writing, doens't work (wanted to replace {scan_id} in the url)
        DataOutputStream writer = new DataOutputStream(con.getOutputStream());
        writer.writeChars("scan_id=42324"); //tried writing directly
        //writer.write(payload);
        writer.close();     

例外:

Exception in thread "main" java.io.IOException: Server returned HTTP response code: 400 for URL: http://localhost/scans/launch

我想要三个响应代码之一,因为这样我就知道 URL 是正确的:

200 Returned if the scan was successfully launched. 
403 Returned if the scan is disabled. 
404 Returned if the scan does not exist. 

我已经尝试了几个网址

localhost/scans/launch, 
localhost/scans//launch, 
localhost/scans/?/launch, 
localhost/scans/{scan_id}/launch,

【问题讨论】:

  • 你使用的是路径参数吗? scan_id=42324 是一个查询参数。在您的情况下,路径参数应为http://localhost/scans/42324/launch
  • 我相信我希望 42324 出现在查询中。当我发送路径localhost/scans/42324/launch 时,API 不理解它并以 400 响应代码响应。

标签: java rest post parameters httpurlconnection


【解决方案1】:

所以在朋友和大家的帮助下,我解决了我的问题。

下面的代码是整个类中的所有代码,一点一点解释。在底部,您有完整的类及其所有语法等,它接受参数并返回一个字符串。

在 HTTP 请求中有某些部分。 在我的例子中,这些部分包括请求标头、Url 中的参数和有效负载。

根据 API,API 所需的某些变量需要进入它们各自的类别。

My ORIGINAL URL looked like this: "http://host:port/scans/{scan_id}/export?{history_id}"
I CHANGED to: "https://host:port/scans/" + scan_Id + "/export?history_id=" + ID;

我正在调用的 API 需要一个名为“格式”的有效载荷中的参数,并带有一个值。

String payload = "{\"format\" : \"csv\"}";

所以我用我的新 URL 打开了一个连接并设置了我需要设置的请求标头。

        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();

发出 GET 请求时应将 setDoOutput 注释掉。

        con.setDoInput(true);
        con.setDoOutput(true); 
        con.setRequestMethod("POST");
        con.setRequestProperty("Accept", "application/json");
        con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        con.setRequestProperty("X-Cookie", "token=" + token);
        con.setRequestProperty("X-ApiKeys", "accessKey="+"23243;" +"secretKey="+"45543;");

我在这里写入有效载荷。

        //WRITING THE PAYLOAD to the http call
        OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
        writer.write(payload);
        writer.close();

在我编写了有效负载后,我读取了我返回的任何响应(这取决于调用,当我执行文件下载(GET 请求)时,我没有读取响应,因为我已经阅读了通过另一段代码响应)。

我希望这对任何可能遇到此问题的人有所帮助。

public String requestScan(int scan_Id, String token, String ID) throws MalformedInputException, ProtocolException, IOException {

    try {
        String endpoint = "https://host:port/scans/" + scan_Id + "/export?history_id=" ID;
        URL url = new URL(endpoint);

        String payload= "{\"format\" : \"csv\"}";

        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();

        con.setDoInput(true);
        con.setDoOutput(true);
        con.setRequestMethod("POST");
        con.setRequestProperty("Accept", "application/json");
        con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        con.setRequestProperty("X-Cookie", "token=" + token);
        con.setRequestProperty("X-ApiKeys", "accessKey="+"324324;" + 
                "secretKey="+"43242;");

        //WRITING THE PAYLOAD to the http call
        OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
        writer.write(payload);
        writer.close();

        //READING RESPONSE
        BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
        StringBuffer jsonString = new StringBuffer();
        String line;
        while ((line = br.readLine()) != null) {
            jsonString.append(line);
        }
        br.close();
        con.disconnect();

        return jsonString.toString();
    } catch (Exception e) {
        throw new RuntimeException(e.getMessage());
    }
}

【讨论】:

    【解决方案2】:

    正如here 所讨论的那样,解决方案是将内容类型更改为application/x-www-form-urlencoded,但由于您已经在使用application/json; charset=UTF-8(我假设这是您的项目的要求),您无法重新设计整件事。我建议您选择以下方法之一:

    如果还有其他我不知道的解决方案,我不知道它们在多大程度上符合 HTTP 协议。

    (More info)

    希望我能帮上忙!

    【讨论】:

    • 我想我会更多地研究我是否可以更改内容类型或将其省略,当我知道更多时会返回:) 感谢帮助。
    • 我更改了内容类型,但不幸的是,我在定义开头的 URL 时仍然遇到问题。我以前只使用 localhost/scans 和 localhost/session 来访问 API,但是一旦有参数,我就找不到 API 调用,即使它是在我的代码顶部指定的。关于我将如何构建它的任何线索?。
    • 我在这个主题上没有太多经验,但我不会排除它是由于您的应用程序服务器和/或您的项目 maven 设置错误造成的,只有 url该作品实际上已出版。我会检查一下。
    • 它是一个外部资源,所以它如何发布确实是一个好问题。但我遇到了以某种方式让 URL 被接受的问题,无论是否存在扫描。但我真的很感谢你的帮助:)
    【解决方案3】:

    为什么你不这样使用。由于你需要对POSTHttpURLConnection做一个HttpURLConnection,所以你需要在打开连接后将参数写入连接。

    String urlParameters  = "scan_id=42324";
    byte[] postData       = urlParameters.getBytes(StandardCharsets.UTF_8);
    
    DataOutputStream dataOutputStream  = new DataOutputStream(conn.getOutputStream());
    dataOutputStream.write(postData);
    

    或者如果你最后有launch,只要把上面的代码改成下面这样,

    String urlParameters  = "42324/launch";
    byte[] postData       = urlParameters.getBytes(StandardCharsets.UTF_8);
    
    DataOutputStream dataOutputStream  = new DataOutputStream(conn.getOutputStream());
    dataOutputStream.write(postData);
    

    【讨论】:

    • 考虑到我会这样做,原始 URI 会是什么样子? - localhost/scans/launch, - localhost/scans//launch, - localhost/scans/?/launch, - localhost/scans/{scan_id}/launch,
    • 在添加上述代码(都尝试过)并更改 url 后仍然以某种方式失败。我不确定我做错了什么,因为我只是不断收到 400 .. 我只能怀疑 URL 因为它与 localhost/session 上的 POST 一起使用,但不适用于 localhost/scans 等。如果我之前没有说清楚,我想补充一下,提供的 url 是 localhost/scans/{scan_id}/launch 其中 localhost 是正确主机的替代品,因为它是私有的。
    【解决方案4】:
    URL url = new URL("http://localhost/scans/{scan_id}/launch");
    

    那条线在我看来很奇怪;看来您正在尝试使用一个 URL,您打算在其中使用 URI Template 的行为。

    确切的语法取决于您选择的模板实现;使用Spring libraries 的实现可能如下所示:

    import org.springframework.web.util.UriTemplate;
    import java.net.url;
    
    // Warning - UNTESTED code ahead
    UriTemplate template = new UriTemplate("http://localhost/scans/{scan_id}/launch");
    Map<String,String> uriVariables = Collections.singletonMap("scan_id", "42324");
    URI uri = template.expand(uriVariables);
    URL url = uri.toURL();
    

    【讨论】:

    • 我尝试使用 spring 库在 spring 中实现您的示例,它告诉我无法从 UriTemplate 转换为 URL(UriTemplate 源于 springframework)。任何进一步的说明?老实说,我在当前的实现中有点走下坡路,想知道你是否还有什么可以推荐的,仍然适用于 Java?我可以添加到请求标头和有效负载中,这一点很重要。任何反馈表示赞赏:)
    • 示例已更新 - 我在转录中犯了一个错误
    猜你喜欢
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多