4. Request-Process chain mapping (handlermapping)
Handlermapping defines a strategy for mapping between requests and processing chains, as shown in the following interfaces.
Public Interface handlermapping { = handlermapping. Class. GetName () + ". pathwithinhandlermapping"; throws Exception;}
The main inheritance classes and inheritance structures are as follows
which
*abstracthandlermapping: Defines the most basic parts of the handlermapping implementation, including the Interceptor list and the default processing object
*abstracturlhandlermapping: On the basis of abstracthandlermapping, the mapping Relationship Management from URL to processing object is defined, and its main processing process is as follows
Gethandlerinternal:
protectedObject gethandlerinternal (HttpServletRequest request)throwsException {String Lookuppath= This. Urlpathhelper.getlookuppathforrequest (Request); if(logger.isdebugenabled ()) {Logger.debug ("Looking up handler for [" + Lookuppath + "]"); } Object Handler=Lookuphandler (Lookuppath, request); if(Handler = =NULL) { //we need to care for the default handler directly, since we need to//expose the Path_within_handler_mapping_attribute for it as well.Object Rawhandler =NULL; if("/". Equals (Lookuppath)) {Rawhandler=Getroothandler (); } if(Rawhandler = =NULL) {Rawhandler=Getdefaulthandler (); } if(Rawhandler! =NULL) {Validatehandler (rawhandler, request); Handler=Buildpathexposinghandler (Rawhandler, Lookuppath); } } returnhandler; }
Lookuphandler:
protectedObject Lookuphandler (String URLPath, httpservletrequest request)throwsException {//Direct match?Object handler = This. Handlermap.get (URLPath); if(Handler! =NULL) {Validatehandler (handler, request); returnBuildpathexposinghandler (handler, URLPath); } //Pattern match?String Bestpathmatch =NULL; for(Iterator it = This. Handlermap.keyset (). iterator (); It.hasnext ();) {String Registeredpath=(String) it.next (); if(Getpathmatcher (). Match (Registeredpath, URLPath) &&(Bestpathmatch==NULL|| Bestpathmatch.length () <registeredpath.length ())) {Bestpathmatch=Registeredpath; } } if(Bestpathmatch! =NULL) {Handler= This. Handlermap.get (Bestpathmatch); Validatehandler (handler, request); String pathwithinmapping=Getpathmatcher (). Extractpathwithinpattern (Bestpathmatch, URLPath); returnBuildpathexposinghandler (handler, pathwithinmapping); } //No handler found ... return NULL; }
In addition, it defines the handler registration method Registerhandler
*abstractdetectingurlhandlermapping:abstractdetectingurlhandlermapping The Applicationcontextaware interface is implemented by inheriting Applicationobjectsupport and is automatically passed after initialization is completed. Applicationobjectsupport.setapplicationcontext--> Abstractdetectingurlhandlermapping.initapplicationcontext--> Abstractdetectingurlhandlermapping.detecthandlers calls the Detecthandlers function, which checks all bean objects registered to ApplicationContext, The Determineurlsforhandler implemented by its subclasses determine the URL for each Bean object and register the URL with the bean through Abstracturlhandlermapping.registerhandler
protected voidDetecthandlers ()throwsbeansexception {if(logger.isdebugenabled ()) {Logger.debug ("Looking for URL mappings in application context:" +Getapplicationcontext ()); } string[] Beannames= ( This. detecthandlersinancestorcontexts?beanfactoryutils.beannamesfortypeincludingancestors (Getapplicationcontext (), Object.class): Getapplicationcontext (). Getbeannamesfortype (Object.class)); //Take any bean name or alias this begins with a slash. for(inti = 0; i < beannames.length; i++) {String beanname=Beannames[i]; String[] URLs=Determineurlsforhandler (beanname); if(!objectutils.isempty (URLs)) { //URL Paths Found:let ' s consider it a handler.Registerhandler (URLs, beanname); } Else { if(logger.isdebugenabled ()) {Logger.debug ("Rejected Bean name '" + beannames[i] + "': No URL paths identified"); } } } }
*beannameurlhandlermapping: Very simple, it implements the Determineurlsforhandler function, if a bean starts with a "/", it is considered a processor class, and the name of the bean is the URL of the map. The processing process is as follows
protected string[] Determineurlsforhandler (String beanname) {List urls = new ArrayList (); if (Beanname.startswith ("/" = Getapplicationcontext (). getaliases (Beanname); for (int j = 0; J < Aliases.length; J++ if (Aliases[j].startswith ("/" Span style= "color: #000000;" >)) {Urls.add (aliases[j]); }} return Stringutils.tostringarr Ay (URLs); }
*defaultannotationhandlermapping: Implement the Determineurlsforhandler function, examine each Bean object's class or method there is no requestmapping this annotation, if there is , the URL of the corresponding configuration is treated as the URL for that bean, and the process is as follows
protectedstring[] Determineurlsforhandler (String beanname) {ApplicationContext context=Getapplicationcontext (); Class<?> Handlertype =Context.gettype (beanname); Requestmapping Mapping= Annotationutils.findannotation (Handlertype, requestmapping.class); if(Mapping = =NULL&& contextinstanceofConfigurableapplicationcontext &&context.containsbeandefinition (Beanname)) {configurableapplicationcontext CAC=(configurableapplicationcontext) context; Beandefinition BD=cac.getbeanfactory (). Getmergedbeandefinition (Beanname); if(BDinstanceofabstractbeandefinition) {abstractbeandefinition abd=(abstractbeandefinition) BD; if(Abd.hasbeanclass ()) {Class<?> Beanclass =Abd.getbeanclass (); Mapping= Annotationutils.findannotation (Beanclass, requestmapping.class); } } } if(Mapping! =NULL) { //@RequestMapping found at type level This. Cachedmappings.put (handlertype, mapping); Set<String> URLs =NewLinkedhashset<string>(); String[] Paths=Mapping.value (); if(Paths.length > 0) { //@RequestMapping Specifies paths at type level for(String path:paths) {addurlsforpath (URLs, path); } returnStringutils.tostringarray (URLs); } Else { //actual paths specified by @RequestMapping on method level returndetermineurlsforhandlermethods (Handlertype); } } Else if(Annotationutils.findannotation (Handlertype, Controller.)class) !=NULL) { //@RequestMapping to being introspected at method level returndetermineurlsforhandlermethods (Handlertype); } Else { return NULL; } }
5. Processor Adapter (Handleradapter)
Handleradapter defines how the processing class handles the request, as shown in the following interface
Public Interface handleradapter { boolean supports (Object handler); throws Exception; Long getlastmodified (httpservletrequest request, Object handler);}
By implementing a specific policy, you have the flexibility to convert any object into a request processing object, including the following:
1) Simplecontrollerhandleradapter/httprequesthandleradapter/simpleservlethandleradapter/throwawaycontroller
Very simple, oriented to implement the implementation of a particular interface of the processing class situation, just do a proxy execution processing, look at the simplecontrollerhandleradapter of the code below, its specific processing implements the Controller interface processing class
Public classSimplecontrollerhandleradapterImplementsHandleradapter { Public Booleansupports (Object handler) {return(HandlerinstanceofController); } PublicModelandview handle (httpservletrequest request, httpservletresponse response, Object handler)throwsException {return( Controller) handler). HandleRequest (request, response); } Public Longgetlastmodified (httpservletrequest request, Object handler) {if(Handlerinstanceoflastmodified) { return((lastmodified) handler). getlastmodified (Request); } return-1l; }}
2) Annotationmethodhandleradapter
By configuring a specific annotation, you define how the parameters are injected, which method to invoke, and how to handle the return parameters, as follows (Annotationmethodhandleradapter.invokehandlermethod)
Try{servlethandlermethodresolver Methodresolver=Getmethodresolver (handler); Method Handlermethod=Methodresolver.resolvehandlermethod (Request); Servlethandlermethodinvoker MethodInvoker=NewServlethandlermethodinvoker (Methodresolver); Servletwebrequest webRequest=Newservletwebrequest (request, response); Extendedmodelmap Implicitmodel=NewExtendedmodelmap (); Object result=Methodinvoker.invokehandlermethod (Handlermethod, Handler, WebRequest, Implicitmodel); Modelandview Mav=Methodinvoker.getmodelandview (Handlermethod, result, Implicitmodel, webRequest); Methodinvoker.updatesessionattributes (Handler, (Mav!=NULL? Mav.getmodel ():NULL), Implicitmodel, webRequest); returnMav; } Catch(Nosuchrequesthandlingmethodexception ex) {returnHandlenosuchrequesthandlingmethod (ex, request, response); }
*servlethandlermethodresolver (Annotationmethodhandleradapter inner Class): This class is defined by the request URL, request method, and the requestmapping of the processing class. Finally determine which method of the processing class is used to process the request
*servlethandlermethodinvoker (Annotationmethodhandleradapter inner Class): Checks the parameters of the processing class's corresponding processing method and the associated annotation configuration, Determines how the required parameters are converted into the calling method, and the final call returns Modelandview
6. View Policy (Viewresolver)
Viewresolver defines the strategy for determining the View object that handles the views, as shown in the following interface
Public Interface viewresolver { throws Exception;}
SPRINGMVC Source Code Analysis (next)