Поиск по этому блогу

понедельник, 21 января 2013 г.

REST. Разница между @QueryParam и @PathParam


При использовании JAX-RS при написании REST методов для обработки пользовательских запросов встает вопрос, как лучше передавать параметры запроса на сервер. Для этого существуют различные способы, о двух из которых тут пойдет речь. Параметры можно передавать используя @PathParam или @QueryParam. В чем разница при передаче параметров с  использованием @PathParam и @QueryParam я хочу рассказать в этой статье. 

Краткое описание


Необходимо получить список заказчиков, посылая на сервер один или несколько параметров. Эти параметры можно посылать как часть URL (тогда используется @PathParam) или как часть самого запроса ( тогда параметр посылается при помощи @QueryParam). Если мы посылаем параметр как часть URL то просто добавляем его к адресу через знак /. Например, 

rest/customers/getCustomers/ABCD123 - где  ABCD123  - посылаемый параметр (строковый id).

Если посыламем параметр как часть запроса, то используем специальный синтаксис. 
Перед тем как перечислять параметры ставим значк вопроса ? потом ставим имя параметра потом знак равно = потом значение параметра. Если параметров больше одного то между ними ставится знак &. Например, для того чтобы отправить два параметра placeId и placeId нужно написать так:

/rest/customers/getCustomers?placeId=PAD1234C&placeId=90321

Ресурс, который будет обрабатывать запросы 


package ru.ipoint.rest.server.resource;
 
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
 
@Path("/customers")
public class MyRestService {
 
 private MyRestManager manager = MyRestManager.getInstance();
 
 // Если мы используем @PathParam
 // то необходимо добавлять параметр в URL
 @Path("/getCustomers/{placeId}")
 @GET
 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
 public Response getCustomersByPathParam(@PathParam("placeId") String placeId) {
  return Response.ok(manager.getCustomers(placeId)).build();
 }
 
 // @PathParam с двумя параметрами
 @Path("/getCustomers/{placeId}/{orderId}")
 @GET
 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
 public Response getCustomersByPathParams(
   @PathParam("placeId") String placeId,
   @PathParam("orderId") Long orderId) {
  return Response.ok(manager.getCustomers(placeId, orderId)).build();
 }
 
 // Если мы используем @QueryParam
 // то в URL ничего добавлять не надо
 @Path("/getCustomers")
 @GET
 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
 public Response getCustomersByQueryParam(
   @QueryParam("placeId") String placeId) {
  return Response.ok(manager.getCustomers(placeId)).build();
 }
 
 // @QueryParam с двумя параметрами
 @Path("/getCustomersWithOrder")
 @GET
 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
 public Response getPlacesByQueryParam(
   @QueryParam("placeId") String placeId,
   @QueryParam("orderId") Long orderId) {
  return Response.ok(manager.getCustomers(placeId, orderId)).build();
 }
}


Класс, из которого мы будем формировать и отправлять запросы на сервер


package ru.ipoint.rest.client;
 
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestException;
 
public class RestTest {
 public static void main(String[] args) {
 
  String placeId = "PAD1234C";
  int orderId = 90321;
 
  // запрос с использованием @PathParam, где 1 параметр
  RequestBuilder requestBuilder1 = new RequestBuilder(RequestBuilder.GET,
    "/rest/customers/getCustomers/" + placeId);
  try {
   requestBuilder1.send();
  } catch (RequestException e) {
   e.printStackTrace();
  }
 
  // запрос с использованием @PathParam, где 2 параметра
  RequestBuilder requestBuilder2 = new RequestBuilder(RequestBuilder.GET,
    "/rest/customers/getCustomers/" + placeId + "/" + orderId);
  try {
   requestBuilder2.send();
  } catch (RequestException e) {
   e.printStackTrace();
  }
 
  // запрос с использованием @QueryParam, где 1 параметр
  RequestBuilder requestBuilder3 = new RequestBuilder(RequestBuilder.GET,
    "/rest/customers/getCustomers?placeId=" + placeId);
  try {
   requestBuilder3.send();
  } catch (RequestException e) {
   e.printStackTrace();
  }
 
  // запрос с использованием @QueryParam, и где 2 параметра
  RequestBuilder requestBuilder4 = new RequestBuilder(RequestBuilder.GET,
    "/rest/customers/getCustomers?placeId=" + placeId 
    + "&orderId=" + orderId);
  try {
   requestBuilder4.send();
  } catch (RequestException e) {
   e.printStackTrace();
  }
 }
}


Так будут выглядеть сформированные адреса запросов


1. Запрос с использованием @PathParam, где 1 параметр

/rest/customers/getCustomers/PAD1234C

2. Запрос с использованием @PathParam, где 2 параметра

/rest/customers/getCustomers/PAD1234C/90321

3. Запрос с использованием @QueryParam, где 1 параметр 

/rest/customers/getCustomers?placeId=PAD1234C

4. Запрос с использованием @QueryParam, и где 2 параметра 

/rest/customers/getCustomers?placeId=PAD1234C&orderId=90321

Выводы


Рекомендуется все необходимые параметры добавлять в path (то есть в @PathParam). А параметры, которые являются опциональными, почти всегда являются строковыми параметрами. Добавление опциональных параметров в URL может привести к очень запутанным оюработчикам URL, которые должны будут обрабатывать различные комбинации их этих параметров.

То есть, например, id у хранящейся в базе записи будет всегда, поэтому поле id можно передавать как @PathParam, а например, поля цена, имя, кр. описание или любое другое необязательное к заполнению пользователем поле, которое может быть равно null нужно передавать как @QueryParam. Так как если в URL будет null, то естественно ничего работать не будет, а если в параметрах, то null значения можно обработать на сервере.

Полезные ссылки


Дополнительно о @PathParam и @QueryParam можно почитать тут:
  1. http://stackoverflow.com/questions/11552248/when-to-use-queryparam-vs-pathparam
  2. http://www.mkyong.com/webservices/jax-rs/jax-rs-queryparam-example/
  3. http://www.mkyong.com/webservices/jax-rs/jax-rs-pathparam-example/ 
  4. http://habrahabr.ru/post/140181/

1 комментарий: