如何将查询参数发送到来自 Java 客户端的 POST 请求,并使用 @QueryParam 接收

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35796264/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 00:36:30  来源:igfitidea点击:

How to send query parameters to POST request from Java client, and receive using @QueryParam

javaweb-servicesrestjax-rsquery-parameters

提问by Akhil Dixit

I'm trying to write a basic web service that uses JAX-RS @QueryParam annotation. My Java client sends a POST request using HttpURLConnection. The call is being made to the web service, but the parameters are not getting sent correctly (They remain null). I know there are lot of questions related to this on StackOverflow, but I couldn't find a convincing solution. It'll be great if somebody points out the mistake in the code below. (I've simplified the code for posting here).

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

Here's the web service code:

这是网络服务代码:

@POST
@Path("/notify")
@Consumes("*/*")
public Response notifyUser(@QueryParam("notification") String notification, @QueryParam("applicationName") String applicationName) {
    System.out.println("Notification: " + notification);
    System.out.println("Application: " + applicationName);
    return Response.status(200).entity(notification + " from " + applicationName).build();
}

And this is Java client:

这是 Java 客户端:

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();
}

My web service is getting called, but the parameter values are received as null. Please help.

我的 Web 服务被调用,但参数值被接收为空值。请帮忙。

回答by cassiomolin

To bind the value(s) of a HTTP query parameter to a resource method parameter using @QueryParam, you need to send your parameters in the query string of the URL:

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

3.4. Query

The query component contains non-hierarchical data that, along with data in the path component, serves to identify a resource within the scope of the URI's scheme and naming authority (if any). The query component is indicated by the first question mark ("?") character and terminated by a number sign ("#") character or by the end of the URI.

[...]

3.4. 询问

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

[...]

By default, in GETrequests, the parameters are sent as part of the URL. In POSTrequests, the parameters are sent in the body of the request.

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

To send query parametersin POSTrequests with HttpURLConnection, appendthem to the requested URL, as following:

要发送的查询参数POST有要求HttpURLConnection追加他们请求的URL,如下:

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();

...

回答by wero

@QueryParamonly recognizes parameters which are part of the URL. You need to use @FormParaminstead in order to read the parameters from the POST body.

@QueryParam仅识别作为 URL 一部分的参数。您需要改为使用@FormParam以从 POST 正文中读取参数。

回答by Vicky Ronnen

Note that rfc2616 is obsolete since 2014, it's replaced by the rfc723x specs. No rfc723x servers exists at this moment

请注意,rfc2616 自 2014 年起已过时,它已被 rfc723x 规范取代。目前不存在 rfc723x 服务器

A rfc723x compilant server will respond with status 400:

rfc723x 兼容服务器将响应状态 400:

  • When a get request has a message body.
  • When a post request has parameters in the request uri.
  • 当获取请求具有消息正文时。
  • 当 post 请求在请求 uri 中有参数时。

Creating a server that will accept both are insecure by design. Uri parameters can and will be forged by a hacker. When a parameter is in the request uri and in the message body, how to securely handle this situation? Which has precedence?

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

The only reasonable answer is to reject such a request with status 400. You as a programmer cannot make the distinction between a legal user and a hacker in this situation.

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

rfc7230 also specifies that parameters may only occur once. Why? An example:

rfc7230 还规定参数只能出现一次。为什么?一个例子:

Who do you vote for? http://voting.com/?vote=clintonobviously Clinton

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

Who do you vote for? http://voting.com/?vote=trump&vote=clintonTrump? Clinton? Trump and Clinton?

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

Who do you vote for? http://voting.com/?vote=trump&vote=clinton&vote=trumpTrump? Trump 2 times and Clinton 1 time?

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

rfc2616 servers accept this and return an array of values for vote and are insecure by design on this point.

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