2010-12-07 32 views
116

Estamos planificando un proyecto que principalmente sirve contenido para aplicaciones móviles, pero que necesita tener un sitio web.RESTful on Play! framework

Mi pregunta es si tiene sentido usar Jersey o Restlet para desarrollar API REST para nuestras aplicaciones móviles, y luego usar Play! para servir el sitio web.

¿O tiene más sentido simplemente usar Play! para hacerlo todo? Si es así, ¡cómo hacer REST con Play! ¿marco de referencia?

+0

Le agradecería si puedes ayúdame aquí http://stackoverflow.com/questions/32699420/url-parameters-are-not-being-passed-by-curlpost –

Respuesta

25

Use Play! para hacerlo todo. Escribir servicios REST en Play es muy fácil.

En primer lugar, el archivo de rutas hace que sea sencillo escribir rutas que se ajusten al enfoque REST.

Luego, escriba sus acciones, en el controlador, para cada método API que desee crear.

Dependiendo de cómo desee devolver el resultado (XML, JSON, etc.), existen algunos métodos que puede utilizar. Por ejemplo, al usar el método renderJSON, permite que los resultados se procesen muy fácilmente. Si desea procesar XML, puede hacerlo de la misma forma que crearía un documento HTML en su Vista.

Aquí hay un buen ejemplo. presentar

rutas

GET  /user/{id}   Application.getUser(format:'xml') 
GET  /user/{id}/json  Application.getUserJSON 
POST /user/    Application.createUser 
PUT  /user/{id}   Application.updateUser 
DELETE /user/{id}   Application.deleteUser 

Archivo de aplicación

public static void createUser(User newUser) { 
    newUser.save(); 
    renderText("success"); 
} 

public static void updateUser(Long id, User user) { 
    User dbUser = User.findById(id); 
    dbUser.updateDetails(user); // some model logic you would write to do a safe merge 
    dbUser.save(); 
    renderText("success"); 
} 

public static void deleteUser(Long id) { 
    // first check authority 
    User.findById(id).delete(); 
    renderText("success"); 
} 

public static void getUser(Long id) { 
    User user = User.findById(id) 
    renderJSON(user); 
} 

public static void getUserJSON(Long id) { 
    User user = User.findById(id) 
    renderJSON(user); 
} 

archivo getUser.xml

<user> 
    <name>${user.name}</name> 
    <dob>${user.dob}</dob> 
    .... etc etc 
</user> 
+0

¿Es posible elegir el método getUser correcto basado en el encabezado Accept? –

+0

es, pero no del todo confiable. Si Play sabe que el encabezado es una solicitud JSON, intentará procesar un archivo getuser.json. Si el encabezado es un xml, intentará con getuser.xml. Sin embargo, es mucho más fácil de entender, y más como REST, para el usuario/usuario/{id}/tipo – Codemwnci

+28

No creo que sea más parecido a un REST especificar el tipo de representación explícitamente en el URI. Es mejor usar el encabezado Aceptar directamente y no cambiar el URI ya que el recurso que desea ver permanece igual. El ejemplo anterior podría reescribirse para tener solo un método getUser (Id. Largo) que hace exactamente lo mismo que su implementación actual, pero en lugar de definir un getUserJSON, getUserXML, etc., más bien define una plantilla getUser.json y getUser.xml . Aunque cambiaría el nombre a user.json/user.xml también – seb

5

La integración con una aplicación JAX-RS es una posible aproximación alternativa al uso de Juego incorporado en enrutamiento HTTP. Para un ejemplo RESTEasy, vea el RESTEasy Play! module.

Este enfoque tiene sentido si ya ha invertido en JAX-RS, o si necesita algunas de las características avanzadas de REST que JAX-RS ofrece, como la negociación de contenido. De lo contrario, sería más sencillo usar Play directamente para servir JSON o XML en respuesta a solicitudes HTTP.

112

Según la solicitud, un enfoque simple similar al REST. Funciona casi de la misma manera que la solución de Codemwncis, pero utiliza el encabezado Aceptar para la negociación de contenido. Primero el archivo de rutas:

GET  /user/{id}   Application.user 
POST /user/    Application.createUser 
PUT  /user/{id}   Application.updateUser 
DELETE /user/{id}   Application.deleteUser 

No especifica ningún tipo de contenido aquí. Hacerlo es en mi humilde opinión solo necesario cuando quieres tener URIs "especiales" para ciertos recursos. Como declarar una ruta a /users/feed/ para regresar siempre en Atom/RSS.

