Як отримати доступ до параметрів у методі RESTful POST


123

Мій метод POST виглядає так:

@POST
@Consumes({"application/json"})
@Path("create/")
public void create(String param1, String param2){
    System.out.println("param1 = " + param1);
    System.out.println("param2 = " + param2);
}

Коли я створюю клієнта Джерсі в Netbeans, метод, який викликає метод публікації, виглядає приблизно так:

public void create(Object requestEntity){
    webResource.path("create").type(MediaType.APPLICATION_JSON).post(requestEntity);
}

Під час виконання цього тесту:

@Test
public void hello(){
    String json = "{param1=\"hello\",param2=\"hello2\"}";
    this.client.create(json);
}

Він дає наступний вихід на сервер:

INFO: param1 = {param1="hello",param2="hello2"}
INFO: param2 = 

Що потрібно змінити, щоб параметри давали правильне значення?


ви використовуєте це в додатку для Android чи ні?
Android-Droid

Нарешті, я хочу назвати цей метод публікації в додатку для Android. Якось веб-сервіс не знає, як підписати значення до параметрів. Я хочу знати, як це зробити.
Klaasvaak

Відповіді:


356

Ваш @POSTметод повинен приймати об'єкт JSON замість рядка. Джерсі використовує JAXB, щоб підтримувати об'єкти JSON, що займаються маршируванням та знешкодженням (детальніше дивіться документи про майки ). Створіть клас на кшталт:

@XmlRootElement
public class MyJaxBean {
    @XmlElement public String param1;
    @XmlElement public String param2;
}

Тоді ваш @POSTметод виглядатиме так:

@POST @Consumes("application/json")
@Path("/create")
public void create(final MyJaxBean input) {
    System.out.println("param1 = " + input.param1);
    System.out.println("param2 = " + input.param2);
}

Цей метод очікує отримання об'єкта JSON як тіла HTTP POST. JAX-RS передає тіло вмісту повідомлення HTTP як неозначений параметр - inputу цьому випадку. Фактичне повідомлення виглядатиме приблизно так:

POST /create HTTP/1.1
Content-Type: application/json
Content-Length: 35
Host: www.example.com

{"param1":"hello","param2":"world"}

Використання JSON таким способом є досить поширеним з очевидних причин. Однак, якщо ви генеруєте або використовуєте його в чомусь іншому, ніж JavaScript, тоді вам потрібно бути обережним, щоб належним чином уникнути даних. У JAX-RS ви використовуєте MessageBodyReader та MessageBodyWriter для цього. Я вважаю, що Джерсі вже має реалізацію для необхідних типів (наприклад, Java примітивів та класів, оброблених JAXB), а також для JSON. JAX-RS підтримує ряд інших методів передачі даних. Вони не вимагають створення нового класу, оскільки дані передаються за допомогою простого передачі аргументів.


HTML <FORM>

Параметри будуть помічені за допомогою @FormParam :

@POST
@Path("/create")
public void create(@FormParam("param1") String param1,
                   @FormParam("param2") String param2) {
    ...
}

Браузер кодує форму за допомогою "application / x-www-form-urlencoded" . Виконання JAX-RS подбає про декодування тіла та передачу його методу. Ось що ви повинні побачити на дроті:

POST /create HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 25

param1=hello&param2=world

У цьому випадку вміст кодується URL-адресою .

Якщо ви не знаєте імен FormParam, ви можете зробити наступне:

@POST @Consumes("application/x-www-form-urlencoded")
@Path("/create")
public void create(final MultivaluedMap<String, String> formParams) {
    ...
}

HTTP заголовки

Ви можете використовувати анотацію @HeaderParam, якщо хочете передати параметри через заголовки HTTP:

@POST
@Path("/create")
public void create(@HeaderParam("param1") String param1,
                   @HeaderParam("param2") String param2) {
    ...
}

Ось як виглядатиме повідомлення HTTP. Зауважте, що цей POST не має тіла.

POST /create HTTP/1.1
Content-Length: 0
Host: www.example.com
param1: hello
param2: world

Я б не використовував цей метод для передачі узагальнених параметрів. Це дуже зручно, якщо вам потрібно отримати доступ до значення певного заголовка HTTP.


Параметри запиту HTTP

Цей метод використовується в основному з HTTP GET, але він однаково застосовний до POST. Він використовує анотацію @QueryParam .

@POST
@Path("/create")
public void create(@QueryParam("param1") String param1,
                   @QueryParam("param2") String param2) {
    ...
}

Як і в попередній техніці, для передачі параметрів через рядок запиту не потрібне тіло повідомлення. Ось повідомлення HTTP:

POST /create?param1=hello&param2=world HTTP/1.1
Content-Length: 0
Host: www.example.com

Вам потрібно бути особливо обережним, щоб правильно кодувати параметри запиту на стороні клієнта. Використання параметрів запиту може бути проблематичним через обмеження довжини URL-адреси, які застосовуються деякими проксі-серверами, а також проблеми, пов'язані з їх кодуванням.


Параметри шляху HTTP

Параметри шляху аналогічні параметрам запиту, за винятком того, що вони вбудовані в шлях до ресурсів HTTP. Цей метод, здається, сьогодні йде на користь. Існує вплив щодо кешування HTTP, оскільки шлях є тим, що дійсно визначає ресурс HTTP. Код виглядає дещо інакше, ніж інші, оскільки анотація @Path модифікована і вона використовує @PathParam :

@POST
@Path("/create/{param1}/{param2}")
public void create(@PathParam("param1") String param1,
                   @PathParam("param2") String param2) {
    ...
}

Повідомлення подібне до версії параметра запиту, за винятком того, що імена параметрів не містяться ніде в повідомленні.

POST /create/hello/world HTTP/1.1
Content-Length: 0
Host: www.example.com

Цей метод розділяє ті самі проблеми кодування, що і версія параметра запиту. Сегменти шляху кодуються по-різному, тому ви також повинні бути там обережними.


Як бачите, у кожного методу є плюси і мінуси. Вибір зазвичай вирішують ваші клієнти. Якщо ви FORMрозміщуєте HTML-сторінки на базі даних, тоді використовуйте @FormParam. Якщо вашими клієнтами є JavaScript + HTML5, ви, ймовірно, захочете використовувати об'єкти серіалізації та JSON на основі JAXB. У MessageBodyReader/Writerреалізації повинні подбати про необхідність втечі для вас , так що це один менше , що може піти не так. Якщо ваш клієнт базується на Java, але у нього немає хорошого процесора XML (наприклад, Android), я, ймовірно, використовую FORMкодування, оскільки тіло вмісту легше генерувати та кодувати належним чином, ніж URL-адреси. Сподіваємось, цей запис у міні-вікі проливає трохи світла на різні методи, які підтримує JAX-RS.

Примітка: в інтересах повного розкриття інформації я ще не використовував цю функцію Джерсі. Ми розмовляли з цим, оскільки у нас розгорнуто декілька програм JAXB + JAX-RS і переходять у мобільний клієнтський простір. JSON набагато краще підходить до XML для HTML5 або jQuery-рішень.


4
Я перевіряв цю функцію вчора, @XmlElement не потрібні анотації
mmatloka

Дякую за це Якщо я все-таки хочу надіслати 2 рядки, то для чого потрібно спокійне споживання? Або кілька парам працюють лише з @PathParm?
Klaasvaak

1
@Klaasvaak - вам потрібно вказати, звідки очікується витяг кожного параму. Як тепер у вас є речі, Джерсі / NetBeans бере на себе форму форми та витягує дані, що надсилаються як FormParm. Анотація кожного з ваших розробок методу, звідки ви хочете отримати дані (PathParam, FormParam, CookieParam тощо)
Сприйняття

1
@Klaasvaak - я додав купу прикладів, використовуючи різні анотації
D.Shawley

2
Дуже дякую за це! Це було справді те, що я шукав. Ви зробили мій день;) Я зараз використовую FormParams, і він працює!
Klaasvaak
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.