Conheça a Resolução de Argumentos nos Controladores do Spring MVC

Um dos aspectos fascinantes do Spring MVC é a flexibilidade que encontramos para receber argumentos em nossos métodos de controladores. Neste texto vamos conversar sobre como esta mágica ocorre e como você pode se beneficiar dela para deixar seu código mais simples.


Para exemplificar um pouco esta flexibilidade, vamos imaginar que necessitamos de um objeto que está presente na sessão HTTP, por exemplo, o usuário logado. Algumas formas de recuperar o usuário via parâmetros de um controlador são as seguintes:

Nos dois primeiros métodos, estamos recuperando o objeto desejado por meio da API de Servlets, utilizando para isso uma instância do HttpServletRequest e o HttpSession associado à requisição HTTP corrente.

Nos dois métodos seguintes nós utilizamos artefatos do próprio Spring MVC. No primeiro, temos uma anotação chamada @SessionAttribute que permite vincular um atributo da sessão com um dado parâmetro. Já no segundo, uma instância da interface WebRequest, que abstrai muitos aspectos de uma requisição HTTP sem expor diretamente as classes da API Servlet.

A última forma é uma abordagem customizada, onde uma anotação criada pelo sistema, aqui chamada @UsuarioLogado, é utilizada para indicar que o usuário presente na sessão HTTP deve ser definido como parâmetro da requisição que está sendo processada.

Todas estas abordagens são possíveis devido uma abstração chamada Handler Method Argument Resolver.


Para exemplificar como esta abstração funciona vamos analisar como implementar a abordagem customizada citada anteriormente. Para isso, precisamos executar três passos. No primeiro, vamos definir uma anotação utilizada para marcar um parâmetro:

Com esta anotação, estamos dizendo ao compilador que ela deve ser aplicável apenas aos parâmetros, sendo assim nós podemos anotar parâmetro do controlador com ela. Como vamos vê mais na frente, esta anotação não é necessária para resolver um dado parâmetro.

Já no segundo passo, devemos criar uma implementação da interface Handler Method Argument Resolver:

A implementação é simples, basta definir dois métodos. No primeiro - supportsParameter - vamos dizer se o nosso handler será o responsável pela resolução de um dado parâmetro. Em nossa implementação, o argumento só será fornecido se o parâmetro estiver anotado por @UsuarioLogado e o tipo do parâmetro for da classe Usuario.

No segundo método — resolveArgument — nós devemos implementar a resolução do valor do argumento que será fornecido para o parâmetro. Neste caso, estamos utilizando uma especialização da interface WebRequest, que conhecemos a pouco, para retornar o objeto presente no atributo de escopo de sessão chamado “usuario”.

Com estes componentes implementados, só nos resta informar ao Spring sobre a existência do nosso resolver customizado. Isso pode ser feito com um código semelhante ao seguinte:

Feito isto, quando o Spring MVC identificar a classe responsável por manipular uma dada requisição, serão verificados os parâmetros presentes no método pela classe InvocableHandlerMethod e, para cada parâmetro, será verificado qual Handler Method Argument Resolver será capaz de fornecer um argumento válido. Muito legal, não? :)

Considerações Finais

Há diversos manipuladores já implementados pelo próprio módulo Web, para conhecer alguns basta verificar as implementações desta interface na própria documentação.

Além disso, outros módulos, tais como o Spring Data JPA, possuem extensões com o módulo Web bastante interessantes. Uma delas permite recuperar uma entidade de domínio diretamente do banco de dados, sem a necessidade de recuperar um parâmetro “ID” da requisição e invocar um método de consulta para recuperar este objeto no banco de dados. Com isso, não necessitamos injetar uma dependência do repositório no controlador em questão, deixando nosso código mais enxuto!

Até a próxima.

Se você acha que também pode contribuir com textos em português, entre em contato para compartilhar seus textos aqui.
Show your support

Clapping shows how much you appreciated Lucas Farias’s story.