Как получить доступ к параметрам в методе RESTful POST
Мой метод POST выглядит так:
@POST
@Consumes({"application/json"})
@Path("create/")
public void create(String param1, String param2){
System.out.println("param1 = " + param1);
System.out.println("param2 = " + param2);
}
Когда я создаю клиент Jersey в Netbeans, метод, который вызывает метод post, выглядит следующим образом:
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 =
Что мне нужно изменить, чтобы параметры давали правильное значение?
1 ответ
Ваш @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¶m2=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 /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¶m2=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, вы, вероятно, захотите использовать сериализацию на основе JAXB и объекты JSON. MessageBodyReader/Writer
реализации должны позаботиться о необходимом экранировании для вас, так что это еще одна вещь, которая может пойти не так. Если ваш клиент основан на Java, но не имеет хорошего процессора XML (например, Android), то я бы, вероятно, использовал FORM
кодирование, поскольку тело контента легче генерировать и кодировать правильно, чем URL-адреса. Надеемся, что эта статья в мини-вики проливает свет на различные методы, которые поддерживает JAX-RS.
Примечание: в целях полного раскрытия информации я пока еще не использовал эту функцию на Джерси. Мы возились с этим, поскольку у нас развернуто несколько приложений JAXB+JAX-RS, и мы перемещаемся в пространство мобильного клиента. JSON гораздо лучше подходит для XML на решениях на основе HTML5 или jQuery.