O que é um Filtro (Filter)?
Um filtro é uma funcionalidade de especificação padrão J2EE que fornece a capacidade de lidar com tarefas adicionais para todas as solicitações correspondentes ao padrão de URL antes/depois de serem encaminhadas para o servlet despachador (Dispatcher Servlet). Em outras palavras, ele é gerenciado pelo contêiner da Web, como o Tomcat, em vez do contêiner Spring, e, portanto, processa a solicitação antes de atingir o servlet despachador.
Implementação de Filtro (Filter)
Para adicionar um filtro, é necessário implementar a interface Filter do javax.servlet, que possui os três métodos a seguir.
- Método init
- Este método é usado para inicializar o objeto de filtro e adicioná-lo ao serviço. O contêiner da Web chama o método init uma vez para inicializar o objeto de filtro, e as solicitações subsequentes são tratadas por meio do método doFilter().
- Método doFilter
- Este método é executado pelo contêiner da Web antes que todas as solicitações HTTP correspondentes ao padrão de URL sejam encaminhadas para o servlet despachador e antes que o servlet despachador envie a resposta HTTP para o cliente.
O parâmetro do método doFilter() é FilterChain, e a chamada doFilter() de FilterChain encaminha a solicitação para o próximo destino. Ao inserir o processo necessário antes e depois de chain.doFilter(), podemos executar o processo desejado.
- Este método é executado pelo contêiner da Web antes que todas as solicitações HTTP correspondentes ao padrão de URL sejam encaminhadas para o servlet despachador e antes que o servlet despachador envie a resposta HTTP para o cliente.
- Método destroy
- Este método é usado para remover o objeto de filtro do serviço e retornar os recursos usados. Ele é chamado uma vez pelo contêiner da Web, após o qual não é mais processado por doFilter().
Código de exemplo - Especificação Servlet
Código de exemplo - @Component
- @Component: Permite registrar o filtro como um bean Spring.
- @Order: Permite definir a ordem quando houver vários filtros.
- Ao registrar o filtro correspondente à especificação do servlet como um bean Spring dessa forma, você pode usar outros beans correspondentes à especificação Spring.
Código de exemplo - @Configuration
Se você deseja que o filtro seja executado apenas para um URI específico, pode registrar o filtro como um bean Spring usando FilterRegistrationBean.
Propósito do Filtro (Filter)
É principalmente responsável por validar e processar os próprios parâmetros da solicitação.
- Tarefas comuns relacionadas à segurança
- Como o filtro é executado no contêiner da Web, ele pode executar verificações de segurança (como prevenção de XSS e CSRF) para bloquear solicitações inválidas. Como a solicitação é bloqueada antes mesmo de atingir o contêiner Spring, a segurança é ainda maior.
- Registro de todas as solicitações
- Compressão de imagem/dados e codificação de caracteres
- O filtro implementou funções usadas globalmente em aplicativos da Web, como compressão de imagem/dados e codificação de caracteres.
- Personalização de ServletRequest
- HttpServletRequest pode ler o conteúdo do corpo apenas uma vez. Portanto, Filter ou Interceptor não podem ler o corpo. Um ServletRequest personalizado pode ser criado para registrar o corpo.
Interceptor (Interceptador)
O que é um Interceptor (Interceptador)?
Diferente do filtro (Filter), que é uma especificação padrão J2EE, o interceptor (Interceptor) é uma tecnologia fornecida pelo Spring. Ele fornece a capacidade de referenciar ou processar solicitações e respostas antes e depois do servlet despachador chamar o controlador. Ou seja, ao contrário do filtro, que opera no contêiner da Web, o interceptor opera no contexto Spring.
O servlet despachador solicita que o mapeamento de manipulador encontre o controlador apropriado, e como resultado, ele retorna a cadeia de execução (HandlerExecutionChain). Portanto, se houver um ou mais interceptadores registrados nesta cadeia de execução, eles são executados sequencialmente antes da execução do controlador, e se não houver interceptadores, o controlador é executado diretamente.
Implementação de Interceptor (Interceptor)
Para adicionar um interceptor, é necessário implementar a interface HandlerInterceptor do org.springframework.web.servlet, que possui os três métodos a seguir.
- Método preHandle
- O método preHandle é executado antes que o controlador seja chamado. Portanto, ele pode ser usado para realizar tarefas de pré-processamento antes do controlador ou para processar e adicionar informações de solicitação.
- O terceiro parâmetro do método preHandle, o parâmetro handler, é um objeto que abstrai as informações do método com @RequestMapping.
- O tipo de retorno do método preHandle é booleano, e se o valor retornado for true, a execução continua para a próxima etapa, mas se for false, a execução é interrompida, e as etapas subsequentes (próximo interceptor ou controlador) não são executadas.
- Método postHandle
- O método postHandle é executado após a chamada do controlador. Portanto, ele pode ser usado quando houver tarefas de pós-processamento a serem executadas após o controlador.
- Método afterCompletion
- Como o nome sugere, o método afterCompletion é executado após a conclusão de todas as tarefas, incluindo a geração do resultado final por todas as visualizações.
Código de exemplo
- Registre o interceptor criado como um bean.
- Registre o interceptor criado no método addInterceptors() da interface WebMvcConfigurer.
- Os interceptadores são executados na ordem em que são registrados no InterceptorRegistry.
Propósito do Interceptor (Interceptor)
É principalmente responsável por lidar com o processamento da integridade das informações da solicitação usando a lógica de serviço.
- Tarefas comuns como autenticação/autorização
- Pode-se verificar tarefas relacionadas ao cliente, como autenticação ou autorização, antes que sejam encaminhadas para o controlador.
- Registro de chamadas de API
- As informações do cliente podem ser registradas por meio dos objetos HttpServletRequest e HttpServletResponse recebidos.
- Processamento de dados passados para o Controller
- Os objetos HttpServletRequest e HttpServletResponse recebidos podem ser processados e passados para o controlador.
- Imitação de AOP
- O terceiro parâmetro do método preHandle, HandlerMethod, pode ser usado para obter informações adicionais, como a assinatura do método a ser executado, para determinar se a lógica deve ser executada.
Filtro (Filter) vs. Interceptor (Interceptor)
- O filtro é executado no contexto da Web, enquanto o interceptor é executado no contexto Spring, portanto, os tempos de execução são diferentes.
- O filtro pode lidar com o antes e o depois do servlet despachador, enquanto o interceptor pode lidar com o antes e o depois do controlador.
- O filtro é ideal para tarefas que precisam ser processadas globalmente independentemente do Spring, para validação com foco nos próprios parâmetros de entrada ou quando se usa ServletRequest em vez de HttpServletRequest.
- O interceptor é ideal para tarefas que precisam ser processadas globalmente relacionadas à solicitação do cliente que entra no escopo Spring ou quando se precisa misturar lógica de serviço.
- O interceptor pode lidar com exceções usando @ControllerAdvice e @ExceptionHandler, mas o filtro não pode.
- O filtro geralmente envolve o método doFilter() com uma instrução try~catch para lidar diretamente com as exceções que ocorrem nesse ponto.
Argument Resolver
O que é Argument Resolver?
Argument Resolver pode indiretamente criar o objeto desejado a partir dos valores recebidos quando uma solicitação chega ao controlador.
Propósito do Argument Resolver
Por exemplo, suponha que uma solicitação tenha chegado com um token JWT. Precisamos validar se este token é válido e, em seguida, extrair o ID armazenado no token e criá-lo como um objeto de usuário logado.
Se não usarmos Argument Resolver, precisamos implementar o processo de validação do token e conversão para um objeto de usuário logado em todos os controladores. Isso resultaria em código duplicado nos controladores que exigem a validação do usuário, e a responsabilidade do controlador aumentaria. Argument Resolver pode resolver esse problema.
Implementação do Argument Resolver
ArgumentResolver pode ser usado implementando HandlerMethodArgumentResolver. Esta interface especifica que os dois métodos abaixo devem ser implementados.
- Método supportsParameter
- Uma determinada anotação é anexada ao parâmetro para o qual você deseja que o ArgumentResolver seja executado. O método supportsParameter() verifica se o método solicitado possui a anotação desejada, e se a possui, retorna true.
- Método resolveArgument
- Se true for recebido em supportsParameter, ou seja, se houver um determinado método com uma anotação anexada, é o método que vincula o parâmetro à forma desejada e retorna o resultado.
Quando ArgumentResolver é usado dessa forma, a implementação do controlador é a seguinte.
Diferença entre Argument Resolver e Interceptor (Interceptador)
- ArgumentResolver é executado após o interceptor e retorna o objeto desejado a partir dos valores recebidos quando uma solicitação chega ao controlador.
- Por outro lado, o interceptor intercepta a solicitação antes que o controlador seja realmente executado e não pode retornar um determinado objeto. Apenas os tipos de retorno booleano ou vazio são permitidos.
Fontes
- https://mangkyu.tistory.com/173
- https://junhyunny.github.io/spring-boot/filter-interceptor-and-aop/
- https://supawer0728.github.io/2018/04/04/spring-filter-interceptor/
- https://tecoble.techcourse.co.kr/post/2021-05-24-spring-interceptor/
- https://baeldung-cn.com/spring-mvc-handlerinterceptor-vs-filter
- https://www.baeldung.com/spring-boot-add-filter
Perguntas e Respostas Esperadas na Entrevista
O que é um filtro?
Um filtro fornece a capacidade de lidar com tarefas adicionais para todas as solicitações correspondentes ao padrão de URL antes/depois de serem encaminhadas para o servlet despachador e opera no nível do contêiner do servlet.
Quando usar um filtro?
Os filtros podem lidar com tarefas que precisam ser processadas globalmente independentemente do Spring. Ou eles são usados para validar parâmetros de solicitação.
Especificamente, ele lida com tarefas comuns relacionadas à segurança, registro de todas as solicitações, compressão de imagem/dados e codificação de caracteres e personalização de ServletRequest.
O que é um interceptor?
Um interceptor fornece a capacidade de referenciar ou processar solicitações e respostas antes e depois do servlet despachador chamar o controlador, e opera no nível do contêiner Spring.
Quando usar um interceptor?
Os interceptadores podem lidar com tarefas que precisam ser processadas globalmente relacionadas à solicitação do cliente. Eles são frequentemente usados quando a lógica do serviço precisa ser chamada durante a validação.
Especificamente, ele lida com tarefas comuns como autenticação/autorização, registro de chamadas de API e processamento de dados passados para o controlador.
Qual a diferença entre um filtro e um interceptor?
Os filtros são executados no contêiner do servlet, enquanto os interceptadores são executados no contêiner Spring.
Os filtros podem lidar com o antes e o depois do servlet despachador, enquanto os interceptadores podem lidar com o antes e o depois do controlador.
Portanto, os filtros são ideais para tarefas que precisam ser processadas globalmente independentemente do Spring, e os interceptadores são ideais para tarefas que precisam ser processadas globalmente relacionadas à solicitação do cliente.
O que é Argument Resolver?
Argument Resolver indiretamente cria o objeto desejado a partir dos valores recebidos quando uma solicitação chega ao controlador.
Quando usar Argument Resolver?
Ele pode ser usado quando uma solicitação chega com um token JWT, e você precisa validar se o token é válido e, em seguida, extrair o ID armazenado no token e criá-lo como um objeto LoginMember.
Qual a diferença entre um interceptor e Argument Resolver?
ArgumentResolver retorna o objeto desejado a partir dos valores recebidos quando uma solicitação chega ao controlador. Por outro lado, o interceptor não pode retornar um objeto dessa forma, e Argument Resolver é executado após a execução do interceptor.
Comentários0