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