DispatcherServlet 的作用
DispatcherServlet是前端控制器设计模式的实现,提供 SpringWebMVC 的集中访问点,负责职责的分派,与 SpringIoC 容器可以无缝集成,从而可以获得 Spring 的所有能力。
DispatcherServlet 主要用作职责调度工作,本身主要用于控制流程,主要职责如下:
1:文件上传解析,如果请求类型是 multipart 将通过 MultipartResolver 进行文件上传解析
2:通过HandlerMapping,将请求映射到处理器(返回一个 HandlerExecutionChain,它包括一个处理器、多个 HandlerInterceptor 拦截器)
3:通过 HandlerAdapter 支持多种类型的处理器(HandlerExecutionChain 中的处理器)
4:通过 ViewResolver 解析逻辑视图名到具体视图实现
5:本地化解析
6:渲染具体的视图
7:如果执行过程中遇到异常将交给 HandlerExceptionResolver 来解析
DispatcherServler 的配置
DispatcherServlet 也可以配置自己的初始化参数,也就是 servlet 配置中可以配置<init-param>
参数 | 描述 |
contextClass | 实现 WebApplicationContext 接口的类,当前的 servlet 用它来创建上下文。如果这个参数没有指定,默认使用 XmlWebApplicationContext |
contextConfigLocation | 传给上下文实例(由 contextClass 指定)的字符串,用来指定上下文的位置。这个字符串可以被分成多个字符串(使用逗号作为分隔符)来支持多个上下文(在有多个上下文的情况下,如果同一个 bean 被定义两次,后面一个优先) |
namespace | 命名空间。默认值是 [servlet-name]-servlet |
上下文关系
SpringWeb 项目通用上下文配置如下:
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
contextConfigLocation:表示用于加载 Bean 的配置文件路径;
contextClass:表示用于加载 Bean 的 ApplicationContext 实现类,默认 WebApplicationContext
DispatcherServlet 的初始化顺序
1:HttpServletBean 继承 HttpServlet,因此在 Web 容器启动时将调用它的 init 方法
2:FrameworkServlet 继承 HttpServletBean,通过 initServletBean() 进行 Web 上下文初始化
3:DispatcherServlet 继承 FrameworkServlet,并实现了 onRefresh() 方法提供一些前端控制器相关的配置
在 SpringMVC 框架 DispatcherServlet 中的第 470 行左右:
/**
* This implementation calls {@link #initStrategies}.
*/
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
整个 DispatcherServler 初始化的过程具体主要做了两件事情:
- 初始化 SpringMVC 使用的 Web 上下文,并且可能指定父容器(ContextLoaderListener 加载了根上下文)
- 初始化 DispatcherServlet 使用的策略,如 HandlerMapping、HandlerAdapter 等
DispatcherServler 的默认配置:
DispatcherServlet 的默认配置在 DispatcherServlet.properties(和 DispatcherServlet 类在一个包下)中,而且是当 Spring 配置文件中没有指定配置时使用的默认策略;
从配置可以看出 DispatcherServlet 在启动时会自动注册这些特殊的 Bean,无需我们注册,如果我们注册了,默认的将不会注册。
DispatcherServlet 中的特殊 Bean
DispatcherServlet 默认使用 WebApplicationContext 作为上下文,该上下文中有以下的一些 Bean:
Controller
处理器/页面控制器,做的是 MVC 中的 C 的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;
HandlerMapping
请求到处理器的映射,如果映射成功返回一个 HandlerExecutionChain 对象(包含一个 Handler 处理器(页面处理器)对象、多个 HandlerInterceptor 拦截器);如BeanNameUrlHandlerMapping 将 URL 与 Bean 名字映射,映射成功的 Bean 就是此处的处理器;
HandlerAdapter:
HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;如 SimpleControllerHandlerAdapter 将对实现了 Controller 接口的 Bean 进行适配,并且调用处理器的 handleRequest 方法进行功能处理;
ViewResolver
ViewResolver 将把逻辑视图名解析为具体的 View,如InternalResourceViewResoulver 将逻辑视图名映射为 jsp 视图;
LocalResolver
本地化解析,因为 Spring 支持国际化,因此 LocaleResolver 解析客户端的 Locale 信息从而方便进行国际化;
ThemeResolver
主题解析,通过它来实现一个页面多套风格,即常见的类似于软件皮肤效果;
MultipartResolver
文件上传解析,用于支持文件上传;
HandlerExceptionResolver
处理器异常解析,可以将异常映射到相应的同意错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);
RequestToViewNameTranslator
当处理器没有返回逻辑视图名等相关信息时,自动将请求 URL 映射为逻辑视图名;
FlashMapManager
用于管理 FlashMap 的策略接口,FlashMap 用于存储一个请求的输出,当进入另一个请求时作为该请求的输入,通常用于重定向场景。
Controller 简介
Controller 控制器,是 MVC 中的部分 C,主要负责功能处理部分
1、收集、验证请求参数并绑定到命令对象
2、将命令对象交给业务对象,由业务对象处理并返回模型数据
3、返回 ModelAndView(Model 部分是业务对象返回的模型数据,视图部分为逻辑视图名)
DisaptcherServler + Controller
DispatcherServlet 负责将请求委托交给 Controller 进行处理,
再根据 Controller 返回的逻辑视图名选择具体的视图进行渲染(并把模型数据传入)
**MVC 中完整的 C(包含逻辑控制和功能处理)由(DispatcherServlet + Controller)组成
Controller注解
Spring2.5之前,我们都是通过实现 Controller 接口或其实现类来定义我们的处理器类(已不建议使用)。
Spring2.5 引入注解式处理器支持,通过 @Controller 和 @RequestMapping 注解定义处理器类。并且提供了一组强大的注解:
- @Controller
- @RequestMapping
- @RequestParam
- @ModelAttribute
- @SessionAttributes
- @InitBinder
Spring3.0 引入了 Restful 架构风格支持(通过 @PathVariable 注解和一些其他的特性支持),且又引入了更多的注解支持
- @CookieValue
- @RequestHeader
- @RequestBody
- @ResponseStatus
- @ExceptionHandler
- @PathVariable
Spring3.1 使用新的 HandlerMapping 和 HandlerAdapter 来支持 @Controller 和 @RequestMapping 注解处理器,使用处理器映射 RequestMappingHandlerMapping 和处理器适配器 RequestMappingHandlerAdapter 组合来代替 Spring2.5 开始的处理器映射 DefaultAnnotationHandlerMapping 和处理器适配器 AnnotationMethodHandlerAdapter。
注解实现 Controller
HandlerMapping 和 HandlerAdapter 的配置
- Spring3.1 以前的版本:
DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter- Spring3.1 开始的版本:
RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter
示例代码:
代码结构参考:
https://blog.csdn.net/qq_33811662/article/details/80658813
修改 spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<context:component-scan base-package="mvc1"></context:component-scan>
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
修改 HelloController 的内容为:
package mvc1;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class HelloController {
@RequestMapping("/hello")
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("进入后台控制器");
ModelAndView mv = new ModelAndView();
mv.addObject("content", "SpringMVC 初体验");
mv.setViewName("/WEB-INF/jsp/hello.jsp");
return mv;
}
}
运行 Server,进入网址: