Метод POST на почтовом отправлении получает нулевые значения в качестве параметров

Я разрабатываю услуги RESTful с Джерси, и он отлично работает с методами GET. Однако я не могу заставить его работать с методами POST и JSON или текстовыми параметрами. Это то, что я сделал:

@Path("/method/")
@POST
@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
@Produces({MediaType.APPLICATION_JSON})
public ResponseObject method(@Context Request request, @PathParam("ob1") Object obj1, @PathParam("obj2") String obj2) {
...
}

Я получаю только нулевые значения для всех параметров. Я попытался использовать только строку в качестве параметра, и он тоже не работает... Я пытаюсь получить доступ к этим методам из IOS и, возможно, к одной из проблем. Однако я обнюхивал свою локальную сеть, и я могу видеть правильные параметры в корпусе пакета... это правильно?

Я отправил из XCode другое содержимое тела как:

obj1={"id1": "value1", "id2" : "value2"}&obj2=xxxx

и

{"id1": "value1", "id2" : "value2"},xxxx

в то время как я играл с @QueryParam и @PathParam без результатов... всегда null...

Спасибо за вашу помощь!

Ответ 1

Параметр пути - это часть URL-адреса запроса, соответствующего определенному шаблону. Таким образом, существуют ограничения характера для того, что можно указать как параметр пути, в частности, любые специальные символы должны быть закодированы в URL. Это применяется одинаково для любого запроса (GET, POST, PUT, DELETE).

Как правило, вы должны ограничить параметры своего пути такими простыми значениями, как идентификаторы или конечные точки ресурса - более сложные данные должны быть переданы службе REST через параметры запроса или сам запрос. Здесь используется смешанный подход, который передает идентификатор объекта в качестве параметра пути и данные сущности в теле запроса:

@Path("/contacts/{id}")
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response updateContact(@PathParam final String contactId, Contact contact) {
}

В приведенном выше примере contactId получается как параметр пути, и контакт сериализуется автоматически из тела запроса.

То, что я описал выше, - это общие правила. Что касается специфики вашего случая, то одно замечание, которое я заметил в вашем коде, заключается в том, что вы фактически не определяете параметры пути. Помните, что они должны быть определены как часть вашей аннотации @Path, прежде чем их использовать в методе REST:

@Path("/method/{obj1}/{obj2}")
public ResponseObject method(@Context Request request, @PathParam("obj1") Object obj1, @PathParam("obj2") String obj2) {
}

При указанных выше изменениях ваши параметры больше не будут отображаться как null, если вы правильно закодировали URL-адрес на стороне клиента.


* РЕДАКТИРОВАТЬ *

Основываясь на вашем комментарии, я вижу, вам нужно более подробно ознакомиться с спецификацией JAX-RS и различными типами параметров. Я рекомендую прочитать документацию RESTEasy JAX-RS. В нем есть некоторые детали реализации конкретного поставщика, но в целом это отличное руководство для JAX-RS.


@PathParam

Цель. Используется для вставки части URL-адреса запроса в переменную. Обратите внимание, что параметры URL не считаются частью URL.

Пример: учитывая URL http://services.example.com/contacts/20578, я могу определить:

@Path("/contacts/{id}")

Из которого я могу ввести a @PathParam("id").

public Response getContact(@PathParam("id") final String identifier);

Это работает для любого HTTP-запроса (GET, POST, PUT, DELETE).


@QueryParam

Цель. Используется для ввода части строки запроса или форматирования закодированных данных в переменную. Строка запроса - это часть вашего URL-адреса после ?. Формированные кодированные данные представляют собой данные с паролем имени/значения URL, переданные в теле HTTP-запроса, когда тип запроса - application/x-www-form-urlencoded. Как правило, параметры запроса передаются как часть строки URL для запросов GET, а в теле запроса для запросов POST.

Пример. Учитывая URL http://services.example.com/contacts?group=Business, я могу ввести @QueryParam("group")

public Response getContactsInGroup(@QueryParam("group") final String groupName);

Нестандартно использовать параметры запроса с запросом POST, но это возможно, если тип запроса - application/x-www-form-urlencoded:

@POST
@Path("/contacts")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response createContact(@QueryParam("contact") final Contact contactData, @QueryParam("metadata") final String metaData);

Это просто примеры высокого уровня, пожалуйста, прочитайте документацию. Я связался, чтобы получить лучший пример того, как работает каждый тип параметра, и когда использовать его.

Ответ 2

Я только начал разрабатывать webservice в java и имел ту же проблему с данными POST. Я получил очень простое решение для чтения данных POST с помощью @FormParam, на самом деле я использовал @QueryParam, чтобы читать данные POST, я думаю, что это только для чтения данных QueryString с использованием метода GET

Очень хорошая документация, приведенная здесь. Прочитав эту статью, большинство моих заметок были очищены. http://docs.jboss.org/resteasy/docs/2.0.0.GA/userguide/html_single/index.html

Совет. Просто убедитесь, что вы используете тип mime "application/x-www-form-urlencoded" при использовании @FormParam

Ответ 3

Я бы опубликовал это как комментарий к принятому ответу, но я просто стесняюсь этого сделать.

В дополнение к превосходному совету выше, я бы добавил, что, по крайней мере, в версии 2.0.x Джерси не вытаскивает @FormParam из строки запроса. Вместо этого он ожидает, что он будет включен как пара имен и значений в тело запроса.

Например, вместо POST http://localhost/app?name=Joe вы отправите  POST http://localhost/app с телом:

name=Joe

Ответ 4

Предположим, что у нас есть объект tenant, который имеет атрибуты id и name, а ресурс REST - через @POST и @PATH("/xyz/tenants").

Пример тела в JSON:

{"id":"001","name":"myname"}

Пример тела в XML:

<tenant><id>001</id><name>myname</name></tenant>