Spring MVC 是一种基于 Java 的 Web 框架,它提供了一种基于 MVC(Model-View-Controller)的架构模式,可以帮助开发者更轻松地构建Web应用程序。在本文中,我们将深入探讨 Spring MVC 的启动流程及初始化流程。
加载配置文件:Spring MVC的配置文件一般为 XML 格式,通过 ApplicationContext 来加载配置文件,获取相关的bean。
初始化 DispatcherServlet:DispatcherServlet 是整个 Spring MVC 的核心,它继承了 HttpServlet,实现了对 HTTP 请求的处理和响应。在初始化 DispatcherServlet 时,会调用其 init() 方法,并且为其设置一些参数,例如 SpringMVC 配置文件的位置等。
初始化 HandlerMapping:HandlerMapping负责将请求映射到相应的Controller上,DispatcherServlet在初始化时会初始化HandlerMapping,并将其注册到自己的属性中。
初始化 HandlerAdapter:HandlerAdapter 用于将请求对象转换成 ModelAndView 对象。在初始化时,DispatcherServlet 会根据 HandlerMapping 获取相应的 Controller,并生成相应的 HandlerAdapter。
初始化 ViewResolver:ViewResolver 用于将 ModelAndView 对象渲染成具体的视图(如JSP、HTML等)。在初始化时,DispatcherServlet 会根据 ViewResolver 的配置,生成相应的ViewResolver 对象。
启动 Spring MVC:DispatcherServlet 在初始化完成后,会监听HTTP请求,并将请求分发到相应的 Controller上 进行处理。处理完成后,将 ModelAndView 对象交给 ViewResolver 进行渲染。
Spring MVC 的配置文件一般为 XML 格式,可以在 web.xml 中配置。在配置文件中,需要声明 DispatcherServlet,并指定 Spring MVC 的配置文件位置。例如:
<servlet>
<servlet-name>dispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring-mvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
这里配置了一个名为 dispatcherServlet 的 Servlet,并将其映射到 “/” 路径下。同时指定了 Spring MVC 的配置文件位置为 classpath:spring-mvc.xml。
DispatcherServlet 是整个 Spring MVC 的核心,它继承了 HttpServlet,实现了对 HTTP 请求的处理和响应。在初始化DispatcherServlet 时,会调用其init()方法,并且为其设置一些参数,例如Spring MVC配置文件的位置等。具体的初始化过程可以参考DispatcherServlet的源码:
public void init(ServletConfig config) throws ServletException {
// ...
try {
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
catch (ServletException ex) {
logger.error("Context initialization failed", ex);
throw ex;
}
catch (RuntimeException ex) {
logger.error("Context initialization failed", ex);
throw ex;
}
// ...
}
protected WebApplicationContext initWebApplicationContext() {
// ...
// 加载配置文件,创建ApplicationContext
ConfigurableWebApplicationContext wac = new XmlWebApplicationContext();
wac.setServletContext(getServletContext());
wac.setConfigLocation(getConfigLocation());
// ...
// 设置DispatcherServlet的父容器为ApplicationContext
wac.setParent(applicationContext);
// ...
wac.refresh();
// ...
return wac;
}
可以看出,DispatcherServlet 的初始化过程主要包括两个步骤:加载配置文件,创建 ApplicationContext,并设置 DispatcherServlet 的父容器为 ApplicationContext。
HandlerMapping 负责将请求映射到相应的 Controller 上,DispatcherServlet 在初始化时会初始化 HandlerMapping,并将其注册到自己的属性中。Spring MVC 提供了多种 HandlerMapping,包括:
BeanNameUrlHandlerMapping:将请求 URL 与 Handler Bean 的名称进行映射。
SimpleUrlHandlerMapping:将请求 URL 与 Handler 对象进行映射。
DefaultAnnotationHandlerMapping:将带有 @Controller 注解的类进行映射。
RequestMappingHandlerMapping:将带有 @RequestMapping 注解的方法进行映射。
在初始化时,DispatcherServlet 会根据配置文件中的内容,生成相应的 HandlerMapping,并将其注册到自己的属性中。例如:
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello">helloControllerprop>
props>
property>
bean>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
这里配置了三个 HandlerMapping:BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping 和 RequestMappingHandlerMapping。
HandlerAdapter 用于将请求对象转换成 ModelAndView 对象。在初始化时,DispatcherServlet 会根据 HandlerMapping 获取相应的Controller,并生成相应的 HandlerAdapter。Spring MVC 提供了多种 HandlerAdapter,包括:
SimpleControllerHandlerAdapter:用于处理实现了 Controller 接口的 Controller。
HttpRequestHandlerAdapter:用于处理实现了 HttpRequestHandler 接口的 Controller。
AnnotationMethodHandlerAdapter:用于处理带有 @RequestMapping注解的方法。
在初始化时,DispatcherServlet 会根据 HandlerMapping 获取相应的 Controller,并生成相应的 HandlerAdapter。例如:
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
这里配置了三个 HandlerAdapter:SimpleControllerHandlerAdapter、HttpRequestHandlerAdapter 和 AnnotationMethodHandlerAdapter。
ViewResolver 用于将 ModelAndView 对象渲染成具体的视图(如JSP、HTML等)。在初始化时,DispatcherServlet 会根据 ViewResolver 的配置,生成相应的 ViewResolver 对象。Spring MVC 提供了多种 ViewResolver,包括:
InternalResourceViewResolver:将视图名称解析为 JSP 文件。
VelocityViewResolver:将视图名称解析为 Velocity 模板文件。
FreeMarkerViewResolver:将视图名称解析为 FreeMarker 模板文件。
TilesViewResolver:将视图名称解析为 Tiles 视图定义。
在初始化时,DispatcherServlet 会根据 ViewResolver 的配置,生成相应的 ViewResolver 对象。例如:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
bean>
这里配置了一个InternalResourceViewResolver 对象,它将视图名称解析为 JSP 文件。具体的解析过程可以参考 InternalResourceViewResolver 的源码:
public View resolveViewName(String viewName, Locale locale) throws Exception {
// ...
// 将视图名称解析为JSP文件
String resourcePath = this.prefix + viewName + this.suffix;
// ...
return new InternalResourceView(resourcePath);
}
可以看出,InternalResourceViewResolver 的 resolveViewName 方法将视图名称解析为 JSP 文件,并返回一个 InternalResourceView 对象。
在初始化完成后,DispatcherServlet 会监听 HTTP 请求,并将请求分发到相应的 Controller 上进行处理。处理完成后,将 ModelAndView 对象交给 ViewResolver 进行渲染。具体的处理流程可以参考 DispatcherServlet 的源码:
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
// ...
// 将请求分发给相应的Controller进行处理
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// ...
// 执行Controller的方法,处理请求
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// ...
// 将ModelAndView对象交给ViewResolver进行渲染
render(mv, processedRequest, response);
// ...
}
可以看出,DispatcherServlet 的 doService 方法会将请求分发给相应的 Controller 进行处理,处理完成后,将 ModelAndView 对象交给 ViewResolver 进行渲染。
今天我们先对启动流程有个初步的认识,在后面的篇章中,我们将详细了解每个步骤中对应的类型都有哪些功能。