对比 entre filtros e interceptadores em Java/Spring

No desenvolvimento com Java EE e Spring, filtros e interceptadores desempenham papéis importantes no processamento de requisições, mas possuem diferenças fundamentais em sua implementação e aplicação.

Diferenças Conceituais

  • Filtros são baseados em um mecanismo de funções de retorno (callback), enquanto interceptadores utilizam reflexão Java.
  • Filtros dependem fortemente do contêiner Servlet (como Tomcat), enquanto interceptadores são independentes, operando dentro do ciclo de vida da aplicação Spring.
  • Filtros podem ser aplicados a praticamente qualquer requisição HTTP (incluindo recursos estáticos), já interceptadores normalmente atuam apenas em requisições para handlers (controllers).
  • Interceptadores possuem acesso ao contexto da aplicação Spring (como o ApplicationContext e seus beans), permitindo injeção de dependências e invocação da lógica de negócios. Filtros não têm acesso direto a esses recursos do Spring.
  • Em uma única requisição, um filtro é chamado apenas uma vez, na entrada e saída. Um interceptador pode ser invocado múltiplas vezes durante o ciclo de vida de um handler.

Momento de Ativação e Fluxo de Execução

A principal diferença reside no momento de ativação. O fluxo de uma requisição, do servidor para o código da aplicação, segue esta sequência:

  1. A requisição HTTP chega ao contêiner Servlet.
  2. O Filtro é acionado (pré-processamento).
  3. A requisição é encaminhada para o DispatcherServlet do Spring (o Servlet central do Spring MVC).
  4. Dentro do Spring MVC, o Interceptador é acionado.
  5. O método do Controller (handler) é invocado.
  6. O Interceptador executa ações pós-processamento.
  7. A resposta passa novamente pelo Filtro (pós-processamento) antes de ser retornada ao cliente.

Em resumo: o Filtro envolve o Servlet, e o Interceptador é envolvido pelo fluxo interno do DispatcherServlet.

Exemplo de Filtro (javax.servlet.Filter)

Um filtro implementa a interface javax.servlet.Filter. Seu método principal recebe como parâmetros ServletRequest e ServletResponse, que são as abstrações mais genéricas do Servlet API.

@Override
public void doFilter(ServletRequest requisicao, ServletResponse resposta, FilterChain cadeia)
        throws IOException, ServletException {
    // Lógica de pré-processamento
    System.out.println(">>> Filtro antes do encaminhamento");

    // Encaminha a requisição para o próximo filtro ou para o Servlet
    cadeia.doFilter(requisicao, resposta);

    // Lógica de pós-processamento
    System.out.println("<<< Filtro após o retorno");
}

A chamada cadeia.doFilter() é o ponto de divisão que transfere o controle para o próximo elemento da cadeia, eventualmente chegando ao Servlet.

Exemplo de Interceptador (org.springframework.web.servlet.HandlerInterceptor)

Um interceptador Spring implementa a interface HandlerInterceptor. Ele oferece três pontos de interceptação que permitem maior granularidade no controle do fluxo de uma requisição de controller.

@Override
public boolean preHandle(HttpServletRequest requisicao, HttpServletResponse resposta,
                         Object handler) throws Exception {
    System.out.println("Interceptador: pré-handle");
    // Retornar true permite a continuação; false interrompe.
    return true;
}

@Override
public void postHandle(HttpServletRequest requisicao, HttpServletResponse resposta,
                       Object handler, ModelAndView modelAndView) throws Exception {
    System.out.println("Interceptador: pós-handle");
    // Pode modificar o ModelAndView antes da renderização da view.
}

@Override
public void afterCompletion(HttpServletRequest requisicao, HttpServletResponse resposta,
                            Object handler, Exception ex) throws Exception {
    System.out.println("Interceptador: após conclusão");
    // Executado após a renderização da view (ou após uma exceção).
}

A execução dos métodos do interceptador ocorre entre as chamadas do filtro:

  • preHandle() é chamado após o filtro de entrada e antes do handler.
  • postHandle() é chamado após o handler, mas antes do filtro de saída.
  • afterCompletion() é chamado no final, após a renderização, também antes do filtro de saída.

Considerações Práticas

No ecossistema Spring, os interceptadores são gerenciados como beans do contêiner IoC. Isso permite injetar outros serviços neles para realizar lógicas complexas, como autenticação e auditoria, mantendo o código do controller limpo.

Para simplificar, pode-se estender a classe HandlerInterceptorAdapter (ou AsyncHandlerInterceptor) e sobrescrever apenas os métodos desejados.

Para fins de diagnóstico e entendimento do fluxo completo, pode-se inserir pontos de depuração (breakpoints) nos métodos doFilter, service e preHandle para observar a ordem de execução diretamente.

Tags: Spring MVC Java EE Filtros Interceptadores Request Handling

Publicado em 7-20 04:14