Spring-DispatcherServlet request processing

Detailed explanation of Spring-DispatcherServlet initialization: http://donald-draper.iteye.com/blog/2325394
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.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327081592&siteId=291194637