DispatcherServlet初始化
- HttpServletBean继承HttpServlet,因此在Web容器启动时将调用它的init方法,该初始化方法的主要作用是将Servlet初始化参数(init-param)设置到该组件上(如contextAttribute、contextClass、namespace、contextConfigLocation),通过BeanWrapper简化设值过程,方便后续使用。并提供给子类初始化扩展点,initServletBean(),该方法由FrameworkServlet覆盖。
1 | public abstract class HttpServletBean extends HttpServlet implements EnvironmentAware{ |
- FrameworkServlet继承HttpServletBean,通过initServletBean()进行Web上下文初始化,该方法主要覆盖一下两件事情
- 初始化web上下文
- 提供给子类初始化扩展点从initWebApplicationContext()方法可以看出,基本上如果ContextLoaderListener加载了上下文,该上下文将作为DispatcherServlet的根上下文(DispatcherServlet的父容器)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53public abstract class FrameworkServlet extends HttpServletBean {
@Override
protected final void initServletBean() throws ServletException {
//省略部分代码
try {
//1、初始化Web上下文
this.webApplicationContext = initWebApplicationContext();
//2、提供给子类初始化的扩展点
initFrameworkServlet();
}
//省略部分代码
}
}
protected WebApplicationContext initWebApplicationContext() {
//ROOT上下文(ContextLoaderListener加载的)
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
// 1、在创建该Servlet注入的上下文
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
//2、查找已经绑定的上下文
wac = findWebApplicationContext();
}
if (wac == null) {
//3、如果没有找到相应的上下文,并指定父亲为ContextLoaderListener
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
//4、刷新上下文(执行一些初始化)
onRefresh(wac);
}
if (this.publishContext) {
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
//省略部分代码
}
return wac;
}
最后调用了onRefresh()方法执行容器的一些初始化,这个方法由子类实现,来进行扩展。
- DispatcherServlet继承FrameworkServlet,并实现了onRefresh()方法提供一些前端控制器相关的配置
1 | public class DispatcherServlet extends FrameworkServlet { |
从如上代码可以看出,DispatcherServlet启动时会进行我们需要的Web层Bean的配置,如HandlerMapping、HandlerAdapter等,而且如果我们没有配置,还会给我们提供默认的配置。
- 初始化总结
从如上代码我们可以看出,整个DispatcherServlet初始化的过程和做了些什么事情,具体主要做了如下两件事情:
- 初始化Spring Web MVC使用的Web上下文,并且可能指定父容器为(ContextLoaderListener加载了根上下文)
- 初始化DispatcherServlet使用的策略,如HandlerMapping、HandlerAdapter等。
DispatcherServlet默认配置
DispatcherServlet的默认配置在DispatcherServlet.properties(和DispatcherServlet类在一个包下)中,而且是当Spring配置文件中没有指定配置时使用的默认策略。DispatcherServlet在启动时会自动注册这些特殊的Bean,无需我们注册,如果我们注册了,默认的将不会注册。
DispatcherServlet的请求分派处理
- 文件上传解析,如果请求类型是mutilpart将通过MultipartpartResolver进行文件上传解析。
- 将请求通过HandlerMapping映射成HandlerExecutionChain(包含一个Handler和多个拦截器)
- 将HandlerExecutionChain通过HandlerAdapter适配支持多种处理器。
- 通过适配器调用用户定义的处理器的逻辑,返回ModelAndView
- 通过ViewResolver解析逻辑视图名到具体实现。
- 本地化解析
- 如果执行过程中遇到异常,则交给HandlerExceptionResolver来解析。
主要接口
- HandlerMapping:处理器映射器
- HandlerAdapter:处理器适配器
- ViewResolver:视图解析器(InternalResourceViewResolver)
- MultipartResolver:文件上传解析器
- HandlerExceptionResolver: 处理器异常解析器
- HandlerExecutionChain:包装用户处理器Handler + 多个处理器拦截器
- HandlerInterceptor: 处理器拦截器
1 | //前端控制器分派方法 |