Springmvc 作为使用最为广泛的web框架,它已取代Struts2,成为Java Web领域的不二霸主;作为一名后台开发人员,熟悉它的启动流程不仅有助于我们了解springmvc框架,更能帮助我们解决很多开发中遇到的问题。
Springmvc也是基于Servlet,所以的入口也是一个Servlet即GenericServlet,框架启动时会调用init方法,进行初始化,它其实是执行的是HttpServletBean的init方法,然后会调用FrameworkServlet的initervletBean,进行SpringWeb容器的初始化
进行WebApplicationContext初始化时会触发DispatcherServlet的onfresh方法,进行SpringMVC框架的初始化,做了9件事,完成整个MVC环境的初始化
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* Initialize the strategy objects that this servlet uses.
* 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);
}
这9件事分别完成了以下事情:
initMultipartResolver(context):用于处理文件上传,如果有文件上传,会将当前的HttpServletRequest包装成DefaultMultipartHttpServletRequest,并将上传的内容封装成CommonsMultipartFile对象;
initLocaleResolver(context):处理应用的国际化问题;
initThemeResolver(context):用于定义一个主题,如:根据用户的喜好设置用户访问的页面的样式;
initHandlerMappings(context):定义用户设置的请求映射关系;
initHandlerAdapters(context):根据Handler的类型定义不同的处理规则;
initHandlerExceptionResolvers(context):当Handler出错时,会通过这个Handler来统一处理,默认实现类是SimpleMappingExceptionResolver,将错误日志记录在log文件中,并转到默认的错误页面;
initRequestToViewNameTranslator(context):将指定的ViewName按照定义的RequestToViewNameTranslator替换成想要的格式,如加上前缀或者后置;
initViewResolvers(context):用于将View解析成页面,可在ViewResolvers中设置多个解析策略;
initFlashMapManager(context):用于准备DispatcherServlet处理请求时所使用的FlashMapManager
策略组件对象。
至此,SpringMVC的环境准备完成,下面就可以接收我们的Http请求了,下面看看SpringMVC处理Http的流程,http请求会通过DispatcherServlet的doService进行处理,在doService中会将框架初始化时设置的handler和view处理对象设置到HttpServletRequest对象中,之后会调用核心处理方法doDispatcher
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
Map attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap();
Enumeration> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// Make framework objects available to handlers and view objects.
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try {
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
在doDispatch方法中主要做完成几个步骤:
(1)请求HandlerMapping查找Handler,返回包含具体的处理器handler和多个拦截器的HandlerExecutionChain对象(getHandler方法)
(2) 根据request对象获取合适的处理器适配器,然后调用拦截器的前置处理方法
(3) 调用处理器适配器去执行Handler,完成后返回视图对象
(4) 调用拦截器的后置处理方法
(5) 进行视图解析(processDispatcherResult方法),并向前端控制器返回View
(6) 在DispatcherServlet返回结果之前会执行拦截器的afterCompletion防范
(7) 前端控制器向用户响应结果
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
SpringMVC框架做为主流web框架,继承了spring框架的优秀设计理念,提供了许多可扩展接口,方便用户自定义扩展,但是想要深入理解它还是需要多阅读它的源码,了解它架构设计理念,学习之路还很漫长,共勉。