controlador

La aplicación se ve así:

public static void createUser(User newUser) { 
    newUser.save(); 
    user(newUser.id); 
} 

public static void updateUser(Long id, User user) { 
    User dbUser = User.findById(id); 
    dbUser.updateDetails(user); // some model logic you would write to do a safe merge 
    dbUser.save(); 
    user(id); 
} 

public static void deleteUser(Long id) { 
    User.findById(id).delete(); 
    renderText("success"); 
} 

public static void user(Long id) { 
    User user = User.findById(id) 
    render(user); 
} 

Como se puede ver que sólo se retira el método getUserJSON y renombrado el método getUser. Para que funcionen diferentes tipos de contenido, ahora debe crear varias plantillas. Uno para cada tipo de contenido deseado. Por ejemplo:

usuario.xml:

<users> 
    <user> 
    <name>${user.name}</name> 
    . . . 
    </user> 
</users> 

user.json:

{ 
    "name": "${user.name}", 
    "id": "${user.id}", 
    . . . 
} 

user.html:

<html>...</html> 

Este enfoque da navegadores siempre la vista HTML, ya que todos los navegadores envían a/html tipo de contenido de texto en su encabezado Aceptar. Todos los demás clientes (posiblemente algunas solicitudes AJAX basadas en JavaScript) pueden definir su propio tipo de contenido deseado. método que utiliza jQuerys ajax() que podría hacer lo siguiente:

$.ajax({ 
    url: @{Application.user(1)}, 
    dataType: json, 
    success: function(data) { 
    . . . 
    } 
}); 

Cuál debe conseguir que los detalles acerca del usuario con el ID 1 en el formato JSON. Play actualmente admite HTML, JSON y XML de forma nativa, pero puede usar fácilmente un tipo diferente ya sea siguiendo el official documentation o usando el content negotiation module.

Si está utilizando Eclipse para el desarrollo, le sugiero que utilice el REST client plugin que le permite probar sus rutas y su tipo de contenido correspondiente.

+2

Gracias por publicar esto. ¡El juego! Los documentos son algunos de los mejores que he visto para explicar la estructura básica de las cosas, pero a veces faltan ejemplos detallados. Tener los dos enfoques demostrados en el mismo ejemplo realmente aclara las cosas. –

+0

Estoy probando su ejemplo. Tengo curiosidad por saber dónde se han convertido los datos JSON publicados en clase de usuario. por ejemplo, dentro de la función createUser, encuentro que newUser es nulo. – Gary

+2

@Gary: ¿Tal vez usaste "usuario" en lugar de "usuario nuevo"? El nombre del controlador y el parámetro del formulario deben coincidir. He creado un proyecto simple que muestra el método anterior, incluida la salida HTML/XML/JSON para todos los usuarios en https://github.com/sebhoss/play-user-sample – seb

67

Todavía es una pregunta popular, pero las respuestas más votadas no están actualizadas con la versión actual. He aquí un ejemplo RESTO trabajar con el juego 2.2.1:

conf/rutas:

GET  /users     controllers.UserController.getUsers 
GET  /users/:id    controllers.UserController.getUser(id: Long) 
POST /users     controllers.UserController.createUser 
PUT  /users/:id    controllers.UserController.updateUser(id: Long) 
DELETE /users/:id    controllers.UserController.deleteUser(id: Long) 

app/controllers/UserController.java:

public static Result getUsers() 
{ 
    List<User> users = Database.getUsers(); 
    return ok(Json.toJson(users)); 
} 

public static Result getUser(Long id) 
{ 
    User user = Database.getUser(id); 
    return user == null ? notFound() : ok(Json.toJson(user)); 
} 

public static Result createUser() 
{ 
    User newUser = Json.fromJson(request().body().asJson(), User.class); 
    User inserted = Database.addUser(newUser); 
    return created(Json.toJson(inserted)); 
} 

public static Result updateUser(Long id) 
{ 
    User user = Json.fromJson(request().body().asJson(), User.class); 
    User updated = Database.updateUser(id, user); 
    return ok(Json.toJson(updated)); 
} 

public static Result deleteUser(Long id) 
{ 
    Database.deleteUser(id); 
    return noContent(); // http://stackoverflow.com/a/2342589/1415732 
} 
+0

? También me gustaría ver una versión actualizada de la respuesta del seb, pero desafortunadamente tu respuesta eliminó todos los .xml y .html magic . :-( – flaschenpost