Java 带正文的http get请求

Java 带正文的http get请求,java,scala,http,get,Java,Scala,Http,Get,我知道您不应该发送带有主体的HTTP GET请求,但ceilometer web api迫使我这样做。 我正在开发一个ceilometer scala客户机,因此我需要一种scala/java方法来使用主体发出get请求。 到目前为止,我尝试使用beeClient()和纯Java使用httpConnection,但得到了404错误。 在curl中,我可以通过以下方式获得结果: curl -X GET -H "X-Auth-Token: ..long long token here.." -H

我知道您不应该发送带有主体的HTTP GET请求,但ceilometer web api迫使我这样做。 我正在开发一个ceilometer scala客户机,因此我需要一种scala/java方法来使用主体发出get请求。 到目前为止,我尝试使用beeClient()和纯Java使用httpConnection,但得到了404错误。 在curl中,我可以通过以下方式获得结果:

curl -X GET -H "X-Auth-Token: ..long long token here.." 
-H "Content-Type: application/json" 
-d '{"q": [{"field": "resource", "op": "eq", "value": "gdfsf"}]}'
http://137.204.57.150:8777/v2/meters/
这是我使用java HttpURLConnection的scala代码:

import java.io._
import java.net._
val token = "myToken"
val url = new URL("http://137.204.57.150:8777/v2/meters/")
val body = "{\"q\": [{\"field\": \"resource\", \"op\": \"eq\", \"value\": \"gdfsf\"}]}"
val bodyLenght = body.length.toString
val connection = url.openConnection().asInstanceOf[HttpURLConnection]
connection.setRequestMethod("GET")
connection.setRequestProperty("Content-Type", "application/json")
connection.setRequestProperty("Content-Length", bodyLength)
connection.setRequestProperty("Accept", "*/*")
connection.setRequestProperty("X-Auth-Token", token)
connection.setDoInput(true)
connection.setDoOutput(true)
//SEND REQUEST
val wr = new DataOutputStream(connection.getOutputStream)
wr.write(body.getBytes)
wr.flush
wr.close
if (connection.getResponseCode == 200) 
    println("ok")
else
    println("error")
我的Java实现和curl命令之间有什么区别?我看不到,我试着检查curl的头,用-v参数调用它,这就是我得到的结果:

* Hostname was NOT found in DNS cache
*   Trying 137.204.57.150...
* Connected to 137.204.57.150 (137.204.57.150) port 8777 (#0)
> GET /v2/meters/ HTTP/1.1
> User-Agent: curl/7.37.1
> Host: 137.204.57.150:8777
> Accept: */*
> X-Auth-Token: ...Token....
> Content-Type: application/json
> Content-Length: 60
> 
* upload completely sent off: 60 out of 60 bytes
* HTTP 1.0, assume close after body
然后我得到了回应


提前感谢您

您在发送Celiometer API的请求正文时使用HTTP PUT或POST请求

我查看了Ceilometer文档,发现所有带有请求体的请求都使用HTTP PUT或POST方法。没有请求主体的GET方法。

一般来说,该规范不禁止任何类型的http请求(GET、DELETE等)的正文,因此您可以在需要时执行。然而,按照惯例,这是不典型的

您遇到的问题是,在您使用的URLConnection的实现中,有一些关于您可以做什么和不能做什么的假设。通常,您将使用一个HttpUrlConnection(当您转换到时),它实际上将由jvm实现。例如,下面是一个例子

如果您查看这个实现,您将看到它假定需要输出流的GET请求实际上是一个POST


如果您想要一个带有主体的GET,则需要使用不同的连接方法,例如apachehttp客户端之类的库。你可以先看看。首先,您可能会有更好的scala替代方案。

在查看了云高计和旋度的文档后,我可以提出两个建议

  • 使用URL参数而不是JSON
  • 根据文档,您可以使用URL参数或JSON。您可以按照下面的说明修改请求,以使用URL参数而不是JSON实现相同的功能

    URL("http://YOURHOST.COM:8777/v2/meters/?q.field=resource&q.op=eq&q.value=gdfsf")
    
  • 如果您有特定的理由不在JSON方法中使用URL参数,我想您的请求中缺少的就是编码。只需要在查询参数中发送参数,而不需要在正文内容中发送参数。为此,我想您需要根据您在问题中的请求,尝试使用如下所示的编码数据

    URL(“”)

  • 这里q是根查询参数名,没有令牌,我无法验证它


    将YOURHOST.COM替换为服务器的ip地址,因为即使将它们放入代码块中,它也会向我显示问题,请告诉我。

    您也可以这样尝试

    @RequestMapping(value=“/listcategories”,method=RequestMethod.GET)

    private model和view getCategories(){
    ModelAndView ModelAndView=新的ModelAndView(“类别列表”);
    List categories=categoryService.getAllCategories();
    添加对象(“类别”,类别);
    返回模型和视图;
    }
    
    我使用jetty客户端实现解决了这个问题,它允许以任何方式构建http请求。下面是代码(它不是一成不变的,但在scala中也不是那么糟糕):


    看,我正在使用blocking API,但jetty也提供了Java NIO API。

    我找到了一个普通的Java解决方案,使用apache的
    httpclient
    httpcore
    commons logging
    libs

    您需要创建一个类并扩展
    HttpEntityEnclosingRequestBase
    ,覆盖方法名称:

    import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
    
    public class HttpGetWithEntity extends HttpEntityEnclosingRequestBase {
        public final static String METHOD_NAME = "GET";
    
        @Override
        public String getMethod() {
            return METHOD_NAME;
        }
    }
    
    然后你就这样使用它:

    HttpClient httpClient = HttpClientBuilder.create().build();
    HttpGetWithEntity e = new HttpGetWithEntity();
    e.setURI(new URI(yourURL))
    e.setEntity(yourEntity);
    HttpResponse response = httpclient.execute(e);
    

    希望有帮助。

    您的代码在哪里?HTTP规范没有说任何关于GET主体的内容,这意味着实现可以决定是否允许GET主体。我相信您应该能够以Java.httpget请求的主体形式发送GET。所以你不能这么做。@ElliottFrisch我不得不这么做,如果你看一下这里的ceilometer web api文档,你会发现用户可能会在get请求的主体内传递查询参数。我认为这在pythonapi中是可能的,在curl中显然是可能的。我知道标准不允许给get请求主体赋予语义。但是我必须这样做,过去有人已经用Java()回答了类似的问题。也许你可以让它为scala工作?也链接到这个错误:看这一节的最后一个curl命令:我明白你的意思了。不过,它仍然允许您在GET请求中使用URL参数。>“应该使用上述方法之一对查询参数进行编码,例如作为URL参数或作为传递给GET请求的JSON编码数据。”我在一个能够解析和序列化complexqueries以及从JSON到JSON的内容的库上下了很大功夫。我不想使用get参数可以执行的简单查询。恐怕最好的方法是避免get请求中的body,使用更简单的URI参数。很高兴您知道我们可以为您的需求的Ceilometer API使用URL参数。我解决了使用jetty客户端传递GET请求体中编码的json的问题。我无法在普通java中实现这一点,因为HttpURLConnection的实现没有提供这一功能?你能在这里分享一下你的Jetty客户端代码吗?谢谢,但它没有显示你是如何将查询的正文或内容传递给ceilometer Api的。对不起,我错过了,只需添加:content(新的StringContentProvider(body))。send()
    org.eclipse.jetty.client.HttpClient
    ,与ApacheHttpClient相比,它看起来更容易处理
    import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
    
    public class HttpGetWithEntity extends HttpEntityEnclosingRequestBase {
        public final static String METHOD_NAME = "GET";
    
        @Override
        public String getMethod() {
            return METHOD_NAME;
        }
    }
    
    HttpClient httpClient = HttpClientBuilder.create().build();
    HttpGetWithEntity e = new HttpGetWithEntity();
    e.setURI(new URI(yourURL))
    e.setEntity(yourEntity);
    HttpResponse response = httpclient.execute(e);