SPRINGMVC Source Code Analysis (ii) how the request is forwarded to the corresponding controller

Source: Internet
Author: User
Tags constructor http request mutex

In the previous analysis of Dispatcherservlet, how to deal with the request after the beginning, this article will focus on the analysis, handlermapping and handleradapter how to work

In the process of launching the Web container, the classes required for a series of SPRINGMVC are initially initialized, and here we look at the Inithandlermethods method of the Abstracthandlermethodmapping class.



If the bean has the corresponding annotation detection handlermethod


Concrete look at the implementation of Selectmethods method

And the inspect method calls the Getmappingformethod method to implement the implementation by its subclass requestmappinghandlermapping

Protected Requestmappinginfo Getmappingformethod (method, class<?> handlertype) {
		requestmappinginfo Info = Createrequestmappinginfo (method);
		if (info! = null) {
			Requestmappinginfo typeinfo = Createrequestmappinginfo (handlertype);
			if (typeinfo! = null) {
				info = typeinfo.combine (info);}
		}
		return info;
	}

This method returns an instance of the Requestmappinginfo class, which shows that the T type in our previous methods map is Requestmappinginfo

This class is a class that encapsulates the various request-mapping criteria and implements the Requestcondition interface. There are various Requestcondition implementation class properties, Patternscondition,methodscondition,paramscondition,headerscondition, Consumescondition and Producescondition, please.
The condition depends on the property name, which represents the path pattern, method, parameter, and header of the HTTP request, respectively.

Continue to see the Getmappingformethod method, the specific implementation of Createrequestmappinginfo is as follows:

Private Requestmappinginfo Createrequestmappinginfo (annotatedelement Element) {
		requestmapping requestmapping = Annotatedelementutils.findmergedannotation (element, requestmapping.class);
		requestcondition<?> condition = (element instanceof class<?>?
				) Getcustomtypecondition ((class<?>) Element): Getcustommethodcondition (Method) element);
		Return (requestmapping! = null? createrequestmappinginfo (requestmapping, condition): null);
	}
First find the @requestmapping annotation of the method, then get requestcondition, if there is an annotation, call the concrete creation method, otherwise return null

Protected Requestmappinginfo createrequestmappinginfo (
			requestmapping requestmapping, requestcondition<? > customcondition) {

		return requestmappinginfo
				. Paths (Resolveembeddedvaluesinpatterns ( Requestmapping.path ()))
				. Methods (Requestmapping.method ()).
				params (Requestmapping.params ())
				. Headers (requestmapping.headers ())
				. Consumes (Requestmapping.consumes ())
				. produces ( Requestmapping.produces ())
				. MappingName (Requestmapping.name ()).
				customcondition (customcondition)
				. Options (This.config)
				. Build ();
	}
In addition to pathcondithion others are directly using the condition in the requestmapping annotation


Look back and see the Registerhandlermethod method


The URL-related operations are registered to this end


Look back. The call to GetHandler in the Dodispatch method will eventually call the Gethandlerinternal method, specifically:

Protected Handlermethod gethandlerinternal (HttpServletRequest request) throws Exception {
		String Lookuppath = Geturlpathhelper (). Getlookuppathforrequest (request);
		if (logger.isdebugenabled ()) {
			logger.debug ("Looking up handler method for path" + Lookuppath);
		}
		This.mappingRegistry.acquireReadLock ();
		try {
			Handlermethod Handlermethod = Lookuphandlermethod (Lookuppath, request);
			if (logger.isdebugenabled ()) {
				if (handlermethod! = null) {
					Logger.debug ("Returning handler method [" + Handlerme Thod + "]");
				}
				else {
					Logger.debug ("Didn't not find handler method for [" + Lookuppath + "]");
				}
			}
			Return (Handlermethod! = null? Handlermethod.createwithresolvedbean (): null);
		}
		finally {
			this.mappingRegistry.releaseReadLock ();
		}
	}
The key code is to get Handlermethod by calling Lookuphandlermethod



The above is based on the controller method of mapping requestmappinghandlermapping, about the static resource mapping here is not to be described in detail, the corresponding handlermpping is simpleurlhandlermapping


Handlerexecutionchain Executionchain = Gethandlerexecutionchain (handler, request);
Build Handlerexecutionchain with Handler and request

