DispatcherServlet 是前端控制器設計模式的實現,提供 Spring Web MVC 的集中訪問點,而且負責職責的分派,而且與 Spring IoC 容器無縫集成,從而可以獲得 Spring 的所有好處。DispatcherServlet 主要用作職責調度工作,本身主要用于控制流程,主要職責如下:
- 文件上傳解析,如果請求類型是 multipart 將通過 MultipartResolver 進行文件上傳解析;
- 通過 HandlerMapping,將請求映射到處理器(返回一個 HandlerExecutionChain,它包括一個處理器、多個 HandlerInterceptor 攔截器);
- 通過 HandlerAdapter 支持多種類型的處理器(HandlerExecutionChain 中的處理器);
- 通過 ViewResolver 解析邏輯視圖名到具體視圖實現;
- 本地化解析;
- 渲染具體的視圖等;
- 如果執行過程中遇到異常將交給 HandlerExceptionResolver 來解析
DispathcherServlet配置詳解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
< 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:表示啟動容器時初始化該 Servlet;
- url-pattern:表示哪些請求交給 Spring Web MVC 處理, "/" 是用來定義默認 servlet 映射的。也可以如 *.html 表示攔截所有以 html 為擴展名的請求
- contextConfigLocation:表示 SpringMVC 配置文件的路徑
Spring配置
先添加一個service包,提供一個HelloService類,如下:
1
2
3
4
5
6
|
@Service public class HelloService { public String hello(String name) { return "hello " + name; } } |
添加applicationContext.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<? 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 > |
這個配置文件默認情況下,并不會被自定加載,所有,需要我們在web.xml對其進行配置
1
2
3
4
5
6
|
< 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 配置文件的位置,這個配置文件也有一些默認規則,它的配置文件名默認就叫 applicationContext.xml ,并且,如果你將這個配置文件放在 WEB-INF 目錄下,那么這里就可以不用指定配置文件位置了,只需要指定監聽器就可以了。這段配置是 Spring 集成 Web 環境的通用配置;一般用于加載除 Web 層的 Bean(如DAO、Service 等),以便于與其他任何Web框架集成。
contextConfigLocation: 表示用于加載Bean的配置文件
contextClass: 表示用于加載 Bean的 ApplicationContext 實現類,默認 WebApplicationContext。
在MyController中注入HelloService:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@org .springframework.stereotype.Controller( "/hello" ) public class MyController implements Controller { @Autowired HelloService helloService; /** * 這就是一個請求處理接口 * * @param req 這就是前端發送來的請求 * * @param resp 這就是服務端給前端的響應 * * @return 返回值是一個 ModelAndView,Model 相當于是我們的數據模型, * 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 注解,同時,由于我們目前采用的 HandlerMapping 是 BeanNameUrlHandlerMapping(意味著請求地址就是處理器 Bean 的名字),所以,還需要手動指定 MyController 的名字。
最后,修改 SpringMVC 的配置文件,將 Bean 配置為掃描形式:
1
2
3
|
< 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 > |
1
2
3
4
5
6
7
8
9
10
11
|
<!--這個是處理器映射器,這種方式,請求地址其實就是一個 Bean 的名字,然后根據這個 bean 的名字查找對應的處理器--> < 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 > |
配置完成后,再次啟動項目,Spring 容器也將會被創建。訪問 /hello 接口,HelloService 中的 hello 方法就會自動被調用。
兩個容器
當 Spring 和 SpringMVC 同時出現,我們的項目中將存在兩個容器,一個是 Spring 容器,另一個是 SpringMVC 容器,Spring 容器通過 ContextLoaderListener 來加載,SpringMVC 容器則通過 DispatcherServlet 來加載,這兩個容器不一樣:
從圖中可以看出:
- ContextLoaderListener 初始化的上下文加載的 Bean 是對于整個應用程序共享的,不管是使用什么表現層技術,一般如 DAO 層、Service 層 Bean;
- DispatcherServlet 初始化的上下文加載的 Bean 是只對 Spring Web MVC 有效的 Bean,如 Controller、HandlerMapping、HandlerAdapter 等等,該初始化上下文應該只加載 Web相關組件。
這個是不可能的。因為請求達到服務端后,找DispatcherServlet 去處理,只會去 SpringMVC 容器中找,這就意味著Controller 必須在 SpringMVC 容器中掃描。
2.為什么不在 SpringMVC 容器中掃描所有 Bean?
這個是可以的,可以在SpringMVC 容器中掃描所有 Bean。不寫在一起,有兩個方面的原因:
- 為了方便配置文件的管理
- 在 Spring+SpringMVC+Hibernate 組合中,實際上也不支持這種寫法
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://www.cnblogs.com/qiuwenli/p/13423900.html