DispatcherServlet初始化過程
可以看到有幾個生命週期介面:
-
ApplicationContextAware:儲存了spring上下文
public interface ApplicationContextAware extends Aware { //上下文初始化完成後被呼叫 void setApplicationContext(ApplicationContext applicationContext) throws BeansException; } #org.springframework.web.servlet.FrameworkServlet //儲存SpringMVC上下文 當通過Spring裝載DispatchServlet時會被呼叫 @Override public void setApplicationContext(ApplicationContext applicationContext) { if (this.webApplicationContext == null && applicationContext instanceof WebApplicationContext) { this.webApplicationContext = (WebApplicationContext) applicationContext; this.webApplicationContextInjected = true; } } 複製程式碼
-
EnvironmentAware:儲存了環境變數物件
public interface EnvironmentAware extends Aware { //環境變數物件初始化完成後被呼叫 void setEnvironment(Environment environment); } #org.springframework.web.servlet.HttpServletBean @Override public void setEnvironment(Environment environment) { Assert.isInstanceOf(ConfigurableEnvironment.class, environment, "ConfigurableEnvironment required"); this.environment = (ConfigurableEnvironment) environment; } 複製程式碼
-
Servlet:Servlet生命週期
public interface Servlet { //serlvet初始化 public void init(ServletConfig config) throws ServletException; public ServletConfig getServletConfig(); public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; public String getServletInfo(); //serlvet銷燬 public void destroy(); } #org.springframework.web.servlet.HttpServletBean @Override public final void init() throws ServletException { ... initServletBean(); } @Override public void destroy() { if (this.webApplicationContext instanceof ConfigurableApplicationContext && !this.webApplicationContextInjected) { //銷燬上下文 ((ConfigurableApplicationContext) this.webApplicationContext).close(); } } #org.springframework.web.servlet.FrameworkServlet DispatcherServlet extends FrameworkServlet #org.springframework.web.servlet.FrameworkServlet @Override protected final void initServletBean() throws ServletException { ... try { this.webApplicationContext = initWebApplicationContext(); initFrameworkServlet(); } ... } protected WebApplicationContext initWebApplicationContext() { WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; ... //以spring配置方式時webApplicationContext!=null if (this.webApplicationContext != null) { wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; cwac.setParent(rootContext); } } } if (wac == null) { //建立applicationContext wac = createWebApplicationContext(rootContext); } ... return wac; } protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) { //XmlWebApplicationContext Class<?> contextClass = getContextClass(); ... //建立applicationContext ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); wac.setEnvironment(getEnvironment()); //設定parent(ContextLoadListener中建立的applicationContext) wac.setParent(parent); //讀取contextConfigLocation配置 wac.setConfigLocation(getContextConfigLocation()); //refresh() configureAndRefreshWebApplicationContext(wac); return wac; } //當SpringMVC上下初始化完成後會去裝載預設策略(HandlerMapping,HandleAdapter) protected void initStrategies(ApplicationContext context) { //獲取容器中是否有其實現 沒有則載入DispatcherServlet.properties中的預設實現 initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); } 複製程式碼
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\ org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager 複製程式碼
DispatcherServlet呼叫過程
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
//將相關配置設定到request作用於中
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());
...
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try {
doDispatch(request, response);
}
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//1.呼叫handlerMapping獲取handlerChain
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// 2.獲取支援該handler解析的HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//前置處理(CORS時用到)
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 3.使用HandlerAdapter完成handler處理
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//如果是非同步請求 直接返回
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(request, mv);
//後置處理
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
//4.異常處理,檢視解析,渲染返回
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
...
}
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
boolean errorView = false;
//如果HandlerAdapter.handler()執行異常 則進行異常處理
if (exception != null) {
...
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
//4.1
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
if (mv != null && !mv.wasCleared()) {
//4.2 檢視解析 渲染返回
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
}
//異常處理
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
ModelAndView exMv = null;
for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
//使用異常解析器解析異常(類似HandlerAdapter引數解析,呼叫)
exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
...
}
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
//國際化
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale);
View view;
if (mv.isReference()) {
//4.2.1檢視解析
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
...
}
else {
view = mv.getView();
}
....
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
//渲染返回
view.render(mv.getModelInternal(), request, response);
}
...
}
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
HttpServletRequest request) throws Exception {
//檢視解析
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
return null;
}
複製程式碼
過程概括:
- 呼叫HandlerMapping得到HandlerChain(Handler+Intercept)
- 呼叫HandlerAdapter執行handle過程(引數解析 過程呼叫)
- 異常處理(過程類似HanderAdapter)
- 呼叫ViewResolver進行檢視解析
- 渲染檢視
上述圖片來自網路