JavaRouting

opensas edited this page Apr 26, 2012 · 5 revisions
Clone this wiki locally

Rutas HTTP

El router (enrutador) HTTP de Play

El router es el componente encargado de traducir las solicitudes HTTP entrantes en una llamada a una acción (un método público y estático en una clase controladora).

Una solicitud HTTP es vista por el framework MVC como un evento. Este evento contiene dos partes importantes de información:

  • el path de la solicitud (tal como /clients/1542, /photos/list), incluyendo el querystring.
  • el método HTTP (GET, POST, …).

Las rutas se definen en el fichero conf/routes, que es compilado. Esto implica que podrá ver los errores de las rutas directamente en el navegador:

Sintaxis del archivo conf/routes

conf/routes es el fichero de configuración que utiliza el router. Este fichero lista todas las rutas que necesita la aplicación. Cada ruta consiste en un método HTTP y el patrón URI asociado con una llamada a un método de acción.

Veamos cómo son las definiciones de ruta:

GET   /clients/:id          controllers.Clients.show(id: Long)  

Observe que en la llamada a la acción, el tipo de parámetro viene tras el nombre del parámetro, como en Scala.

Cada ruta comienza con el método HTTP, seguido del patrón URI. El último elemento de una ruta es la definición de la llamada.

También se pueden añadir comentarios al fichero de rutas, con el carácter #:

# Muestra un cliente.
GET   /clients/:id          controllers.Clients.show(id: Long)  

El método HTTP

El método HTTP puede ser cualquiera de los métodos válidos soportados por HTTP (GET, POST, PUT, DELETE, HEAD).

El patrón URI

Define el path de solicitud de la ruta. Algunas partes del path pueden ser dinámicas.

Path estático

Por ejemplo, para coincidir exactamente con las solicitudes entrantes GET /clients/all puede definir esta ruta:

GET   /clients/all              controllers.Clients.list()

Partes dinámicas

Si quiere definir una ruta que, digamos, recupere un cliente por id, tiene que añadir una parte dinámica:

GET   /clients/:id          controllers.Clients.show(id: Long)  

Tenga en cuenta que el patrón URI puede tener más de una parte dinámica.

La estrategia por defecto para capturar una parte dinámica se define con la expresión regular [^/]+, que indica que cualquier parte dinámica definida como :id capturará exactamente un segmento del path.

Partes dinámicas que se extienden a varios /

Si quiere que una parte dinámica capture más de un segmento del path URI separados por barras /, puede definir la parte dinámica usando la sintaxis *id, que usa la expresión regular .*:

GET   /files/*name          controllers.Application.download(name)  

En este caso, para una solicitud como GET /files/images/logo.png, la parte dinámica name capturará el valor images/logo.png.

Partes dinámicas con expresiones regulares personalizadas

También puede definir su propia expresión regular para una parte dinámica, con la sintaxis $id<regex>:

GET   /clients/$id<[0-9]+>  controllers.Clients.show(id: Long)  

Llamada a un método de acción

La última parte de una definición de ruta es la llamada. Esta parte ha de definir una llamada válida a un método de acción.

Si el método no define ningún parámetro, basta poner el nombre completo del método:

GET   /                     controllers.Application.homePage()

Si el método de acción define parámetros, los valores correspondientes a los parámetros se buscarán en la URI de solicitud, ya sea extrayéndolos del path en sí mismo, o a partir de la cadena de consulta (query string).

# Extraer el parámetro page del path.
# p.ej. http://myserver.com/index
GET   /:page                controllers.Application.show(page)

O bien:

# Extraer el parámetro page de la query string
# p.ej. http://myserver.com/?page=index
GET   /                     controllers.Application.show(page)

Esta es la correspondiente definición del método show en el controlador controllers.Application:

public static Result show(String page) {
  String content = Page.getContentOf(page);
  response().setContentType("text/html");
  return ok(content);
}

Tipos de parámetros

Para los parámetros de tipo String el tipo de parámetro es opcional. Si quiere que Play lo transforme en un tipo específico de Scala, puedes añadir el tipo de manera explícita:

GET   /client/:id           controllers.Clients.show(id: Long)

Y luego usar el mismo tipo en el correspondiente método de acción en el controlador:

public static Result show(Long id) {
  Client client = Client.findById(id);
  return ok(views.html.Client.show(client));
}

Nota: Los tipos de parámetros se especifican utilizando una sintaxis de sufijos. Asimismo los tipos genéricos se especifican usando los símbolos [] en vez de <>, como en Java. Por ejemplo, List[String] es lo mismo que el tipo java List<String>.

Parámetros con valores fijos

A veces querrá utilizar un valor fijo para un parámetro:

# Extraer el parámetro page del path o poner valor por defecto si llega /
GET   /                     controllers.Application.show(page = "home")
GET   /:page                controllers.Application.show(page)

Parámetros con valores por defecto

También puede proporcionar un valor por defecto a ser utilizando en caso de no encontrar el valor en la solicitud entrante:

# Enlaces de paginación, como /clients?page=3
GET   /clients              controllers.Clients.list(page: Integer ?= 1)

Prioridad de las rutas

Muchas rutas pueden coincidir con el mismo pedido HTTP. Si hay conflicto, se usará la primera ruta (en el orden en que están declaradas).

Rutas invertidas

El router puede usarse para generar una URL a partir de una llamada Java. Con ello se hace posible centralizar todos los patrones URI en un solo fichero de configuración, lo que le da mayor tranquilidad a la hora de reestructurar su aplicación.

Por cada controlador que se usa en el fichero de rutas, el router genera un 'controlador invertido' en el paquete routes, que tiene los mismos métodos de acción, con la misma cantidad y tipos de parámetros, pero que devuelven un play.mvc.Call en vez de un play.mvc.Result.

El play.mvc.Call define una llamada HTTP, y proporciona tanto el método HTTP como la URI.

Por ejemplo, si crea un controlador como:

package controllers;

import play.*;
import play.mvc.*;

public class Application extends Controller {

  public static Result hello(String name) {
      return ok("Hello " + name + "!");
  }

}

Y lo asigna en el fichero conf/routes:

# Hello action
GET   /hello/:name          controllers.Application.hello(name)

Puede obtener la URL que invocaría al método de acción hello, usando el controlador invertido controllers.routes.Application:

// Redirigir a /hello/Bob
public static Result index() {
    return redirect(controllers.routes.Application.hello("Bob")); 
}

Siguiente: Manipulando la respuesta