如何从Java客户端向POST请求发送查询参数,并使用@QueryParam接收

时间:2016-03-04 12:36:18

标签: java web-services rest jax-rs query-parameters

我正在尝试编写一个使用JAX-RS @QueryParam注释的基本Web服务。我的Java客户端使用HttpURLConnection发送POST请求。正在调用Web服务,但参数未正确发送(它们保持为空)。我知道在StackOverflow上有很多与此相关的问题,但我找不到令人信服的解决方案。如果有人在下面的代码中指出错误,那就太棒了。 (我已经简化了在这里发布的代码)。

这是网络服务代码:

public static void main(String args[]) {
    URL url;
    HttpURLConnection conn = null;
    try {
         url = new URL("http://localhost:8080/...");
         conn = (HttpURLConnection) url.openConnection();
         conn.setDoOutput(true);
         conn.setRequestMethod("POST");
         conn.setDoInput(true);
         conn.setDoOutput(true);
         conn.setRequestProperty("Content-Type", "application/json");
         conn.setRequestProperty("charset", "UTF-8");
         OutputStream os = conn.getOutputStream();
         List<NameValuePair> params = new ArrayList<NameValuePair>();
         params.add(new NameValuePair("notification", "Notification string"));
         params.add(new NameValuePair("applicationName", "MyApp"));
         os.write(getQuery(params).getBytes("UTF-8"));
         os.flush();
         os.close();
         return conn.getResponseCode();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return -1;
    } finally {
        if (conn != null) {
            conn.disconnect();
        }
    }
}

private String getQuery(List<NameValuePair> params) throws UnsupportedEncodingException {
    StringBuilder result = new StringBuilder();
    boolean first = true;

    for (NameValuePair pair : params) {
        if (first)
            first = false;
        else
            result.append("&");

        result.append(URLEncoder.encode(pair.getName(), "UTF-8"));
        result.append("=");
        result.append(URLEncoder.encode(pair.getValue(), "UTF-8"));
    }

    return result.toString();
}

这是Java客户端:

TodoList

我的Web服务正在调用,但参数值收到null。请帮忙。

3 个答案:

答案 0 :(得分:3)

要使用@QueryParam将HTTP查询参数的值绑定到资源方法参数,您需要在URL的查询字符串中发送您的参数

  

3.4. Query

     

查询组件包含非分层数据   路径组件中的数据用于标识a   URI的方案和命名权限范围内的资源   (如果有的话)。查询组件由第一个问题指示   标记(“?”)字符并以数字符号(“#”)字符结束   或者在URI的末尾。

     

[...]

默认情况下,在GET个请求中,参数作为URL的一部分发送。在POST请求中,参数在请求正文中发送

要使用HttpURLConnectionPOST个请求中发送查询参数附加到请求的网址,如下所示:

List<NameValuePair> params = new ArrayList<>();
params.add(new NameValuePair("param1", "value1"));
params.add(new NameValuePair("param2", "value2"));

String query = getQuery(params);
URL url = new URL("http://localhost:8080/api" + "?" + query);
URLConnection connection = url.openConnection();

...

答案 1 :(得分:1)

@QueryParam仅识别属于URL的参数。您需要使用@FormParam代替来从POST正文中读取参数。

答案 2 :(得分:1)

请注意,rfc2616自2014年起已过时,它已被rfc723x规格所取代。目前还没有rfc723x服务器

rfc723x compilant服务器将以状态400响应:

  • 当get请求有邮件正文时。
  • 当请求中有参数时,请求uri。

创建将接受两者的服务器在设计上是不安全的。 Uri参数可以并且将由黑客伪造。 当参数在请求uri和消息体中时,如何安全地处理这种情况?哪个优先?

唯一合理的答案是拒绝状态为400的请求。在这种情况下,作为程序员,您无法区分合法用户和黑客。

rfc7230还指定参数可能只发生一次。 为什么?一个例子:

你投票给谁? http://voting.com/?vote=clinton 显然克林顿

你投票给谁? http://voting.com/?vote=trump&vote=clinton 王牌?克林顿?特朗普和克林顿?

你投票给谁? http://voting.com/?vote=trump&vote=clinton&vote=trump 王牌?特朗普2次,克林顿1次?

rfc2616服务器接受这个并返回一组值进行投票,并且在这一点上设计不安全。