Springmvc DispatcherServlet原理及用法解析
DispatcherServlet 是前端控制器設(shè)計(jì)模式的實(shí)現(xiàn),提供 Spring Web MVC 的集中訪問點(diǎn),而且負(fù)責(zé)職責(zé)的分派,而且與 Spring IoC 容器無縫集成,從而可以獲得 Spring 的所有好處。DispatcherServlet 主要用作職責(zé)調(diào)度工作,本身主要用于控制流程,主要職責(zé)如下:
- 文件上傳解析,如果請(qǐng)求類型是 multipart 將通過 MultipartResolver 進(jìn)行文件上傳解析;
- 通過 HandlerMapping,將請(qǐng)求映射到處理器(返回一個(gè) HandlerExecutionChain,它包括一個(gè)處理器、多個(gè) HandlerInterceptor 攔截器);
- 通過 HandlerAdapter 支持多種類型的處理器(HandlerExecutionChain 中的處理器);
- 通過 ViewResolver 解析邏輯視圖名到具體視圖實(shí)現(xiàn);
- 本地化解析;
- 渲染具體的視圖等;
- 如果執(zhí)行過程中遇到異常將交給 HandlerExceptionResolver 來解析
DispathcherServlet配置詳解
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- servlet-mapping -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- load-on-startup:表示啟動(dòng)容器時(shí)初始化該 Servlet;
- url-pattern:表示哪些請(qǐng)求交給 Spring Web MVC 處理, "/" 是用來定義默認(rèn) servlet 映射的。也可以如 *.html 表示攔截所有以 html 為擴(kuò)展名的請(qǐng)求
- contextConfigLocation:表示 SpringMVC 配置文件的路徑

Spring配置
先添加一個(gè)service包,提供一個(gè)HelloService類,如下:
@Service
public class HelloService {
public String hello(String name) {
return "hello " + name;
}
}
添加applicationContext.xml
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.javaboy" use-default-filters="true">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
這個(gè)配置文件默認(rèn)情況下,并不會(huì)被自定加載,所有,需要我們?cè)趙eb.xml對(duì)其進(jìn)行配置
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
首先通過 context-param 指定 Spring 配置文件的位置,這個(gè)配置文件也有一些默認(rèn)規(guī)則,它的配置文件名默認(rèn)就叫 applicationContext.xml ,并且,如果你將這個(gè)配置文件放在 WEB-INF 目錄下,那么這里就可以不用指定配置文件位置了,只需要指定監(jiān)聽器就可以了。這段配置是 Spring 集成 Web 環(huán)境的通用配置;一般用于加載除 Web 層的 Bean(如DAO、Service 等),以便于與其他任何Web框架集成。
contextConfigLocation: 表示用于加載Bean的配置文件
contextClass: 表示用于加載 Bean的 ApplicationContext 實(shí)現(xiàn)類,默認(rèn) WebApplicationContext。
在MyController中注入HelloService:
@org.springframework.stereotype.Controller("/hello")
public class MyController implements Controller {
@Autowired
HelloService helloService;
/**
* 這就是一個(gè)請(qǐng)求處理接口
* * @param req 這就是前端發(fā)送來的請(qǐng)求
* * @param resp 這就是服務(wù)端給前端的響應(yīng)
* * @return 返回值是一個(gè) ModelAndView,Model 相當(dāng)于是我們的數(shù)據(jù)模型,
* View 是我們的視圖 * @throws Exception
*/
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
System.out.println(helloService.hello("javaboy"));
ModelAndView mv = new ModelAndView("hello");
mv.addObject("name", "javaboy");
return mv;
}
}
為了在 SpringMVC 容器中能夠掃描到 MyController ,這里給 MyController 添加了 @Controller 注解,同時(shí),由于我們目前采用的 HandlerMapping 是 BeanNameUrlHandlerMapping(意味著請(qǐng)求地址就是處理器 Bean 的名字),所以,還需要手動(dòng)指定 MyController 的名字。
最后,修改 SpringMVC 的配置文件,將 Bean 配置為掃描形式:
<context:component-scan base-package="org.javaboy.helloworld" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
<!--這個(gè)是處理器映射器,這種方式,請(qǐng)求地址其實(shí)就是一個(gè) Bean 的名字,然后根據(jù)這個(gè) bean 的名字查找對(duì)應(yīng)的處理器--> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" id="handlerMapping"> <property name="beanName" value="/hello"/> </bean> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" id="handlerAdapter"/> <!--視圖解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver"> <property name="prefix" value="/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
配置完成后,再次啟動(dòng)項(xiàng)目,Spring 容器也將會(huì)被創(chuàng)建。訪問 /hello 接口,HelloService 中的 hello 方法就會(huì)自動(dòng)被調(diào)用。
兩個(gè)容器

