2016-03-04 4 views
2

Я пытаюсь написать базовый веб-сервис, который использует аннотацию JAX-RS @QueryParam. Мой клиент Java отправляет запрос POST с использованием HttpURLConnection. Вызов выполняется в веб-службе, но параметры не отправляются правильно (они остаются пустыми). Я знаю, что в StackOverflow много вопросов, связанных с этим, но я не мог найти убедительного решения. Будет здорово, если кто-то укажет на ошибку в приведенном ниже коде. (Я упростил код для публикации здесь).Как отправить параметры запроса на запрос POST с Java-клиента и получить с помощью @QueryParam

Вот код веб-сервис:

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

И это 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(); 
} 

Мой веб-сервис вызывался, но значения параметров, полученных в нуль. Пожалуйста помоги.

+0

Этот код предназначен только для Android JDK или для Windows JDK? – user3002512

ответ

1

@QueryParam только распознает параметры, которые являются частью URL-адреса. Вам нужно использовать @FormParam вместо этого, чтобы прочитать параметры из тела POST.

2

Чтобы связать значение (ы) параметра HTTP запроса для параметра метода ресурса с использованием @QueryParam, вам необходимо отправить параметры в строке запроса URL:

3.4. Query

Компонент запроса содержит неиерархические данные, которые вместе с данными в компоненте пути служат для идентификации ресурса в рамках схемы URI и полномочий именования (если есть). Компонент запроса указывается первым символом вопроса («?») И заканчивается символом числа («#») или к концу URI.

[...]

По умолчанию в GET запросов, параметры посланы как часть URL. В запросах POST параметры отправлены в теле запроса.

Чтобы отправить параметры запрос в POST запросы с HttpURLConnection, Append их к запрошенному 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(); 

... 
1

Обратите внимание, что RFC2616 устарела с 2014 года, он заменяется rfc723x спецификации. Нет rfc723x серверов не существует в данный момент

compilant сервер rfc723x ответит со статусом 400:

  • Когда запрос прибудет имеет тело сообщения.
  • Когда запрос на отправку имеет параметры в запросе uri.

Создание сервера, который будет принимать оба, небезопасно по дизайну. Параметры Uri могут и будут подделываться хакером. Когда параметр находится в запросе uri и в теле сообщения, как безопасно обрабатывать эту ситуацию? Что имеет приоритет?

Единственный разумный ответ - отклонить такой запрос со статусом 400. Вы, как программист, не можете провести различие между законным пользователем и хакером в этой ситуации.

rfc7230 также указывает, что параметры могут возникать только один раз. Почему? Пример:

Для кого вы голосуете? http://voting.com/?vote=clinton очевидно Клинтон

Для кого вы голосовали? http://voting.com/?vote=trump&vote=clinton Trump? Клинтон? Трамп и Клинтон?

Для кого вы голосовали? http://voting.com/?vote=trump&vote=clinton&vote=trump Трамп? Трамп 2 раза и Клинтон 1 раз?

серверы rfc2616 принимают это и возвращают массив значений для голосования и ненадежны по дизайну в этой точке.