【问题标题】:How to use parameters with HttpPost如何在 HttpPost 中使用参数
【发布时间】:2011-12-28 13:05:30
【问题描述】:

我正在通过这种方法使用 RESTfull 网络服务:

@POST
@Consumes({"application/json"})
@Path("create/")
public void create(String str1, String str2){
System.out.println("value 1 = " + str1);
System.out.println("value 2 = " + str2);
}

在我的 Android 应用程序中,我想调用此方法。如何使用 org.apache.http.client.methods.HttpPost 为参数提供正确的值;

我注意到我可以使用注解 @HeaderParam 并简单地将标头添加到 HttpPost 对象。这是正确的方法吗?这样做:

httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("str1", "a value");
httpPost.setHeader("str2", "another value");

在 httpPost 上使用 setEntity 方法不起作用。它仅使用 json 字符串设置参数 str1。像这样使用它时:

JSONObject json = new JSONObject();
json.put("str1", "a value");
json.put("str2", "another value");
HttpEntity e = new StringEntity(json.toString());
httpPost.setEntity(e);
//server output: value 1 = {"str1":"a value","str2":"another value"} 

【问题讨论】:

    标签: java android json web-services http-post


    【解决方案1】:

    要为您的HttpPostRequest 设置参数,您可以使用BasicNameValuePair,如下所示:

        HttpClient httpclient;
        HttpPost httpPost;
        ArrayList<NameValuePair> postParameters;
        httpclient = new DefaultHttpClient();
        httpPost = new HttpPost("your login link");
    
    
        postParameters = new ArrayList<NameValuePair>();
        postParameters.add(new BasicNameValuePair("param1", "param1_value"));
        postParameters.add(new BasicNameValuePair("param2", "param2_value"));
    
        httpPost.setEntity(new UrlEncodedFormEntity(postParameters, "UTF-8"));
    
        HttpResponse response = httpclient.execute(httpPost);
    

    【讨论】:

    • 当我在有和没有@QueryParam 注释的情况下执行此操作时。 webapp中的参数和null。
    • 您不需要对此进行任何注释。只需输入您的参数名称和值,例如:debug_data=1username_hash=jhjahbkzjxcjkahcjkzhbcjkzhbxcjshd 我正在将此代码与参数一起使用,对我来说没有问题。
    • 没有注释是值也是空的。
    • 所以问题应该出在你的代码和你放置值的方式上。
    • 当你的代码这样做时,web应用程序中的方法就会被调用。它所做的第一件事是将值打印到记录器。它说它们是空的。我怀疑这与我的 webapp 代码有关。
    【解决方案2】:

    如果你想传递一些http参数并发送一个json请求,你也可以使用这种方法:

    (注意:我添加了一些额外的代码,以防它帮助任何其他未来的读者)

    public void postJsonWithHttpParams() throws URISyntaxException, UnsupportedEncodingException, IOException {
    
        //add the http parameters you wish to pass
        List<NameValuePair> postParameters = new ArrayList<>();
        postParameters.add(new BasicNameValuePair("param1", "param1_value"));
        postParameters.add(new BasicNameValuePair("param2", "param2_value"));
    
        //Build the server URI together with the parameters you wish to pass
        URIBuilder uriBuilder = new URIBuilder("http://google.ug");
        uriBuilder.addParameters(postParameters);
    
        HttpPost postRequest = new HttpPost(uriBuilder.build());
        postRequest.setHeader("Content-Type", "application/json");
    
        //this is your JSON string you are sending as a request
        String yourJsonString = "{\"str1\":\"a value\",\"str2\":\"another value\"} ";
    
        //pass the json string request in the entity
        HttpEntity entity = new ByteArrayEntity(yourJsonString.getBytes("UTF-8"));
        postRequest.setEntity(entity);
    
        //create a socketfactory in order to use an http connection manager
        PlainConnectionSocketFactory plainSocketFactory = PlainConnectionSocketFactory.getSocketFactory();
        Registry<ConnectionSocketFactory> connSocketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", plainSocketFactory)
                .build();
    
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(connSocketFactoryRegistry);
    
        connManager.setMaxTotal(20);
        connManager.setDefaultMaxPerRoute(20);
    
        RequestConfig defaultRequestConfig = RequestConfig.custom()
                .setSocketTimeout(HttpClientPool.connTimeout)
                .setConnectTimeout(HttpClientPool.connTimeout)
                .setConnectionRequestTimeout(HttpClientPool.readTimeout)
                .build();
    
        // Build the http client.
        CloseableHttpClient httpclient = HttpClients.custom()
                .setConnectionManager(connManager)
                .setDefaultRequestConfig(defaultRequestConfig)
                .build();
    
        CloseableHttpResponse response = httpclient.execute(postRequest);
    
        //Read the response
        String responseString = "";
    
        int statusCode = response.getStatusLine().getStatusCode();
        String message = response.getStatusLine().getReasonPhrase();
    
        HttpEntity responseHttpEntity = response.getEntity();
    
        InputStream content = responseHttpEntity.getContent();
    
        BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
        String line;
    
        while ((line = buffer.readLine()) != null) {
            responseString += line;
        }
    
        //release all resources held by the responseHttpEntity
        EntityUtils.consume(responseHttpEntity);
    
        //close the stream
        response.close();
    
        // Close the connection manager.
        connManager.close();
    }
    

    【讨论】:

      【解决方案3】:

      一般来说,HTTP POST 假定正文的内容包含一系列键/值对,这些键/值对是(最常见的)由 HTML 端的表单创建的。您不要使用 setHeader 设置值,因为这不会将它们放在内容正文中。

      因此,在您的第二个测试中,您遇到的问题是您的客户端没有创建多个键/值对,它只创建了一个并且默认映射到您方法中的第一个参数。

      您可以使用几个选项。首先,您可以更改您的方法以仅接受一个输入参数,然后像在第二个测试中所做的那样传入一个 JSON 字符串。进入方法后,您可以将 JSON 字符串解析为允许访问字段的对象。

      另一种选择是定义一个表示输入类型字段的类,并使其成为唯一的输入参数。例如

      class MyInput
      {
          String str1;
          String str2;
      
          public MyInput() { }
            //  getters, setters
       }
      
      @POST
      @Consumes({"application/json"})
      @Path("create/")
      public void create(MyInput in){
      System.out.println("value 1 = " + in.getStr1());
      System.out.println("value 2 = " + in.getStr2());
      }
      

      根据您使用的 REST 框架,它应该为您处理 JSON 的反序列化。

      最后一个选项是构造一个如下所示的 POST 正文:

      str1=value1&str2=value2
      

      然后为您的服务器方法添加一些额外的注释:

      public void create(@QueryParam("str1") String str1, 
                        @QueryParam("str2") String str2)
      

      @QueryParam 不关心该字段是在表单帖子中还是在 URL 中(如 GET 查询)。

      如果您想继续在输入中使用单个参数,那么关键是生成客户端请求以在 URL(对于 GET)或 POST 正文中提供命名查询参数。

      【讨论】:

      • 还有一个问题就是发送的字符串可以有/
      • 另外,当我想让方法也使用 XML 时,这不会像这样工作。
      • 作为 Query 参数值包含的所有字符串都应经过正确的 URL 编码,因此如果您按照上述方式构建帖子,则预期这些值将经过 URL 编码。所以是的,您可以发送 XML,您只需要首先通过 URL 编码机制运行它。如果您在表单上有一个文本区域并输入 XML,这就是您的浏览器会执行的操作。
      • URL 编码器不会将“”变成“+”。还有更多类似的吗?那这行不通,因为我也希望能够发送一个“+”。
      • 阅读 java.net.URLEncoder 类,它将解释它的作用。基本上它会将空格编码为 + 但会将文本中的加号编码为它们的 %xx 等价物,因此它会处理这些细节。如果您将发送的内容类型设置为 application/x-www-form-urlencoded REST 包将自动为您解码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多