當(dāng) Spring 和 SpringMVC 同時(shí)出現(xiàn),我們的項(xiàng)目中將存在兩個(gè)容器,一個(gè)是 Spring 容器,另一個(gè)是 SpringMVC 容器,Spring 容器通過 ContextLoaderListener 來加載,SpringMVC 容器則通過 DispatcherServlet 來加載,這兩個(gè)容器不一樣:
從圖中可以看出:
- ContextLoaderListener 初始化的上下文加載的 Bean 是對(duì)于整個(gè)應(yīng)用程序共享的,不管是使用什么表現(xiàn)層技術(shù),一般如 DAO 層、Service 層 Bean;
- DispatcherServlet 初始化的上下文加載的 Bean 是只對(duì) Spring Web MVC 有效的 Bean,如 Controller、HandlerMapping、HandlerAdapter 等等,該初始化上下文應(yīng)該只加載 Web相關(guān)組件。
這個(gè)是不可能的。因?yàn)檎?qǐng)求達(dá)到服務(wù)端后,找DispatcherServlet 去處理,只會(huì)去 SpringMVC 容器中找,這就意味著Controller 必須在 SpringMVC 容器中掃描。
2.為什么不在 SpringMVC 容器中掃描所有 Bean?
這個(gè)是可以的,可以在SpringMVC 容器中掃描所有 Bean。不寫在一起,有兩個(gè)方面的原因:
- 為了方便配置文件的管理
- 在 Spring+SpringMVC+Hibernate 組合中,實(shí)際上也不支持這種寫法
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringMVC中的DispatcherServlet請(qǐng)求分析
- SpringMVC中的DispatcherServlet結(jié)構(gòu)和初始化詳解
- SpringMVC中的DispatcherServlet初始化流程詳解
- SpringMVC之DispatcherServlet配置文件應(yīng)該放在哪里呢
- SpringMVC核心DispatcherServlet處理流程分步詳解
- spring boot 實(shí)現(xiàn)配置多個(gè)DispatcherServlet最簡(jiǎn)單方式
- Spring Boot全局異常處理機(jī)制中DispatcherServlet的處理流程和作用
相關(guān)文章
java網(wǎng)絡(luò)編程之識(shí)別示例 獲取主機(jī)網(wǎng)絡(luò)接口列表
一個(gè)客戶端想要發(fā)起一次通信,先決條件就是需要知道運(yùn)行著服務(wù)器端程序的主機(jī)的IP地址是多少。然后我們才能夠通過這個(gè)地址向服務(wù)器發(fā)送信息。2014-01-01
Java實(shí)現(xiàn)簡(jiǎn)單的聊天室功能
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單的聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
Java中LinkedList數(shù)據(jù)結(jié)構(gòu)的詳細(xì)介紹
這篇文章主要介紹了Java中LinkedList,Linked List 是 java.util 包中 Collection 框架的一部分,文中提供了詳細(xì)的代碼說明,需要的朋友可以參考下2023-05-05
springboot中如何去整合shrio實(shí)例分享
這篇文章主要介紹了springboot中如何去整合shrio實(shí)例分享的相關(guān)資料,需要的朋友可以參考下2023-08-08
java通過url讀取遠(yuǎn)程數(shù)據(jù)并保持到本地的實(shí)例代碼
本文通過實(shí)例代碼給大家介紹了java通過url讀取遠(yuǎn)程數(shù)據(jù)并保持到本地的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-07-07
Java實(shí)現(xiàn)簡(jiǎn)易的分詞器功能
搜索功能是具備數(shù)據(jù)庫(kù)功能的系統(tǒng)的一大重要特性和功能,生活中常見的搜索功能基本上都具備了分詞搜索功能.然而ES功能固然強(qiáng)大,但對(duì)于學(xué)生或小項(xiàng)目而言整合起來太費(fèi)人力物力,若是寫個(gè)分詞器就會(huì)使項(xiàng)目錦上添花,使其不僅僅是只能單關(guān)鍵詞搜索的系統(tǒng),需要的朋友可以參考下2021-06-06
java 如何實(shí)現(xiàn)正確的刪除集合中的元素
這篇文章主要介紹了java 如何實(shí)現(xiàn)正確的刪除集合中的元素,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09
深入理解 Spring Bean 后處理器@Autowired 等注解的本質(zhì)(示
在日常開發(fā)中,我們幾乎每天都會(huì)用到 @Autowired、@Value、@Resource、@PostConstruct 等注解,今天我們通過一個(gè)非常簡(jiǎn)潔的 Demo,一步步揭開 Spring Bean 后處理器的秘密,感興趣的朋友一起看看吧2025-10-10

