O que é o Servlet Dispatcher no Spring?

195

Nesta imagem (que obtive daqui ), a solicitação HTTP envia algo para o Dispatcher Servlet.

insira a descrição da imagem aqui

Minha pergunta é o que o Dispatcher Servlet faz?

É algo como obter as informações lançadas da página da web e jogá-las no controlador?

Kevin
fonte

Respostas:

202

O trabalho do DispatcherServlet é pegar um URI de entrada e encontrar a combinação certa de manipuladores (geralmente métodos nas classes Controller ) e visualizações (geralmente JSPs) que se combinam para formar a página ou recurso que deveria ser encontrado nesse local.

talvez eu tenha

  • um arquivo /WEB-INF/jsp/pages/Home.jsp
  • e um método em uma classe

    @RequestMapping(value="/pages/Home.html")
    private ModelMap buildHome() {
        return somestuff;
    }

O servlet Dispatcher é o bit que "sabe" chamar esse método quando um navegador solicita a página e combinar seus resultados com o arquivo JSP correspondente para criar um documento html.

Como isso ocorre varia muito com a configuração e a versão do Spring.

Também não há razão para o resultado final ter que ser páginas da web. Ele pode fazer o mesmo para localizar pontos finais de RMI , manipular solicitações SOAP , qualquer coisa que possa entrar em um servlet.

Affe
fonte
4
Ótima resposta, agora uma pergunta: como o DispatcherServlet também identifica o nome da classe e o método. Você pode me mostrar um exemplo de configuração em que eu tenho duas classes e dois nomes de métodos e como DispatcherServlet captura a solicitação correta.
Kevin
10
Na verdade, ele verifica o caminho da classe na inicialização para essa anotação e faz um mapeamento de "/pages/Home.html" para o método Class +. Se você tivesse dois métodos com "/pages/Home.html" sem outras restrições em suas anotações, isso seria um erro e geraria exceções para você. Você também pode conectá-lo com XML, se você é da velha escola.
Afixe
2
Precisamos de um Dispatcher Servletarquivo xml ao usar Annotation Based @RestController?
víbora
1
@viper em web.xml nós sempre precisa configurar despachante servlet mesmo que você usar anotações ou configurações XML
Mahender Reddy Yasa
Existe algum outro tipo de servlet?
Minh Nghĩa
72

No Spring MVC, todas as solicitações recebidas passam por um único servlet. Este servlet - DispatcherServlet- é o controlador frontal. O controlador frontal é um padrão de design típico no desenvolvimento de aplicativos da web. Nesse caso, um único servlet recebe todos os pedidos e os transfere para todos os outros componentes do aplicativo.

A tarefa do DispatcherServleté enviar solicitação ao controlador Spring MVC específico.

Geralmente, temos muitos controladores e DispatcherServletrefere-se a um dos seguintes mapeadores para determinar o controlador de destino:

Se nenhuma configuração for realizada, os DispatcherServletusos BeanNameUrlHandlerMappinge DefaultAnnotationHandlerMappingpor padrão.

Quando o controlador de destino é identificado, a DispatcherServletsolicitação é enviada. O controlador realiza algum trabalho de acordo com a solicitação (ou o delega para outros objetos) e retorna ao DispatcherServletmodelo e ao nome da visualização.

O nome da exibição é apenas um nome lógico. Esse nome lógico é então usado para procurar a Visualização real (para evitar o acoplamento com o controlador e a Visualização específica). Em seguida, DispatcherServletrefere-se ViewResolverae mapeia o nome lógico da Visualização para a implementação específica da Visualização.

Algumas implementações possíveis do ViewResolversão:

Quando DispatcherServletdetermina a visualização que exibirá os resultados, ela será renderizada como resposta.

Finalmente, DispatcherServletretorna o Responseobjeto de volta ao cliente.

HDJEMAI
fonte
47

DispatcherServleté a implementação do Spring MVC do padrão do controlador frontal .

Veja a descrição nos documentos do Spring aqui .

Essencialmente, é um servlet que leva a solicitação de entrada e delega o processamento dessa solicitação a um dos vários manipuladores, cujo mapeamento é específico na DispatcherServletconfiguração.

skaffman
fonte
É algo como eventos no Flex, onde recebo eventos de despacho de um MXML para outro ou para o servidor. Posso ter mais de um DispatcherServlet em meu aplicativo. Os arquivos de cada classe têm um DispatcherServlet separado.
Kevin
Geralmente, há apenas um controlador frontal. Isso é independente dos modelos e visualizações que você possui. Apenas reúne modelos e visualizações específicos.
BalusC
2
@ theband: Você pode ter vários DispatcherServlets, se sua arquitetura fizer mais sentido dessa maneira, mas geralmente não há motivos para isso.
Skaffman
47

Sei que esta questão já está marcada como resolvida, mas quero adicionar uma imagem mais recente explicando esse padrão em detalhes (fonte: spring in action 4):

insira a descrição da imagem aqui

Explicação

Quando a solicitação sai do navegador (1) , ela carrega informações sobre o que o usuário está solicitando. No mínimo, a solicitação estará carregando o URL solicitado. Mas também pode transportar dados adicionais, como as informações enviadas em um formulário pelo usuário.

