6.4 URL Mappings - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith
Version: null
Table of Contents
6.4 URL Mappings
Throughout the documentation so far the convention used for URLs has been the default of
Hasta ahora a travez de la documentacion la convencion usada para las URLs ha sido for defecto /controller/action/id. However, this convention is not hard wired into Grails and is in fact controlled by a URL Mappings class located at grails-app/conf/UrlMappings.groovy.
/controller/action/id. Sin embargo, esta convencion no esta fuertemente ligada dentro de Grails y de hecho es controlada por la clase URL Mappings localizada en grails-app/conf/UrlMappings.groovy.
The
La clase UrlMappings class contains a single property called mappings that has been assigned a block of code:
UrlMappings contiene una unica propiedad llamada mappings que ha sido asignada a un bloque de codigo:class UrlMappings {
static mappings = {
}
}6.4.1 Mapping to Controllers and Actions
To create a simple mapping simply use a relative URL as the method name and specify named parameters for the controller and action to map to:
Para crear un mapeo simple, simplemente use una URL relativa como el nombre del metodo y especifique los parametros nombrados para el controlador y la accion a mapear:"/product"(controller: "product", action: "list")
In this case we've mapped the URL
En este caso hemos mapeado la URL /product to the list action of the ProductController. Omit the action definition to map to the default action of the controller:
/product hacia la accion list del ProductController. Omitiendo la definicion de la accion a mapear hacia la accion por defecto del controllador:"/product"(controller: "product")
An alternative syntax is to assign the controller and action to use within a block passed to the method:
Una sintaxis alternativa es asignar el controlador y la accion a usar dentro del bloque pasado al metodo:"/product" { controller = "product" action = "list" }
Which syntax you use is largely dependent on personal preference. To rewrite one URI onto another explicit URI (rather than a controller/action pair) do something like this:
Cual sintaxis usar es enormemente dependiente en su preferencia personal. Para reescribir una URI en otra URI explicita (en vez del par controlador/accion) haga algo asi:"/hello"(uri: "/hello.dispatch")
Rewriting specific URIs is often useful when integrating with other frameworks
Reescribir URIs especificas es comunmente util cuando se integran con otros frameworks.
6.4.2 Embedded Variables
Simple Variables
The previous section demonstrated how to map simple URLs with concrete "tokens". In URL mapping speak tokens are the sequence of characters between each slash, '/'. A concrete token is one which is well defined such as as/product. However, in many circumstances you don't know what the value of a particular token will be until runtime. In this case you can use variable placeholders within the URL for example:static mappings = { "/product/$id"(controller: "product") }
id. For example given the URL /product/MacBook, the following code will render "MacBook" to the response:class ProductController {
def index() { render params.id }
}static mappings = { "/$blog/$year/$month/$day/$id"(controller: "blog", action: "show") }
/graemerocher/2007/01/10/my_funky_blog_entry
year, month, day, id and so on.Dynamic Controller and Action Names
Variables can also be used to dynamically construct the controller and action name. In fact the default Grails URL mappings use this technique:static mappings = { "/$controller/$action?/$id?"() }
controller, action and id embedded within the URL.You can also resolve the controller name and action name to execute dynamically using a closure:static mappings = { "/$controller" { action = { params.goHere } } }
Optional Variables
Another characteristic of the default mapping is the ability to append a ? at the end of a variable to make it an optional token. In a further example this technique could be applied to the blog URL mapping to have more flexible linking:static mappings = { "/$blog/$year?/$month?/$day?/$id?"(controller:"blog", action:"show") }
/graemerocher/2007/01/10/my_funky_blog_entry
/graemerocher/2007/01/10
/graemerocher/2007/01
/graemerocher/2007
/graemerocherArbitrary Variables
You can also pass arbitrary parameters from the URL mapping into the controller by just setting them in the block passed to the mapping:"/holiday/win" { id = "Marrakech" year = 2007 }
Dynamically Resolved Variables
The hard coded arbitrary variables are useful, but sometimes you need to calculate the name of the variable based on runtime factors. This is also possible by assigning a block to the variable name:"/holiday/win" { id = { params.id } isEligible = { session.user != null } // must be logged in }
6.4.3 Mapping to Views
You can resolve a URL to a view without a controller or action involved. For example to map the root URL
Puede resolver una URL hacia una vista sin un controlador o una accion involucrada. Por ejemplo para mapear la URL raiz / to a GSP at the location grails-app/views/index.gsp you could use:
/ hacia un GSP en la ruta grails-app/views/index.gsp podria usar:static mappings = { "/"(view: "/index") // map the root URL }
Alternatively if you need a view that is specific to a given controller you could use:
Alternativamente si necesita una vista que sea especifica a un controlador dado podria usar:static mappings = { "/help"(controller: "site", view: "help") // to a view for a controller }
6.4.4 Mapping to Response Codes
Grails also lets you map HTTP response codes to controllers, actions or views. Just use a method name that matches the response code you are interested in:
Grails tambien le permite mapear codigos de respuesta HTTP hacia los controllers, actions o vistas. Solo use un nombre de metodo que empate el codigo de respuesta en el cual esta interesado:static mappings = { "403"(controller: "errors", action: "forbidden") "404"(controller: "errors", action: "notFound") "500"(controller: "errors", action: "serverError") }
Or you can specify custom error pages:
O puede especificar paginas de error personalizadas:static mappings = { "403"(view: "/errors/forbidden") "404"(view: "/errors/notFound") "500"(view: "/errors/serverError") }
Declarative Error Handling
Manejo Declarativo de Errores
In addition you can configure handlers for individual exceptions:
Ademas puede configurar los manejadores para excepciones individuales:static mappings = { "403"(view: "/errors/forbidden") "404"(view: "/errors/notFound") "500"(controller: "errors", action: "illegalArgument", exception: IllegalArgumentException) "500"(controller: "errors", action: "nullPointer", exception: NullPointerException) "500"(controller: "errors", action: "customException", exception: MyException) "500"(view: "/errors/serverError") }
With this configuration, an
Con esta configuracion, una IllegalArgumentException will be handled by the illegalArgument action in ErrorsController, a NullPointerException will be handled by the nullPointer action, and a MyException will be handled by the customException action. Other exceptions will be handled by the catch-all rule and use the /errors/serverError view.
IllegalArgumentException sera manejada por la accion illegalArgument en ErrorsController, una NullPointerException sera manejada por la accion nullPointer, y MyException sera manejada por la accion customException. Otras excepciones seran manejadas por la regla catch-all y usa la vista /errors/serverError.
You can access the exception from your custom error handing view or controller action using the request's
Puede acceder a la excepcion desde su vista de error personalizada o la accion del controlador usando el atributo exception attribute like so:
exception de la peticion de esta manera:class ErrorController {
def handleError() {
def exception = request.exception
// perform desired processing to handle the exception
}
}If your error-handling controller action throws an exception as well, you'll end up with aSi su accion del manejador de errores del controller arroja una excepcion tambien, terminara con unaStackOverflowException.StackOverflowException.
6.4.5 Mapping to HTTP methods
URL mappings can also be configured to map based on the HTTP method (GET, POST, PUT or DELETE). This is very useful for RESTful APIs and for restricting mappings based on HTTP method.
Los mapeos de URL tambien puede ser configurados para mapear basado en el metodo deh HTTP (GET, POST, PUT or DELETE). Esto es muy util para APIs de RESTful y para restringir mapeos basados en el metodo de HTTP.
As an example the following mappings provide a RESTful API URL mappings for the
Como ejemplo los siguientes mapeos proveen una RESTful API para mapeos de URL para el ProductController:
ProductController:static mappings = { "/product/$id"(controller:"product") { action = [GET:"show", PUT:"update", DELETE:"delete", POST:"save"] } }
6.4.6 Mapping Wildcards
Grails' URL mappings mechanism also supports wildcard mappings. For example consider the following mapping:
El mecanismo de mapeo de URL de Grails tambien soporta el mapeo de wildcards. Por ejemplo considere el siguiente mapeo:static mappings = { "/images/*.jpg"(controller: "image") }
This mapping will match all paths to images such as
Este mapeo empatara todas las rutas de imagenes tales como /image/logo.jpg. Of course you can achieve the same effect with a variable:
/image/logo.jpg. Por supuesto puede obtener el mismo efecto con la variable:static mappings = { "/images/$name.jpg"(controller: "image") }
However, you can also use double wildcards to match more than one level below:
Sin embargo, puede tambien usar dobles wildcards para empatar mas de un solo nivel abajo:static mappings = { "/images/**.jpg"(controller: "image") }
In this cases the mapping will match
En este caso el mapeo empatara /image/logo.jpg as well as /image/other/logo.jpg. Even better you can use a double wildcard variable:
/image/logo.jpg asi como /image/other/logo.jpg. Aun mejor puede usar la variable de doble wildcard:static mappings = { // will match /image/logo.jpg and /image/other/logo.jpg "/images/$name**.jpg"(controller: "image") }
In this case it will store the path matched by the wildcard inside a
En este caso sera almacenada la ruta que empate con el wildcard dentro del parametro name parameter obtainable from the params object:
name obtenible desde el objeto params:def name = params.name println name // prints "logo" or "other/logo"
If you use wildcard URL mappings then you may want to exclude certain URIs from Grails' URL mapping process. To do this you can provide an
Si usa el wildcard del mapeo de URL entonces querra excluir ciertas URIs del proceso de mapeo de URL de Grails. Para hacer esto puede proveer una setting excludes setting inside the UrlMappings.groovy class:
excludes dentro de la clase UrlMappings.groovy:class UrlMappings {
static excludes = ["/images/*", "/css/*"]
static mappings = {
…
}
}
In this case Grails won't attempt to match any URIs that start with
En este caso Grails no intentara de empatar ninguna URI que comience con /images or /css.
/images o /css.
6.4.7 Automatic Link Re-Writing
Another great feature of URL mappings is that they automatically customize the behaviour of the link tag so that changing the mappings don't require you to go and change all of your links.
Otra gran mejora del mapeo de URL es que se puede personalizar automaticamente el comportamiento de la etiqueta link asi que cambiar los mapeos no requiere de ir y cambiar todos sus enlaces.
This is done through a URL re-writing technique that reverse engineers the links from the URL mappings. So given a mapping such as the blog one from an earlier section:
Esto es hecho a travez de la tecnica de reescritura de la URL que hace ingenieria inversa a los links de los mapeos de URL. Asi que dado un mapeo tal como el blog de la seccion anterior:static mappings = { "/$blog/$year?/$month?/$day?/$id?"(controller:"blog", action:"show") }
If you use the link tag as follows:
Si usted usa la etiqueta de enlance como sigue:<g:link controller="blog" action="show" params="[blog:'fred', year:2007]"> My Blog </g:link><g:link controller="blog" action="show" params="[blog:'fred', year:2007, month:10]"> My Blog - October 2007 Posts </g:link>
Grails will automatically re-write the URL in the correct format:
Grails automaticamente reescribira la URL en el formato correcto:<a href="/fred/2007">My Blog</a> <a href="/fred/2007/10">My Blog - October 2007 Posts</a>
6.4.8 Applying Constraints
URL Mappings also support Grails' unified validation constraints mechanism, which lets you further "constrain" how a URL is matched. For example, if we revisit the blog sample code from earlier, the mapping currently looks like this:
Los mapeos de URL tambien soportan el mecanismo unificado de Grails validation constraints, el cual permite ademas "restringir" como una URL es empatada. Por ejemplo: si volvemos al codigo de ejemplo del blog, el mapeo actualmente se ve asi:static mappings = { "/$blog/$year?/$month?/$day?/$id?"(controller:"blog", action:"show") }
This allows URLs such as:
Esto permite URLs tales como:/graemerocher/2007/01/10/my_funky_blog_entry
However, it would also allow:
Sin embargo, esto permitiria tambien:/graemerocher/not_a_year/not_a_month/not_a_day/my_funky_blog_entry
This is problematic as it forces you to do some clever parsing in the controller code. Luckily, URL Mappings can be constrained to further validate the URL tokens:
Esto es problematico por que lo obliga a hacer algun parseo inteligente en el codigo del controlador. Afortunadamente, los mapeos de URL pueden ser restringidos para ademas validar los tokens de la URL:"/$blog/$year?/$month?/$day?/$id?" { controller = "blog" action = "show" constraints { year(matches:/\d{4}/) month(matches:/\d{2}/) day(matches:/\d{2}/) } }
In this case the constraints ensure that the
En este caso las restricciones se aseguran de que los parametros year, month and day parameters match a particular valid pattern thus relieving you of that burden later on.
year, month y day empaten con un patron particular valido asi relevandolo a usted de esa carga despues.
6.4.9 Named URL Mappings
URL Mappings also support named mappings, that is are mappings which have a name associated with them. The name may be used to refer to a specific mapping when links are generated.The syntax for defining a named mapping is as follows:static mappings = {
name <mapping name>: <url pattern> {
// …
}
}static mappings = { name personList: "/showPeople" { controller = 'person' action = 'list' } name accountDetails: "/details/$acctNumber" { controller = 'product' action = 'accountDetails' } }
<g:link mapping="personList">List People</g:link>
<a href="/showPeople">List People</a>
<g:link mapping="accountDetails" params="[acctNumber:'8675309']"> Show Account </g:link>
<a href="/details/8675309">Show Account</a>
<link:personList>List People</link:personList>
<a href="/showPeople">List People</a>
<link:accountDetails acctNumber="8675309">Show Account</link:accountDetails>
<a href="/details/8675309">Show Account</a>
href, specify a Map value to the attrs attribute. These attributes will be applied directly to the href, not passed through to be used as request parameters.<link:accountDetails attrs="[class: 'fancy']" acctNumber="8675309"> Show Account </link:accountDetails>
<a href="/details/8675309" class="fancy">Show Account</a>

