Aperçu
Pour les développeurs Web, le modèle MVC est très familier à tout le monde. Dans SpringMVC, la demande qui remplit les conditions entre dans le Dispatterservlet responsable de la distribution de la demande. Le Dispatcherservlet mappe l'URL de demande au contrôleur (en sauvegarde dans Handlermapping). Handlermapping renvoie enfin le handlerexecutionChain, qui contient le gestionnaire d'objets de traitement spécifique (c'est-à-dire ce que nous avons écrit lorsque nous le programmons). Contrôleur) et une série d'intercepteurs. À l'heure actuelle, le Dispatcherservlet trouvera un HandlerAdapter qui prend en charge ce type de processeur en fonction du gestionnaire du gestionnaire de la HandlereXecutionChain retournée. Dans l'adaptateur de processeur, il appellera éventuellement la méthode de réponse de la demande du contrôleur et renverra la vue de résultats (ModelandView). Après avoir obtenu la vue du résultat, le résultat est affiché via la méthode de rendu.
Système d'héritage de l'hébergement:
SpringMVC demande la distribution au processeur de gestionnaire. Cette étape est résolue à travers le module de mainlentage. Les handlermapping gère également les intercepteurs.
Jetons un coup d'œil à l'arbre héritage de handlermapping en premier
Vous pouvez à peu près faire une classification comme ceci:
1. Une interface handlermapping, définissez une API: handlereXecutionChain Gethandler (demande httpsservletRequest) lance une exception;
2.
3. Utilisation de @Controller, @Requestmapping basé sur l'annotation
4. Configurez le SimpleUrlHandlermapping de l'URL vers le gestionnaire dans le fichier de configuration
5. BeannameUrlHandlerMapping est implémenté par défaut
6. Cartographie des sous-classes de contrôleur
Jetons un coup d'œil à Handlermapping, juste une API Gethandler est très simple.
// handlermappingpackage org.springframework.web.servlet; interface publique handlermapping {handlereXecutionChain gethandler (httpservletRequest request) lève une exception;} L'abstraction-allonger n'est pas si simple
Regardez d'abord la classe héritée par l'abstracthandlermapping et l'interface implémentée
package org.springframework.web.servlet.handler; classe abstraite publique abstracthandlermapping étend webApplicationObjectSupportimplements handlermapping, ordonné {// ...} WebApplicationObjectSupport est utilisé pour fournir un contexte ApplicationContext et ServletContext.
Il y a aussi la méthode InitApplicationContext ici, qui est souvent utilisée à l'avenir. AbstratracthandLermapping est directement remplacé.
Les interfaces ApplicationContextAware et ServletContextaware sont toujours implémentées dans la classe parent, et le concept de printemps est très unifié.
Commandé est utilisé pour le tri de collection.
Continuons à examiner les propriétés de l'abstracthandlermapping
// AbstracThandLermapping // L'ordre affecte la valeur maximale, et la priorité est le plus petit INT privé = Integer.max_value; // par défaut: Identique à celle non commandée // Le gestionnaire par défaut, l'OBEJCT utilisé ici et la sous-classe d'implémentation, utilisent HandlerMethod, HandlereXecutionChain et autres objets privé Defaulthandler; // Classe auxiliaire pour calcul d'URL UrlPathHelper UrlPathHelper = New UrlpathHelper =). Nouveau antpathmatcher (); // Configuration d'interceptor :, Paramètre de propriété handlermapping ;, ExtendInterceptors définir la liste finale privée <Bobile> Interceptors = new ArrayList <Bobile> (); // Analyser à partir d'interceptors et l'ajouter directement à tous les gestionnaires finaux de gestion La correspondance est passée sera utilisée la liste finale privée <mappedInterceptor> mapedInterceptors = new ArrayList <MaptedInterceptor> ();
Découvrez l'initialisation de l'intercepteur:
// AbstrathandLermapping @ OverRideProtected void initApplicationContext () lève BeanSexception {extendInterceptors (this.Interceptors); DetectMappedInterceptors (this.mappinInterceptors); InitIterceptors ();} / *** fourni pour subclasser les intercepteurs d'extension, mais malheureusement, aucun d'entre eux n'est utilisé * / Protected Void Extendcept {} / *** Scannez les MapedInterceptors sous l'application et ajoutez-les à MapPedInterceptors * / Protected void DetectMappedInterceptors (list <mappedInterceptor> mappedInterceptors) {mappedInterceptors.Addall (beanfactoryutils.beansoftypeindedanceStors (GetApplicationContex false) .Values ());} / *** Collectez MapPedInterceptor et adaptez à HandlerInterceptor et WebRequestInterceptor * / Protected void InitInterceptors () {if (! this.Interceptor == null) {lancer un nouveau IllégalArgumentException ("Numéro d'entrée" + i + "dans Interceptors Array est null");} if (Interceptor instance of MapedInterceptor) {mappedInterceptor.Add ((mappedInterceptor) interceptor);} else {adaptedIntercept HandlerInterceptor AdaptInterceptor (objet interceptor) {if (instance interceptorof handlerInterceptor) {return (handlerInterceptor) interceptor;} else if (Interceptor instanceof webRequestInterceptor) {return webrequesthandlerterceptorAdapter (webrequestInterExt Prise en charge: "+ interceptor.getClass (). getName ());}}Ensuite, il y a la mise en œuvre de Gethandler (demande HttpServletRequest), et se réserve également Gethandlerinternal (demande httpservletRequest) pour la mise en œuvre de la sous-classe.
// AbstracthandLermappingPublic final handlerexecutionchain Gethandler (httpsservletRequest request) lève une exception {objet handler = gethandlerinternal (request); if (handler == null) {handler = getDefaulthandler ();} if (handler == null) {retour nul instanceof String) {String handLername = (string) handler; handler = getApplicationContext (). getBean (handLername);} return gethandlereXecutionChain (handler, request);} protected objet abstract gethandleRinternal (httpservletRequest request) lance exception; Enfin, encapsuler l'intercepteur à HandlereXecutionChain
Ajouter directement Adapted Interceptors
MaptedInterceptors doit être ajouté après la correspondance selon l'URL
// abstracthandLermappingProtected handlereXecutionChain gethandlereXecutionChain (objet Handler, httpservletRequest request) {handlereXecutionChain chaîne = (gestionnaire instanceof handlereXecutionChain) Handler: new handlerexecutionchain (gestionnaire); chain.addinterceptors (getAdaptedInterceptors ()); String lookuppath = urlpathhelper.getLookuppathForRequest (request); for (mappedInterceptor mappedInterceptor: mapedInterceptors) {if (mappedInterceptor.matches (lookuppath, pathmatcher))) {chain.addinterceptor (mappedInterceptor.getInterceptor ());}} Chaîne de retour;} La cartographie des sous-classes du contrôleur, cette branche examine d'abord l'héritage de la classe
Parlons des principales responsabilités de chaque catégorie ici
1. Abstracthandlermapping Préparez l'environnement de contexte; Fournir un crochet Gethandlerinternal; encapsuler l'intercepteur en handlerexecutionchain
2. AbstractUrlHandlermapping implémente la méthode d'enregistrement du gestionnaire pour une utilisation de la sous-classe; implémente Gethandlerinternal et trouve le gestionnaire basé sur les informations de configuration initialisées par sous-classes.
3.
4. AbstractControllerUrlHandlerMapping implémente déterminer leurlSForHandler, ajoute l'opération de gestionnaire (configuration du fichier de configuration) et réserve la méthode de crochet buildUrlsForHandler pour l'implémentation de la sous-classe; en même temps juge la sous-classe de contrôleur
5. ControllerBeanNameHandlerMapping Générer une URL basée sur le nom de bean
CONTRIXLASSNAMEHANDLERMAPPing génère une URL basée sur le nom de la classe
Commençons par AbstractUrlHandlerMapping. Ici, nous regardons simplement le code à peu près. Si vous devez l'analyser attentivement, veuillez passer à <SpringMVC Code Source Interprétation - Handlermapping - AbstractUrlHandlerMapping Series Distribution de la série>
Enregistrement du gestionnaire
Protected void RegisterHandler (String [] urlPaths, string beanname) lève BeanSexception, illégalStateException {} protégée void RegisterHandler (UrlPath de String, Handler d'objet) lance BeanSexception, illégalStateException {} La recherche de gestionnaire
Objet protégé Gethandlerinternal (demande httpsservillequest) lève une exception {} // finir la demande de recherche d'objets (UrlPath de chaîne, httpservletRequest) lance une exception {} // Vérifier le gestionnaire de vides de vide (} HandlereXecutionChainProtected objet buildPathexpositingHandler (objet RawHandler, String bestmatchingPattern, String pathwithinmapping, map <string, string> uritemplatevariables) {}AbstractDetectingurlHandlerMapping, ce n'est pas élargi, veuillez déplacer en détail <Interprétation du code source SpringMVC - Handlermapping - AbstractDetectingurlHandlermapping Series Initialisation>
Ce qu'il faut faire:
1. Appelez des détecteurs pour scanner l'OBJCT en écrasant InitApplicationContext
2. Fournir la méthode de crochet déterminer les URL de génération de sous-classes.
3. Appelez le registre de la classe Parent pour vous inscrire
@OverridePublic void initApplicationContext () lève ApplicationContextexception {super.initApplicationContext (); DeteteCthandlers ();} VOID protégé Detecthandlers () lance BeanSexception {// ...} / *** déterminer les urls pour le haricot de handicap. AbstractControllerUrlHandlerMapping, cela n'est pas élargi, veuillez déplacer en détail <Interprétation du code source SpringMVC - Handlermapping - AbstractDetectingurlHandlermapping Series Initialisation> Que faire spécifiquement;
1. Écraser le déterminurLSForHandler pour ajouter de la logique pour supprimer certaines classes, et utiliser excludClasses et excludPackages configuré dans le fichier de configuration.
2. Déterminez si la sous-classe du contrôleur
3. Réserve buildUrlsForHandler pour générer des URL pour les sous-classes
@OverRideProtected String [] déterminerUrlsForHandler (string beanname) {class beanclass = getApplicationContext (). GetType (beanname); if (iSeLIGIBLEFORMAP (beanname, beanclass)) {return buildUrlsForHandler (beanname, beanclass);} else {return Null;}}} protected boolean est eliligible; Storpaping, return null;}}} protected boolean est eliligible; Storpapping, Null;}}} protected boolean est eliligible; Storpaping, Null;}}} protected boolean est eliligible; Storpapping, Null;}}} protected boolean est eligibleForpord (Storpaping. Class BeanClass) {} Boolean Protected IsControllerType (classe BeanClass) {} String abstrait protégé [] BuildUrlsForHandler (String Beanname, classe de beanclasse de classe); ControllerBeanNameHandlerMapping et ControperClassNameHandlerMapping Regardez directement le code source, ou déplacez-vous <Springmvc Code source Interprétation - Handlermapping - AbstractDetectingurlHandlerMapping Initialisation> SimpleUrlHandlerMapping configure directement URL vers le gestionnaire dans le fichier de configuration, qui consiste à utiliser RegisterHandlers pour enregistrer le gestionnaire dans le document de configuration, lire directement le code ou déplacer <Interprétation du code source Springmvc - Handlermapping - SimpleUrlHandlerApping Initialisation>
BeannameUrlHandlerMapping implémente déterminerurLSForHandler pour générer des URL, consultez le code directement ou déplacer <Springmvc Source Code Interprétation - Handlermapping - AbstractDetectingurlHandlerMapping Initialisation>
Utilisation de @Controller, @Requestmapping basé sur l'annotation
L'os le plus dur
Regardons d'abord l'héritage des cours
Parlons des responsabilités de chaque catégorie. Pour une analyse spécifique, veuillez passer à l'article suivant
<Springmvc Code source Interprétation - Handlermapping - requestmappingHandlermapping Initialisation>
<Springmvc Code source Interprétation - Handlermapping - DemandemappingHandlerMapping Device Distribution>
1. Abstracthandlermethodmaping définit le processus d'initialisation et comment le mapper lors de la demande
Initialisation:
1.1.1 Scannez l'objet sous l'application
1.1.2 Réservez la méthode de crochet ISHandler à la sous-classe pour déterminer si l'objet est le gestionnaire
1.1.3 Scannez de manière itérative chaque gestionnaire pour trouver une méthode qui répond aux exigences. Le jugement ici est toujours laissé à la sous-classe pour implémenter GetMappingFormethod
1.1.4 Lors de l'enregistrement du processeur trouvé, vous devez vous assurer qu'une condition de correspondance de mise en œuvre de la mise en place enInfo ne peut être car à un gestionnaire
1.1.5 Obtenez l'URL en fonction des conditions de correspondance, et il en va de même pour définir le processus. L'algorithme spécifique est laissé à la sous-classe pour implémenter GetMappingPathPatterns
Traitement de la distribution de demande:
1.2.1 Méthode de correspondance directe de la chaîne, recherche de gestion
1.2.2 Recherche de condition correspondante, l'algorithme spécifique ici est remis à la sous-classe pour getmatchingmapping
1.2.3 Triez et obtenez le meilleur gestionnaire assorti. La méthode de tri ici est toujours le traitement de la sous-classe GetMappingCaparator
1.2.4 Encapsulation des gestionnaires de correspondance et de non-correspondance respectivement
2.
2.1 Générer une URL -> GetMappingPathPatterns selon RequestMappingInfo
2.2 Trouver le gestionnaire à l'aide de conditions de correspondance -> GetMatchingMapping
2.3 Algorithme du comparateur -> GetMappingComparator
2.4 Écraser de la main et le cache n Informations multiples à demander
Modèle d'enregistrement, meilleur modèle d'appariement, paramètres analysés dans l'URL, paramètres multi-valeurs analysés dans l'URL, MediaType
2.1.5 Écraser Handlernomatch, essayez de le faire correspondre à nouveau après la dernière lutte
3.
3.1 Écraser
3.2 Implémentation ISHandler, et l'une des annotations de la classe est correcte.
3.3 Analyser le contenu de l'annotation et produire des instances de mise en scène