Explorando o DispatcherServlet no Spring MVC

O Papel Central do DispatcherServlet

O DispatcherServlet é o componente fundamental do framework Spring Web MVC, atuando como um controlador frontal unificado para todas as requisições web. Inspirado no padrão de design Front Controller, ele centraliza o ponto de entrada para aplicações web, delegando responsabilidades específicas aos componentes apropriados e garantindo a integração perfeita com o contêiner IoC (Inversion of Control) do Spring, permitindo que a aplicação aproveite todos os benefícios da estrutura.

As principais funções do DispatcherServlet incluem:

  • Processamento de Uploads: Gerencia o tratamento de requisições do tipo multipart, como uploads de arquivos, utilizando um MultipartResolver.
  • Mapeamento de Requisições: Utiliza um HandlerMapping para associar as requisições HTTP a controladores específicos, retornando uma cadeia de execução (HandlerExecutionChain) que pode incluir o handler e vários interceptadores (HandlerInterceptor).
  • Adaptação de Handlers: Através de um HandlerAdapter, o DispatcherServlet suporta diversos tipos de handlers (controladores), adaptando a interface para a execução.
  • Resolução de Vistas: Transforma nomes lógicos de vistas em implementações de vistas concretas usando um ViewResolver.
  • Resolução de Localização: Determina as informações de localidade (Locale) para suporte à internacionalização.
  • Renderização da Vista: Executa a renderização final da vista para o cliente.
  • Tratamento de Exceções: Em caso de erros durante a execução, o HandlerExceptionResolver é acionado para gerenciar e apresentar respostas de erro adequadas.

Em suma, o DispatcherServlet coordena o fluxo de requisições e respostas, oferecendo pontos de extensão flexíveis em cada etapa do processo.

Configuração Básica do DispatcherServlet no web.xml

A configuração do DispatcherServlet é tipicamente realizada no descritor de implantação da aplicação web, o arquivo web.xml. Abaixo, um exemplo de configuração:


<!-- Definição do DispatcherServlet para o Spring MVC -->
<servlet>
    <servlet-name>minhaAppMvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/config/spring-web-config.xml</param-value>
    </init-param>
    <!-- Carrega o servlet na inicialização da aplicação -->
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- Mapeamento de URL para o DispatcherServlet -->
<servlet-mapping>
    <servlet-name>minhaAppMvc</servlet-name>
    <!-- Todas as requisições serão processadas pelo DispatcherServlet -->
    <url-pattern>/</url-pattern>
</servlet-mapping>

Parâmetros de inicialização (<init-param>) podem ser utilizados para personalizar o comportamento do DispatcherServlet:

  • contextClass: Define a classe que implementa WebApplicationContext para criar o contexto do servlet. O padrão é XmlWebApplicationContext.
  • contextConfigLocation: Especifica o(s) caminho(s) para os arquivos de configuração do contexto. Pode ser uma lista de caminhos separados por vírgula. Se não especificado, o Spring procurará por um arquivo no formato /WEB-INF/[servlet-name]-servlet.xml. No exemplo acima, ele busca spring-web-config.xml no classpath.
  • namespace: Atribui um nome para o contexto da aplicação web. O valor padrão é [servlet-name]-servlet.

A Relação entre Contextos de Aplicação

Em ambientes web Spring, é comum ter uma hierarquia de contextos de aplicação. A configuração abaixo mostra a criação de um contexto raiz, geralmente para beans de infraestrutura (DAO, Service):


<!-- Parâmetro para o Listener do Contexto Raiz -->
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
    classpath:config/app-datasource.xml,
    classpath:config/app-services.xml 
  </param-value>
</context-param>

<!-- Listener para carregar o Contexto Raiz -->
<listener> 
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> 

O ContextLoaderListener inicializa um WebApplicationContext (conhecido como contexto raiz) que é compartilhado por toda a aplicação. Este contexto geralmente contém beans de negócio e persistência (e.g., serviços e DAOs) que não dependem da tecnologia de apresentação.

