SpringMVC最主要的類爲DispatcherServlet,包名爲org.springframework.web.servlet。
該類繼承於FrameworkServlet,FrameworkServlet的類圖如下:
即本質上FrameworkServlet也是一個Servlet,特別的是這個Servlet對應的URI爲*,所有的context path下的請求都會在這個Servlet中處理。
當第一次請求時會執行HttpServletBean類的init方法,其中會讀取相關配置文件並執行FrameworkServlet類中的initServletBean方法:
PropertyValues pvs = new
HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
if (!pvs.isEmpty()) {
try {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));
this.initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
} catch (BeansException var4) {
if (this.logger.isErrorEnabled()) {
this.logger.error("Failed to set bean properties on servlet '" + this.getServletName() + "'", var4);
}
throw var4;
}
}
this.initServletBean();
initServletBean方法會調用initWebApplicationContext方法初始化Web容器,其中會調用DispatcherServlet類的onRefresh方法,onRefresh調用initStrategies開始初始化策略:
protected void initStrategies(ApplicationContext context) {
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
其中會初始化模板解析,url映射關係,異常解析等內容。
所有類型的請求都會通過FrameworkServlet類的processRequest方法進行處理:
protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
processRequest方法則調用DispatcherServlet的doService方法,該方法會進行請求參數處理並調用doDispatch方法開始真正的處理。
在doDispatch方法中,mappedHandler = this.getHandler(processedRequest); 來獲取url和Controller中方法的對應關係,getHandler方法會遍歷初始化時的handlerMappings,並與每個mapping的mappingRegistry中註冊的url進行匹配,下圖爲我的測試代碼匹配過程:
匹配結束後會返回該url匹配的處理方法的信息,例如:
之後調用所有的攔截器的preHandle方法,進行公共處理,處理後調用真正的Controller中代碼,執行結束後調用所有攔截的postHandle方法進行處理:
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
其中handle方法會對返回值做對應的處理,比如將對象轉換爲json字符串,該返回將被轉換爲outputStream並置於response返回,完成響應。