Protected Handlerexecutionchain Gethandlerexecutionchain (Object handler, HttpServletRequest request) {
		Handlerexecutionchain chain = (Handler instanceof handlerexecutionchain?
				) (Handlerexecutionchain) Handler:new Handlerexecutionchain (handler));

		String Lookuppath = this.urlPathHelper.getLookupPathForRequest (request);
		for (Handlerinterceptor interceptor:this.adaptedInterceptors) {
			if (Interceptor instanceof Mappedinterceptor) { C5/>mappedinterceptor mappedinterceptor = (mappedinterceptor) interceptor;
				if (Mappedinterceptor.matches (Lookuppath, This.pathmatcher)) {
					Chain.addinterceptor ( Mappedinterceptor.getinterceptor ());
				}
			}
			else {
				chain.addinterceptor (Interceptor);
			}
		}
		return chain;
	}

handleradapter Access and how it works

Also in Dodispatch we get handleradapter through handler.

Handleradapter ha = Gethandleradapter (Mappedhandler.gethandler ());

Protected Handleradapter Gethandleradapter (Object handler) throws Servletexception {for
   (Handleradapter ha: This.handleradapters) {
      if (logger.istraceenabled ()) {
         Logger.trace ("Testing handler adapter [" + Ha + "]");
      }
      if (Ha.supports (handler)) {
         return ha;
      }
   }
   throw new Servletexception ("No Adapter for Handler [" + Handler +
         "]: the Dispatcherservlet configuration needs Clude a handleradapter that supports this handler ");
}

The handleradapters used here is initialized in the private void Inithandleradapters (ApplicationContext context) method, The general idea is to find all instances of the class that implement the Handleradapter interface and put it in the list.
We use the Requestmappinghandleradapter instance to analyze the corresponding supports method as the parent class Abstracthandlermethodadapter method:

Public Final Boolean supports (Object handler) {
		return (handler instanceof Handlermethod && supportsinternal ((Handlermethod) handler));
	}
Implement Supportsinternal in Requestmappinghandleradapter:

Protected Boolean supportsinternal (Handlermethod handlermethod) {
		return true;
	}

You can see that Requestmappinghandleradapter is an adaptation call to all Handlermethod


Back to Dodispatch

MV = Ha.handle (processedrequest, Response, Mappedhandler.gethandler ());

The implementation of the handler call core method Handleinternal is:

Protected Modelandview handleinternal (httpservletrequest request,
			httpservletresponse response, Handlermethod Handlermethod) throws Exception {

		checkrequest (request);

		if (Getsessionattributeshandler (Handlermethod). Hassessionattributes ()) {
			Applycacheseconds (response, this.cachesecondsforsessionattributehandlers);
		}
		else {
			prepareresponse (response);
		}

		Execute Invokehandlermethod in synchronized block if required.
		if (this.synchronizeonsession) {
			HttpSession session = Request.getsession (false);
			if (session! = null) {
				Object mutex = Webutils.getsessionmutex (session);
				Synchronized (mutex) {
					return Invokehandlermethod (Request, response, Handlermethod);

		}} return Invokehandlermethod (Request, response, Handlermethod);
	}

A lot of content, we just need to focus on Invokehandlermethod

Protected Modelandview Invokehandlermethod (httpservletrequest request, httpservletresponse response, Handlermethod

		Handlermethod) throws Exception {servletwebrequest webRequest = new Servletwebrequest (request, response);
		Webdatabinderfactory binderfactory = getdatabinderfactory (Handlermethod);

		Modelfactory modelfactory = Getmodelfactory (Handlermethod, binderfactory);
		Servletinvocablehandlermethod Invocablemethod = Createinvocablehandlermethod (Handlermethod);
		Invocablemethod.sethandlermethodargumentresolvers (this.argumentresolvers);
		Invocablemethod.sethandlermethodreturnvaluehandlers (this.returnvaluehandlers);
		Invocablemethod.setdatabinderfactory (binderfactory);

		Invocablemethod.setparameternamediscoverer (This.parameternamediscoverer);
		Modelandviewcontainer Mavcontainer = new Modelandviewcontainer ();
		Mavcontainer.addallattributes (Requestcontextutils.getinputflashmap (request));
		Modelfactory.initmodel (WebRequest, Mavcontainer, Invocablemethod); Mavcontainer.Setignoredefaultmodelonredirect (This.ignoredefaultmodelonredirect);
		Asyncwebrequest asyncwebrequest = webasyncutils.createasyncwebrequest (request, response);

		Asyncwebrequest.settimeout (this.asyncrequesttimeout);
		Webasyncmanager Asyncmanager = Webasyncutils.getasyncmanager (request);
		Asyncmanager.settaskexecutor (This.taskexecutor);
		Asyncmanager.setasyncwebrequest (asyncwebrequest);
		Asyncmanager.registercallableinterceptors (this.callableinterceptors);

		Asyncmanager.registerdeferredresultinterceptors (this.deferredresultinterceptors);
			if (Asyncmanager.hasconcurrentresult ()) {Object result = Asyncmanager.getconcurrentresult ();
			Mavcontainer = (Modelandviewcontainer) asyncmanager.getconcurrentresultcontext () [0];
			Asyncmanager.clearconcurrentresult ();
			if (logger.isdebugenabled ()) {Logger.debug ("Found Concurrent result value [" + Result + "]");
		} Invocablemethod = Invocablemethod.wrapconcurrentresult (result); } invocablemethod.invokeandhandle (WebrequeSt, Mavcontainer);
		if (asyncmanager.isconcurrenthandlingstarted ()) {return null;
	} return Getmodelandview (Mavcontainer, Modelfactory, webRequest);
 }

In this method, the Servletinvocablehandlermethod object is created according to Handlermethod, and the corresponding Resovler is set during the execution of the method.

Then call Invokeandhandle:

public void Invokeandhandle (Servletwebrequest webRequest, Modelandviewcontainer Mavcontainer, Object ... Providedargs) throws Exception {//Execute request and return result Object returnvalue = Invokeforrequest (webrequ
		EST, mavcontainer, Providedargs);

		Setresponsestatus (webRequest); if (returnvalue = = null) {if (isrequestnotmodified (webRequest) | | | hasresponsestatus () | | mavcontainer.isrequesthandled
				()) {mavcontainer.setrequesthandled (true);
			Return
			}} else if (Stringutils.hastext (This.responsereason)) {mavcontainer.setrequesthandled (true);
		Return
		} mavcontainer.setrequesthandled (FALSE); try {this.returnValueHandlers.handleReturnValue (returnvalue, Getreturnvaluetype (returnvalue), Mavcontainer, WEBR
		Equest); } catch (Exception ex) {if (logger.istraceenabled ()) {Logger.trace (Getreturnvaluehandlingerrormessage ("Error ha
			ndling return value ", returnvalue), ex);
		} throw ex; }
	}
You can see that the first line calls Invokeforrequest execution request

public Object Invokeforrequest (nativewebrequest request, Modelandviewcontainer Mavcontainer,
			object ... Providedargs) throws Exception {

		object[] args = getmethodargumentvalues (Request, Mavcontainer, Providedargs);
		if (logger.istraceenabled ()) {
			logger.trace ("invoking" + Classutils.getqualifiedmethodname (GetMethod (), Getbeantype ()) +
					"' with arguments" + arrays.tostring (args);
		}
		Object returnvalue = Doinvoke (args);
		if (logger.istraceenabled ()) {
			logger.trace ("Method [" + Classutils.getqualifiedmethodname (GetMethod (), Getbeantype ()) +
					"] returned [" + ReturnValue + "]");
		return returnvalue;
	}

Continue with the Doinvoke method, for the above request parameter parsing the next blog will be analyzed, this article only analysis method call



Among the Getbridgedmethod are:

Protected Method Getbridgedmethod () {
		return this.bridgedmethod;
	}
And our bridgedmethod is what, do not know that everyone has noticed, in the previous I mentioned the creation of Servletinvocablehandlermethod instance

Servletinvocablehandlermethod Invocablemethod = Createinvocablehandlermethod (Handlermethod);

The Createinvocablehandlermethod is a good call to the Servletinvocablehandlermethod Handlermethod parameter constructor, and will eventually call the Handlermethod constructor:

Protected Handlermethod (Handlermethod handlermethod) {
		assert.notnull (Handlermethod, "Handlermethod is required" );
		This.bean = Handlermethod.bean;
		This.beanfactory = handlermethod.beanfactory;
		This.beantype = Handlermethod.beantype;
		This.method = Handlermethod.method;
		This.bridgedmethod = Handlermethod.bridgedmethod;
		This.parameters = handlermethod.parameters;
		This.responsestatus = Handlermethod.responsestatus;
		This.responsestatusreason = Handlermethod.responsestatusreason;
		This.resolvedfromhandlermethod = Handlermethod.resolvedfromhandlermethod;
	}

There is the assignment of Bridgedmethod, and it should be clear how adapter is calling our controller.


This section focuses on the working principles and processes of requestmappinghandlermapping and requestmappinghandleradapter.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.