A primeira parada nas viagens da solicitação é no DispatcherServlet da Spring. Como a maioria das estruturas da Web baseadas em Java, o Spring MVC direciona solicitações por meio de um único servlet de controlador frontal. Um controlador frontal é um padrão comum de aplicativo da Web em que um único servlet delega a responsabilidade por uma solicitação a outros componentes de um aplicativo para executar o processamento real. No caso do Spring MVC, o DispatcherServlet é o controlador frontal. O trabalho do DispatcherServlet é enviar a solicitação para um controlador Spring MVC. Um controlador é um componente do Spring que processa a solicitação. Mas um aplicativo típico pode ter vários controladores, e o DispatcherServlet precisa de ajuda para decidir a qual controlador enviar a solicitação. Portanto, o DispatcherServlet consulta um ou mais mapeamentos de manipulador (2)para descobrir onde será a próxima parada da solicitação. O mapeamento do manipulador presta atenção especial ao URL transportado pela solicitação ao tomar sua decisão. Depois que um controlador apropriado é escolhido, o DispatcherServlet envia a solicitação de maneira alegre para o controlador escolhido (3). No controlador, a solicitação diminui sua carga útil (as informações enviadas pelo usuário) e espera pacientemente enquanto o controlador processa essas informações. (Na verdade, um controlador bem projetado realiza pouco ou nenhum processamento em si e, em vez disso, delega a responsabilidade pela lógica comercial a um ou mais objetos de serviço.) A lógica executada por um controlador geralmente resulta em algumas informações que precisam ser transportadas para o usuário e exibido no navegador. Esta informação é referida como o modelo. Mas enviar informações brutas de volta para o usuário não é suficiente - ele precisa ser formatado em um formato amigável, geralmente HTML. Para isso, as informações precisam ser fornecidas para uma visualização, geralmente uma JavaServer Page (JSP). Uma das últimas coisas que um controlador faz é empacotar os dados do modelo e identificar o nome de uma exibição que deve renderizar a saída. Em seguida, ele envia a solicitação, juntamente com o nome do modelo e da visualização, de volta ao DispatcherServlet(4) . Para que o controlador não seja acoplado a uma visualização específica, o nome da visualização passado para DispatcherServlet não identifica diretamente um JSP específico. Nem sequer sugere necessariamente que a visualização é um JSP. Em vez disso, ele carrega apenas um nome lógico que será usado para procurar a visualização real que produzirá o resultado. O DispatcherServlet consulta um resolvedor de visualização (5) para mapear o nome da visualização lógica para uma implementação específica da visualização, que pode ou não ser um JSP. Agora que o DispatcherServlet sabe qual visualização renderizará o resultado, o trabalho da solicitação está quase no fim. Sua parada final está na implementação da vista (6), geralmente um JSP, em que ele fornece os dados do modelo. O trabalho da solicitação está finalmente concluído. A visualização usará os dados do modelo para renderizar a saída que será transportada de volta ao cliente pelo objeto de resposta (não muito trabalhoso) (7) .

Eduardo
fonte
Eu tenho uma pergunta, por favor, como ele seleciona a visualização no caso de retornar o objeto JSON que vemos no navegador, ele retorna ao mesmo URI se não houver nenhuma visualização lógica selecionada?
Nesrin 11/01/19
1
@ Nesrin, faz muito tempo que você não pediu, mas aqui está uma resposta: Você coloca uma anotação especial logo acima do @Controllermétodo chamado, @ResponseBodyindicando que a resposta retornada deve ser escrita diretamente no corpo da resposta HTTP, não para ser colocada em um Modelo ou ser resolvida conforme a vista. .
painel
6

Podemos dizer como DispatcherServletcuidar de tudo no Spring MVC.

No contêiner da web, inicie:

  1. DispatcherServlet será carregado e inicializado chamando init() método
  2. init()O DispatcherServlettentará identificar o documento de configuração do Spring com convenções de nomenclatura, como "servlet_name-servlet.xml"todos os beans podem ser identificados.

Exemplo:

public class DispatcherServlet extends HttpServlet {

    ApplicationContext ctx = null;

    public void init(ServletConfig cfg){
        // 1. try to get the spring configuration document with default naming conventions
        String xml = "servlet_name" + "-servlet.xml";

        //if it was found then creates the ApplicationContext object
        ctx = new XmlWebApplicationContext(xml);
    }
    ...
}

Portanto, em geral DispatcherServletcaptura URI de solicitação e entrega para HandlerMapping. HandlerMappingprocure o mapeamento de bean com o método do controlador, em que o controlador retorna o nome lógico (visualização). Então esse nome lógico é enviado para DispatcherServletpor HandlerMapping. Em seguida, DispatcherServletdiga ViewResolverpara fornecer a localização completa da visão acrescentando prefixo e sufixo e, em seguida, DispatcherServletvisualize o cliente.

user2663609
fonte
Esta é uma boa explicação. Seu ponto 2 diz que o DispatcherServlet tentará identificar o Documento de Configuração do Spring com convenções de nomenclatura como "servlet_name-servlet.xml". No entanto, vi projetos que usavam nomes apenas como "dispatcher" e funcionam bem. Eu também tentei isso. Mas eu não sei por quê?
Subhasish Bhattacharjee
0

O Dispatcher Controller é exibido na figura em que toda a solicitação recebida é interceptada pelo servlet do dispatcher que funciona como controlador frontal. O servlet do distribuidor obtém uma entrada para o mapeamento do manipulador do arquivo XML e define a solicitação para o Controlador.

anjali shrivas
fonte
-1
<?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
    <context:component-scan base-package="com.demo" />
    <context:annotation-config />

    <mvc:annotation-driven />


    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp" />

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="datasource" />
    </bean> 

          <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
        <property name="url" value="jdbc:mysql://localhost:3306/employee" />
        <property name="username" value="username" />
        <property name="password" value="password" />
    </bean> 

</beans>
kartik
fonte