Detailed explanation of Spring's DefaultAnnotationHandlerMapping: http://donald-draper.iteye.com/blog/2325453
We have explored the initialization of DispatcherServlet earlier, Let's take a look at how
DispatcherServlet handles web requests
//DispatcherServlet
public class DispatcherServlet extends FrameworkServlet { }
From DispatcherServlet we can't see any request processing entry Let's look at FrameworkServlet
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { public FrameworkServlet(WebApplicationContext webApplicationContext) { contextClass = DEFAULT_CONTEXT_CLASS; contextInitializers = new ArrayList(); publishContext = true; publishEvents = true; threadContextInheritable = false; dispatchOptionsRequest = false; dispatchTraceRequest = false; webApplicationContextInjected = false; refreshEventReceived = false; this.webApplicationContext = webApplicationContext; } //Here we find the method to handle the request, the default method protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String method = request.getMethod(); if(method.equalsIgnoreCase(RequestMethod.PATCH.name())) processRequest(request, response); else super.service(request, response); } //GET protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } //POST protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } //PUT protected final void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } //DELETE protected final void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } // Actual processing request method protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // handle the request doService(request, response); } } //Extension with subclass DispatcherServlet protected abstract void doService(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse) throws Exception; public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet"; public static final Class DEFAULT_CONTEXT_CLASS = org/springframework/web/context/support/XmlWebApplicationContext; public static final String SERVLET_CONTEXT_PREFIX = (new StringBuilder()).append(org/springframework/web/servlet/FrameworkServlet.getName()).append(".CONTEXT.").toString(); private static final String INIT_PARAM_DELIMITERS = ",; \t\n"; private String contextAttribute; private Class contextClass; private String contextId; private String namespace; private String contextConfigLocation; private final ArrayList contextInitializers; private String contextInitializerClasses; private boolean publishContext; private boolean publishEvents; private boolean threadContextInheritable; private boolean dispatchOptionsRequest; private boolean dispatchTraceRequest; private WebApplicationContext webApplicationContext; private boolean webApplicationContextInjected; private boolean refreshEventReceived; }
Let's look at DispatcherServlet
public class DispatcherServlet extends FrameworkServlet { public DispatcherServlet(WebApplicationContext webApplicationContext) { super(webApplicationContext); detectAllHandlerMappings = true; detectAllHandlerAdapters = true; detectAllHandlerExceptionResolvers = true; detectAllViewResolvers = true; throwExceptionIfNoHandlerFound = false; cleanupAfterInclude = true; } // handle the request protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { //Set request attributes, web context, localization, theme request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); FlashMap inputFlashMap = 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, flashMapManager); //Delegate to doDispatch doDispatch(request, response); } protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest; HandlerExecutionChain mappedHandler; boolean multipartRequestParsed; WebAsyncManager asyncManager; processedRequest = request; mappedHandler = null; multipartRequestParsed = false; asyncManager = WebAsyncUtils.getAsyncManager(request); ModelAndView mv; Exception dispatchException; mv = null; dispatchException = null; processedRequest = checkMultipart(request); multipartRequestParsed = processedRequest != request; //Get the controller processor chain mappedHandler = getHandler(processedRequest); HandlerAdapter ha; //Get controller method adapter ha = getHandlerAdapter(mappedHandler.getHandler()); //Get the processing view mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); // return to the view applyDefaultViewName(request, mv); } //Get the controller processor chain protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //List<HashMap<String,HandlerMapping>> for(Iterator iterator = handlerMappings.iterator(); iterator.hasNext();) { HandlerMapping hm = (HandlerMapping)iterator.next(); if(logger.isTraceEnabled()) logger.trace((new StringBuilder()).append("Testing handler map [").append(hm).append("] in DispatcherServlet with name '").append(getServletName()).append("'").toString()); HandlerExecutionChain handler = hm.getHandler(request); if(handler != null) return handler; } } //Get controller method adapter protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { //List<HashMap<String,HandlerAdapter>> for(Iterator iterator = handlerAdapters.iterator(); iterator.hasNext();) { HandlerAdapter ha = (HandlerAdapter)iterator.next(); if(logger.isTraceEnabled()) logger.trace((new StringBuilder()).append("Testing handler adapter [").append(ha).append("]").toString()); if(ha.supports(handler)) return ha; } } private List handlerMappings;//List<HashMap<String,HandlerMapping>>, Key is beanName, value is HandlerMapping instance private List handlerAdapters;//List<HashMap<String,HandlerAdapter>>,Key为beanName,value值为HandlerAdapter实例 private List handlerExceptionResolvers; private List viewResolvers; static { try { //load default configuration file ClassPathResource resource = new ClassPathResource("DispatcherServlet.properties", org/springframework/web/servlet/DispatcherServlet); defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); } } }
Summary:
DispatcherServlet actually processes requests through the Service() and do* class methods of FrameworkServlet,
and the actual processing logic of these methods is in the doService and doDispatch of DispatcherServlet, doDispatch
first finds out the controller processor, and then finds out the controller Method adapters handle specific requests through controller method adapters.