Spring MVC 用DispatcherServlet處理請求

2021-04-30 11:04 更新

Spring MVC框架,與其他很多web的MVC框架一樣:請求驅(qū)動;所有設(shè)計(jì)都圍繞著一個(gè)中央Servlet來展開,它負(fù)責(zé)把所有請求分發(fā)到控制器;同時(shí)提供其他web應(yīng)用開發(fā)所需要的功能。不過Spring的中央處理器,DispatcherServlet,能做的比這更多。它與Spring IoC容器做到了無縫集成,這意味著,Spring提供的任何特性,在Spring MVC中你都可以使用。

下圖展示了Spring Web MVC的DispatcherServlet處理請求的工作流。熟悉設(shè)計(jì)模式的朋友會發(fā)現(xiàn),DispatcherServlet應(yīng)用的其實(shí)就是一個(gè)“前端控制器”的設(shè)計(jì)模式(其他很多優(yōu)秀的web框架也都使用了這個(gè)設(shè)計(jì)模式)。

圖21.1Spring Web MVC處理請求的(高層抽象)工作流

Spring Web MVC處理請求的(高層抽象)工作流

DispatcherServlet其實(shí)就是個(gè)Servlet(它繼承自HttpServlet基類),同樣也需要在你web應(yīng)用的web.xml配置文件下聲明。你需要在web.xml文件中把你希望DispatcherServlet處理的請求映射到對應(yīng)的URL上去。這就是標(biāo)準(zhǔn)的Java EE Servlet配置;下面的代碼就展示了對DispatcherServlet和路徑映射的聲明:

<web-app>
    <servlet>
        <servlet-name>example</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>example</servlet-name>
        <url-pattern>/example/*</url-pattern>
    </servlet-mapping>
</web-app>

In the preceding example, all requests starting with /example will be handled by the DispatcherServlet instance named example. In a Servlet 3.0+ environment, you also have the option of configuring the Servlet container programmatically. Below is the code based equivalent of the above web.xml example:

在上面的例子中,所有路徑以/example開頭的請求都會被名字為exampleDispatcherServlet處理。在Servlet 3.0+的環(huán)境下,你還可以用編程的方式配置Servlet容器。下面是一段這種基于代碼配置的例子,它與上面定義的web.xml配置文件是等效的。

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.addMapping("/example/*");
    }

}

WebApplicationInitializer是Spring MVC提供的一個(gè)接口,它會查找你所有基于代碼的配置,并應(yīng)用它們來初始化Servlet 3版本以上的web容器。它有一個(gè)抽象的實(shí)現(xiàn)AbstractDispatcherServletInitializer,用以簡化DispatcherServlet的注冊工作:你只需要指定其servlet映射(mapping)即可。若想了解更多細(xì)節(jié),可以參考基于代碼的Servlet容器初始化一節(jié)。

上面只是配置Spring Web MVC的第一步,接下來你需要配置其他的一些bean(除了DispatcherServlet以外的其他bean),它們也會被Spring Web MVC框架使用到。

6.15 應(yīng)用上下文ApplicationContext的其他作用)一節(jié)中我們聊到,Spring中的ApplicationContext實(shí)例是可以有范圍(scope)的。在Spring MVC中,每個(gè)DispatcherServlet都持有一個(gè)自己的上下文對象WebApplicationContext,它又繼承了根(root)WebApplicationContext對象中已經(jīng)定義的所有bean。這些繼承的bean可以在具體的Servlet實(shí)例中被重載,在每個(gè)Servlet實(shí)例中你也可以定義其scope下的新bean。

圖21.2 Spring Web MVC中常見的context層級結(jié)構(gòu)

DispatcherServlet的初始化過程中,Spring MVC會在你web應(yīng)用的WEB-INF目錄下查找一個(gè)名為[servlet-name]-servlet.xml的配置文件,并創(chuàng)建其中所定義的bean。如果在全局上下文中存在相同名字的bean,則它們將被新定義的同名bean覆蓋。

看看下面這個(gè)DispatcherServlet的Servlet配置(定義于web.xml文件中):

<web-app>
    <servlet>
        <servlet-name>golfing</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>golfing</servlet-name>
        <url-pattern>/golfing/*</url-pattern>
    </servlet-mapping>
</web-app>

有了以上的Servlet配置文件,你還需要在應(yīng)用中的/WEB-INF/路徑下創(chuàng)建一個(gè)golfing-servlet.xml文件,在該文件中定義所有Spring MVC相關(guān)的組件(比如bean等)。你可以通過servlet初始化參數(shù)為這個(gè)配置文件指定其他的路徑(更多細(xì)節(jié)請參考下文)。

當(dāng)你的應(yīng)用中只需要一個(gè)DispatcherServlet時(shí),只配置一個(gè)根context對象也是可行的。

圖21.3 Spring Web MVC中的根context

要配置一個(gè)唯一的根context對象,可以通過在servlet初始化參數(shù)中配置一個(gè)空的contextConfigLocation來做到,如下所示:

<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/root-context.xml</param-value>
    </context-param>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

WebApplicationContext繼承自ApplicationContext,它提供了一些web應(yīng)用經(jīng)常需要用到的特性。它與普通的ApplicationContext不同的地方在于,它支持主題的解析(詳見Spring MVC提供的主題一小節(jié)),并且知道它關(guān)聯(lián)到的是哪個(gè)servlet(它持有一個(gè)該ServletContext的引用)。WebApplicationContext被綁定在ServletContext中。如果需要獲取它,你可以通過RequestContextUtils工具類中的靜態(tài)方法來拿到這個(gè)web應(yīng)用的上下文WebApplicationContext。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號