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返回,完成响应。