Cómo acceder a los parámetros en un método RESTful POST

Mi método POST se ve así:

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

Cuando creo un Jersey Client en Netbeans, el método que llama al método de publicación se ve así:

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

Cuando se ejecuta esta prueba:

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

Da el siguiente resultado en el servidor:

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

¿Qué debo cambiar para que los parámetros den el valor correcto?

Su método @POST debería aceptar un objeto JSON en lugar de una cadena. Jersey usa JAXB para admitir el mapeo y la eliminación de objetos JSON (ver los documentos de jersey para más detalles ). Crea una clase como:

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

Entonces su método @POST se vería así:

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

Este método espera recibir el objeto JSON como el cuerpo del HTTP POST. JAX-RS pasa el cuerpo de contenido del mensaje HTTP como un parámetro no anotado – input en este caso. El mensaje real sería algo así como:

 POST /create HTTP/1.1 Content-Type: application/json Content-Length: 35 Host: www.example.com {"param1":"hello","param2":"world"} 

Usar JSON de esta manera es bastante común por razones obvias. Sin embargo, si lo está generando o consumiéndolo en algo que no sea JavaScript, entonces debe tener cuidado de evitar los datos correctamente. En JAX-RS, usaría un MessageBodyReader y MessageBodyWriter para implementar esto. Creo que Jersey ya tiene implementaciones para los tipos necesarios (p. Ej., Primitivas Java y clases envueltas en JAXB), así como para JSON. JAX-RS es compatible con varios otros métodos para pasar datos. Estos no requieren la creación de una nueva clase ya que los datos se pasan usando el paso simple de argumentos.


HTML

Los parámetros se anotarán usando @FormParam :

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

El navegador codificará el formulario usando “application / x-www-form-urlencoded” . El tiempo de ejecución JAX-RS se ocupará de decodificar el cuerpo y pasarlo al método. Esto es lo que debe ver en el cable:

 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 

El contenido está codificado en URL en este caso.

Si no conoce los nombres de FormParam, puede hacer lo siguiente:

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

Encabezados HTTP

Puede usar la anotación @HeaderParam si desea pasar parámetros a través de encabezados HTTP:

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

Así es como se vería el mensaje HTTP. Tenga en cuenta que este POST no tiene un cuerpo.

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

No usaría este método para pasar parámetros generalizados. Sin embargo, es realmente útil si necesita acceder al valor de un encabezado HTTP en particular.


Parámetros de consulta HTTP

Este método se usa principalmente con HTTP GET, pero es igualmente aplicable a los POST. Utiliza la anotación @QueryParam .

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

Al igual que la técnica anterior, pasar parámetros a través de la cadena de consulta no requiere un cuerpo de mensaje. Aquí está el mensaje HTTP:

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

Debe tener especial cuidado para codificar correctamente los parámetros de consulta en el lado del cliente. El uso de parámetros de consulta puede ser problemático debido a las restricciones de longitud de URL impuestas por algunos proxies, así como a los problemas asociados con la encoding de ellos.


Parámetros de ruta HTTP

Los parámetros de ruta son similares a los parámetros de consulta, excepto que están integrados en la ruta de recursos HTTP. Este método parece estar a favor hoy. Existen impactos con respecto al almacenamiento en caché HTTP, ya que la ruta es lo que realmente define el recurso HTTP. El código se ve un poco diferente que los demás ya que la anotación @Path se modifica y usa @PathParam :

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

El mensaje es similar a la versión del parámetro de consulta, excepto que los nombres de los parámetros no se incluyen en ningún lugar del mensaje.

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

Este método comparte los mismos problemas de encoding que la versión del parámetro de consulta. Los segmentos de ruta se codifican de manera diferente, por lo que también hay que tener cuidado.


Como puede ver, existen ventajas y desventajas para cada método. La elección generalmente la deciden tus clientes. Si está sirviendo páginas HTML basadas en FORM , entonces use @FormParam . Si sus clientes están basados ​​en JavaScript + HTML5, es probable que desee utilizar serialización basada en JAXB y objetos JSON. Las implementaciones de MessageBodyReader/Writer deben encargarse del escape necesario para usted, de modo que una cosa menos puede salir mal. Si su cliente está basado en Java pero no tiene un buen procesador XML (p. Ej., Android), probablemente usaría la encoding FORM porque el cuerpo de contenido es más fácil de generar y codificar correctamente que las URL. Esperemos que esta entrada de mini-wiki arroje algo de luz sobre los diversos métodos que admite JAX-RS.

Nota: con el interés de la divulgación completa, aún no he usado esta característica de Jersey. Estuvimos jugando con esto, ya que tenemos implementadas una serie de aplicaciones JAXB + JAX-RS que se están trasladando al espacio del cliente móvil. JSON encaja mucho mejor que XML en soluciones HTML5 o jQuery.