--- title: Controllers REST --- #O que são Controllers? Controller são o que poderíamos pensar como recursos a serem disponibilizados para acesso pelos nossos clientes. No caso de uma aplicação Web baseada no VRaptor, um recurso deve ser anotado com a anotação `@Controller`. Assim que o programador insere tal anotação em seu código, todos os métodos públicos desse recurso se tornam acessíveis através de chamadas do tipo GET ou POST a URIs específicas. O exemplo a seguir mostra um recurso chamado `ClienteController` que possui métodos para diversas funcionalidades ligadas a um cliente. Simplesmente criar essa classe e os métodos faz com que as URLs `/cliente/adiciona`, `/cliente/lista`, `/cliente/visualiza`, `/cliente/remove` e `/cliente/atualiza` sejam disponibilizadas, cada uma invocando o respectivo método em sua classe. ~~~ #!java @Controller public class ClienteController { public void adiciona(Cliente cliente) { } public List lista() { return ... } public Cliente visualiza(Cliente perfil) { return ... } public void remove(Cliente cliente) { ... } public void atualiza(Cliente cliente) { ... } } ~~~ ##Parâmetros dos métodos Você pode receber parâmetros nos métodos dos seus controllers, e se o objeto usar a convenção de java beans (getters e setters para os atributos da classe), você pode usar pontos para navegar entre os atributos. Por exemplo, no método: ~~~ #!java public void atualiza(Cliente cliente) { //... } ~~~ você pode passar como parâmetro na requisição: ~~~ #!jsp cliente.id=3 cliente.nome=Fulano cliente.usuario.login=fulano ~~~ e os campos correspondentes, navegando por getters e setters a partir do cliente, serão setados. Se um atributo do objeto ou parâmetro do método for uma lista (List<>, array ou Set<>), você pode passar vários parâmetros usando colchetes e índices: ~~~ #!jsp cliente.telefones[0]=(11) 5571-2751 #no caso de ser uma lista de String cliente.dependentes[0].id=1 #no caso de ser qualquer objeto, você pode continuar a navegação cliente.dependentes[3].id=1 #os índices não precisam ser sequenciais cliente.dependentes[0].nome=Cicrano #se usar o mesmo índice, vai ser setado no mesmo objeto clientes[1].id=23 #funciona se você receber uma lista de clientes no método ~~~ ##Reflection no nome dos parâmetros O VRaptor tira proveito do framework [Paranamer](http://paranamer.codehaus.org), que consegue extrair essa informação por meio dos dados de debug. Alguns dos desenvolvedores do VRaptor também participam no desenvolvimento do Paranamer. ##Escopos Por vezes você deseja compartilhar um componente entre todos os usuários, entre todas as requisições de um mesmo usuário ou a cada requisição de um usuário. Para definir em que escopo o seu componente vive, basta utilizar as anotações `@ApplicationScoped`, `@SessionScoped`, `@RequestScoped`, `@Dependent` e `@Conversation`. Caso nenhuma anotação seja utilizada, o VRaptor assume que seu componente ficará no escopo de request, isto é, você terá um novo componente a cada nova requisição. ##@Path A anotação `@Path` permite que você customize as URIs de acesso a seus métodos. O uso básico dessa anotação é feito por meio de uma URI fixa. O exemplo a seguir mostra a customização de uma URI para um método, que somente receberá requisições do tipo POST na URI `/cliente`: ~~~ #!java @Controller public class ClienteController { @Path("/cliente") @Post public void adiciona(Cliente cliente) { } } ~~~ Se você anotar o `ClienteController` com `@Path`, o valor especificado vai ser usado como prefixo para todas as URIs desse controller: ~~~ #!java @Controller @Path("/clientes") public class ClienteController { //URI: /clientes/lista public void lista() {...} //URI: /clientes/salva @Path("salva") public void adiciona() {...} //URI: /clientes/todosOsClientes @Path("/todosOsClientes") public void listaTudo() {...} } ~~~ ##Http Methods O ideal é definir uma URI específica para diversos métodos HTTP diferentes, como GET, POST, PUT etc. Para atingir esse objetivo, utilizamos as anotações `@Get`, `@Post`, `@Delete`, etc que também permitem configurar uma URI diferente da URI padrão, da mesma forma que a anotação `@Path`. O exemplo a seguir altera os padrões de URI do `ClienteController` para utilizar duas URIs distintas, com diversos métodos HTTP: ~~~ #!java @Controller public class ClienteController { @Post("/cliente") public void adiciona(Cliente cliente) { } @Path("/") public List lista() { return ... } @Get("/cliente") public Cliente visualiza(Cliente cliente) { return ... } @Delete("/cliente") public void remove(Cliente cliente) { ... } @Put("/cliente") public void atualiza(Cliente cliente) { ... } } ~~~ Como você pode notar, utilizamos os métodos HTTP + uma URI específica para identificar cada um dos métodos da nossa classe Java. No momento de criar os links e formulários HTML devemos tomar um cuidado muito importante pois os browsers só dão suporte aos métodos POST e GET por meio de formulários hoje em dia. Por isso, você deverá criar as requisições para métodos do tipo DELETE, PUT etc usando JavaScript ou passando um parâmetro extra, chamado `_method`. O último só funciona em requisições POST. Esse parâmetro sobrescreverá o método HTTP real sendo invocado. O exemplo a seguir mostra um link para o método visualiza de cliente: ~~~ #!jsp ver cliente 5 ~~~ Agora um exemplo de como invocar o método de adicionar um cliente: ~~~ #!jsp
~~~ E, note que para permitir a remoção pelo método DELETE, temos que usar o parâmetro _method, uma vez que o browser ainda não suporta tais requisições: ~~~ #!jsp
~~~ ##Paths com expressões regulares Você pode restringir o valor dos parâmetros da sua URI com expressões regulares, dessa maneira: ~~~ #!java @Path("/cor/{cor:[0-9A-Fa-f]{6}}") public void setCor(String cor) { //... } ~~~ Tudo que estiver depois do `:` será tratado como uma regex, e a URI só vai casar se o parâmetro casar com a regex: ~~~ #!jsp /cor/a0b3c4 => casa /cor/AABBCC => casa /cor/branco => não casa ~~~ ##Path com injeção de variáveis Em diversos casos, desejamos que a URI que identifica nosso recurso tenha como parte de seu valor, por exemplo, o identificador único do nosso recurso. Suponha o exemplo de um controle de clientes onde meu identificador único (chave primária) é um número, podemos então mapear as URIs `/cliente/{cliente.id}` para a visualização de cada cliente. Isto é, se acessarmos a URI `/cliente/2`, o método `visualiza` será invocado e o parâmetro `cliente.id` será setado para `2`. Caso a URI `/cliente/1717` seja acessada, o mesmo método será invocado com o valor `1717`. Dessa maneira, criamos URIs únicas para identificar recursos diferentes do nosso sistema. Veja o exemplo: ~~~ #!java @Controller public class ClienteController { @Get @Path("/cliente/{cliente.id}") public Cliente visualiza(Cliente cliente) { return ... } } ~~~ Você pode ir além e setar diversos parâmetros pela URI: ~~~ #!java @Controller public class ClienteController { @Get @Path("/cliente/{cliente.id}/visualiza/{secao}") public Cliente visualiza(Cliente cliente, String secao) { return ... } } ~~~ ##Vários paths para a mesma lógica Você pode setar mais de um path para a mesma lógica fazendo: ~~~ #!java @Controller public class ClienteController { @Path({"/cliente/{cliente.id}/visualiza/{secao}", "/cliente/{cliente.id}/visualiza/"}) public Cliente visualiza(Cliente cliente, String secao) { return ... } } ~~~ ##Paths com * Você também pode utilizar o `*` como método de seleção para a sua URI. O exemplo a seguir ignora qualquer coisa após a palavra `foto/` : ~~~ #!java @Controller public class ClienteController { @Get @Path("/cliente/{cliente.id}/foto/*") public File foto(Cliente cliente) { return ... } } ~~~ E agora o mesmo código, mas utilizado para baixar uma foto específica de um cliente: ~~~ #!java @Controller public class ClienteController { @Get @Path("/cliente/{cliente.id}/foto/{foto.id}") public File foto(Cliente cliente, Foto foto) { return ... } } ~~~ Por vezes você deseja que o parâmetro a ser setado inclua também `/s`. Para isso você deve utilizar o padrão `{...*}`: ~~~ #!java @Controller public class ClienteController { @Get @Path("/cliente/{cliente.id}/download/{path*}") public File download(Cliente cliente, String path) { return ... } } ~~~ ##Definindo prioridades para seus paths É possível que algumas das nossas URIs possam ser tratada por mais de um método da classe: ~~~ #!java @Controller public class PostController { @Get @Path("/post/{post.autor}") public void mostra(Post post) { ... } @Get @Path("/post/atual") public void atual() { ... } } ~~~ A URI `/post/atual` pode ser tratada tanto pelo método mostra, quanto pelo atual. Mas eu quero que quando seja exatamente `/post/atual` o método executado seja o atual. O que eu quero é que o VRaptor teste primeiro o path do método atual, para não correr o risco de cair no método mostra. Para fazer isso, podemos definir prioridades para os `@Paths`, assim o VRaptor vai testar primeiro os paths com maior prioridade, ou seja, valor menor de prioridade: ~~~ #!java @Controller public class PostController { @Get @Path(value = "/post/{post.autor}", priority=Path.LOW) public void mostra(Post post) { ... } @Get @Path(value = "/post/atual", priority=Path.HIGH) public void atual() { ... } } ~~~ Assim, o path `/post/atual` vai ser testado antes do `/post/{post.autor}`, e o VRaptor vai fazer o que a gente gostaria que ele fizesse. Você não precisa definir prioridades se tivermos as uris: `/post/{post.id}` e `/post/atual`, pois na `/post/{post.id}` o vraptor só vai aceitar números. ##Paths com headers Você também pode injetar HTTP-Headers na sua lógica usando a anotação `HeaderParam`: ~~~ #!java public void profile(@HeaderParam('X-Auth-User') username) { ... } ~~~