O DispatcherServlet, por sua vez, inicializa seu próprio WebApplicationContext. Este contexto do servlet é um "filho" do contexto raiz. Isso significa que os beans definidos no contexto do DispatcherServlet podem referenciar os beans do contexto raiz, mas o contrário não é verdadeiro. O contexto do DispatcherServlet é dedicado a beans relacionados à camada web, como controladores, mapeadores de handlers e resolvedores de vistas.

Visualmente, essa relação pode ser pensada como: o contexto raiz provê recursos globais e de infraestrutura (como serviços e repositórios) para toda a aplicação, enquanto cada DispatcherServlet (pode haver mais de um em uma aplicação) tem seu próprio contexto, especializado em componentes web (como controladores), que herda e acessa os recursos do contexto raiz. Isso promove uma arquitetura modular e desacoplada.

Sequência de Inicialização do DispatcherServlet

A inicialização do DispatcherServlet segue uma hierarquia de classes no Spring Framework:

  1. HttpServletBean: Esta é a base que estende javax.servlet.http.HttpServlet. Durante o método init() padrão do servlet, ele processa os parâmetros de inicialização definidos no web.xml e os injeta como propriedades na própria instância do servlet. Ele também oferece um ponto de extensão, o método initServletBean(), que é implementado pelas subclasses.
  2. FrameworkServlet: Estende HttpServletBean e é responsável pela inicialização do WebApplicationContext para o servlet. No método initServletBean(), ele cria e configura o contexto web. Após a inicialização do contexto, ele chama o método onRefresh(), que é um ponto de extensão para a configuração específica do framework.
  3. DispatcherServlet: Esta é a classe concreta que estende FrameworkServlet e implementa onRefresh(). No onRefresh(), o DispatcherServlet executa as configurações específicas para o Spring Web MVC. Isso inclui a inicialização dos diversos componentes estratégicos (como HandlerMapping, HandlerAdapter, ViewResolver, etc.) que ele usará para processar as requisições. Se um contexto raiz (do ContextLoaderListener) estiver presente, ele será definido como o pai do contexto do DispatcherServlet.

As estratégias padrão utilizadas pelo DispatcherServlet (quando não configuradas explicitamente) são carregadas de um arquivo de propriedades chamado DispatcherServlet.properties, localizado no mesmo pacote da classe DispatcherServlet.

Beans Especiais Utilizados pelo DispatcherServlet

Dentro do seu WebApplicationContext, o DispatcherServlet utiliza uma série de beans especiais (também conhecidos como objetos de estratégia) para gerenciar o fluxo de requisições. Estes são alguns dos mais importantes:

  • Controller: Representa o "C" no MVC. Responsável por processar requisições após o mapeamento do HandlerMapping.
  • HandlerMapping: Mapeia requisições de entrada (URLs) para handlers (geralmente controladores). Retorna um HandlerExecutionChain que contém o handler e interceptadores associados.
  • HandlerAdapter: Permite que o DispatcherServlet invoque qualquer tipo de handler, independentemente de sua interface, agindo como um adaptador para o handler retornado pelo HandlerMapping.
  • ViewResolver: Traduz um nome lógico de vista (string) retornado por um controlador para uma implementação de vista concreta (e.g., um arquivo JSP, uma template Thymeleaf).
  • LocaleResolver: Deterimna a localidade do usuário (idioma, região) a partir da requisição, essencial para internacionalização.
  • ThemeResolver: Habilita a aplicação de temas (estilos visuais) a uma aplicação, permitindo mudar a aparência da interface do usuário.
  • MultipartResolver: Trata requisições de upload de arquivos (multipart/form-data), extraindo os arquivos da requisição HTTP.
  • HandlerExceptionResolver: Fornece um mecanismo para resolver exceções que ocorrem durante o processamento da requisição, permitindo mapear exceções para vistas de erro específicas.
  • RequestToViewNameTranslator: Uma estratégia que, quando um controlador não retorna um nome de vista explícito, deriva um nome lógico de vista a partir da URL da requisição.
  • FlashMapManager: Gerencia os FlashMaps, que são usados para armazenar atributos por um curto período, tipicamente para serem usados após um redirecionamento (e.g., mensagens de sucesso ou erro que precisam ser exibidas na próxima página).

Tags: Spring MVC DispatcherServlet Spring Framework Front Controller WebApplicationContext

Publicado em 9-5 14:53