Le contrôleur frontal est la partie la plus centrale de l'ensemble du cadre MVC. Il est principalement utilisé pour intercepter les demandes externes qui répondent aux exigences et distribuer les demandes à différents contrôleurs de traitement. Selon les résultats du traitement du contrôleur, il génère des réponses correspondantes et les envoie au client. Le contrôleur frontal peut être implémenté à l'aide de filtre (Struts2 utilise cette méthode) ou du servlet (Spring MVC Framework).
En tant que pré-contrôleur, le Dispatcherservlet est l'entrée du serveur Web et est la classe la plus importante de Spring MVC. Pendant son cycle de vie, la compréhension du serveur Web peut être approfondie.
Cycle de vie du servlet
Tout d'abord, rappelons le cycle de vie du servlet:
Le cycle de vie du servlet est divisé en trois étapes: [Explication détaillée du cycle de vie du servlet et principe de travail]
1. La méthode init () est appelée init () dans la phase d'initialisation. Une fois le servlet chargé, le conteneur servlet crée une instance de servlet et appelle la méthode init () du servlet pour l'initialisation. La méthode init () n'est appelée qu'une seule fois pendant toute la vie d'un servlet.
2. Appelez la méthode Service () en réponse à l'étape de la demande du client
3. Call Detrère () Méthode au stade de terminaison
Phase d'initialisation du servlet
Aux moments suivants, le conteneur servlet charge le servlet:
1. Lorsque le conteneur servlet commence, certains servlets sont automatiquement chargés. Pour l'implémenter, il vous suffit d'ajouter le code suivant entre <Serplet> </vrlet> dans le fichier web.xml:
<Hooton-startup> 1 </foftaron-startup>
2. Après le démarrage du conteneur servlet, le client envoie une demande au servlet pour la première fois
3. Une fois le fichier de classe de servlet mis à jour, rechargez le servlet
La structure du Dispatcherservlet
Après avoir examiné les connaissances ci-dessus, jetons un coup d'œil à la structure de Dispatterservlet:
DispatcherServlet hérite de la classe abstraite: FrameWorksservlet, hérite indirectement HttpServlet (FrameWorkServlet hérite de HttpservletBean et HttpservletBean hérite de Httpservlet)
Initialisation du servlet
Protected void iniTStrategies (ApplicationContext Context) {initMultipArtResolver (contexte); // Téléchargement de fichiers et analyse. Si le type de demande est en multiparne, le téléchargement de fichiers et l'analyse via MultipartResolver; InitLocaleResolver (contexte); // Analyse de localisation InithemeReresolver (contexte); // l'analyse du thème inithandlermappings (contexte); // mappage des demandes au processeur inithandleradapters (contexte); // mappage de plusieurs types de processeurs InithandleRexceptionResolvers (contexte); // prend en charge plusieurs types de processeurs via HandleRadapter; // Si une exception est rencontrée lors de l'exécution, elle sera remise à HandlerexceptionResolver pour analyser IniTRequestToViewnameTranslateur (contexte); // analyse directement la demande au nom de vue initViewResolvers (contexte); // Résolvez le nom de vue logique dans la vue spécifique via ViewResolver pour implémenter initflashmapManager (contexte); // Flash Map Manager}Comment gérer les demandes:
La méthode de service du servlet gère les demandes HTTP.
FraworkServlet.java définit les méthodes de service et de détruire, comme indiqué ci-dessous:
/ ** * remplacer la mise en œuvre de la classe parent afin d'intercepter les demandes de patch *. * / @Override Protected Void Service (HttpServLetRequest Request, HttpServletResponse Response) lève ServletException, ioException {String Method = request.getMethod (); if (method.equalsignorecase (requestMethod.patch.name ())) {processRequest (request, réponse); } else {super.service (demande, réponse); }}Nous savons qu'il existe sept types de types de demandes HTTP (plus une option), qui sont définis comme suit:
Public Enum demandeMethod {get, head, poster, mettre, patch, supprimer, options, trace} Le service () du frameworkservlet gère différentes demandes. Nous utilisons des articles courants pour illustrer:
/ ** * traitez cette demande, publiant un événement quel que soit le résultat. * <p> La manipulation réelle des événements est effectuée par la méthode du modèle Abstract * {@link #doservice}. * / protégée final void processRequest (demande httpservletRequest, réponse httpservletResponse) lève ServletException, ioException {long startTime = System.Currenttimemillis (); Échec jetable = null; LocalEContext précédemmentLocaleContext = localEcontexTholder.getLocaleContext (); Localontext localontext = buildLocaleContext (request); RequestAttributes PREBERATTRIBUTES = requestContexTholder.getRequestAttributes (); ServLetRequestAttributes requestAttributes = buildRequestAttributes (demande, réponse, précédemmentaTributes); WebasyncManager asyncManager = webasyncutils.getAsyncManager (demande); asyncManager.RegisterCallableInterceptor (frameworkservlet.class.getName (), new requestBindingInterceptor ()); INITCONTEXTHOLDERS (request, localontext, requestAttributes); essayez {doservice (demande, réponse); } catch (servlexception ex) {failurecause = ex; jeter ex; } catch (ioException ex) {failurecause = ex; jeter ex; } catch (Throwable ex) {failurecause = ex; Jetez le nouveau NeedServletException ("Le traitement de la demande a échoué", ex); } enfin {resetContexTholders (request, précédemmentLocaleContext, préalableAttributes); if (requestAtTributes! = null) {requestAttributes.requestCompleted (); } if (logger.isdebugeNabled ()) {if (failurecause! = null) {this.logger.debug ("ne peut pas terminer la demande", failUreCause); } else {if (asyncManager.isConcurrentHandlingStarted ()) {logger.debug ("Laissant la réponse ouverte pour le traitement simultané"); } else {this.logger.debug ("Demande terminée avec succès"); }}} PublishRequestHandledEvent (demande, starttime, failurecause); }} Le frameworkservlet définit abstraitement le flux de traitement et le laisse aux sous-classes pour implémenter la méthode et complète le traitement spécifique de la demande.
/ ** * Les sous-classes doivent implémenter cette méthode pour effectuer le travail de gestion des demandes, * recevant un rappel centralisé pour GET, Publier, mettre et supprimer. * <p> Le contrat est essentiellement le même que celui pour les méthodes couramment dépassées * {@code doget} ou {@code doPost} de httpservlet. * <p> Cette classe intercepte les appels pour s'assurer que la gestion des exceptions et la publication d'événements ont lieu. * @param demande de demande HTTP actuelle * @param réponse réponse http actuelle * @throws exception en cas de tout type de défaillance de traitement * @see javax.servlet.http.httpservlet # doget * @see javax.servlet.http.httpservlet # dopost * / Protected abuder void doservice (httpservletre HttpServletResponse Response) lève une exception;La mise en œuvre spécifique est la suivante:
/ ** * expose les attributs de demande spécifiques à DispatcherServlet et délégue à {@link #Dodispatch} * pour la répartition réelle. * / @Override Protected void doservice (HttpServLetRequest Request, HttpServletResponse Response) lève une exception {if (logger.isdebugeNabled ()) {String remedEdResult ()? "Reprise": ""; Logger.debug ("Dispatcherservlet avec name '" + getServletName () + "'" + reprise + "traitement" + request.getMethod () + "request for [" + getRequesturi (request) + "]"); } // Gardez un instantané des attributs de demande en cas d'inclusion, // pour pouvoir restaurer les attributs d'origine après l'inclusion. Map <string, objet> attributionnapshot = null; if (webutils.isincludeRequest (request)) {attributsnapshot = new hashmap <string, object> (); Énumération <?> AttNames = request.getAtTrributeNames (); while (attNames.hasmoreElements ()) {String attRname = (string) attNames.NextElement (); if (this.cleanupafterinclude || attrname.startswith ("org.springframework.web.servlet")) {attributionSnapshot.put (attName, request.getAttribute (attName)); }}}} // Rendez les objets Framework disponibles pour les gestionnaires et afficher les objets. request.setAttribute (web_application_context_attribute, getWebApplicationContext ()); request.setAttribute (locale_resolver_attribute, this.localeresolver); request.setAttribute (thème_resolver_attribute, this.themeresolver); request.setAttribute (thème_source_attribute, getTheMesource ()); Flashmap inputflashmap = this.flashmapManager.RetRievEAnDupdate (demande, réponse); if (inputflashmap! = null) {request.setAttribute (input_flash_map_attribute, collections.unModiFublemap (inputflashmap)); } request.setAttribute (output_flash_map_attribute, new flashmap ()); request.setAttribute (flash_map_manager_attribute, this.flashmapManager); essayez {dodispatch (demande, réponse); } Enfin {if (webasyncutils.getasyncmanager (request) .isConCurrentHandlingStarted ()) {return; } // Restaurer l'instantané d'attribut d'origine, en cas d'inclusion. if (attributsnapshot! = null) {restoreAtTributesaSafteRincLed (request, attributionSnapshot); }}}Le point culminant, comme mise en œuvre du distributeur de demande:
Fonctions: 1. Distribuez la demande au gestionnaire (obtenez la relation de mappage du servlet dans l'ordre de configuration); 2. Interrogez le premier gestionnaire qui peut être traité en fonction des gestionnaires installés par le servlet; 3. Le gestionnaire déclenche le traitement de la demande
/ ** * Traitez la répartition réelle au gestionnaire. * <p> Le gestionnaire sera obtenu en appliquant les maintères du servlet dans l'ordre. * Le Handleradapter sera obtenu en interrogeant le HandlerAdapters du servlet * pour trouver le premier qui prend en charge la classe de gestionnaire. * <p> Toutes les méthodes HTTP sont gérées par cette méthode. C'est à la hauteur des gestionnaires ou des gestionnaires * pour décider quelles méthodes sont acceptables. * @param demande de demande HTTP actuelle * @param Response Response http Response * @throws Exception dans le cas de tout type d'échec de traitement * / Protected void Dodispatch (HttpservletRequest, réponse httpservletResponse) lève exception {httpservletRequest processErequest = request; HandlereXecutionChain mapedHandler = null; Boolean MultiparTreQuestPaSed = false; WebasyncManager asyncManager = webasyncutils.getAsyncManager (demande); essayez {ModelAndView mv = null; Exception DispatchException = null; try {processEdRequest = checkMultupart (request); MultipArtReSeStPaRSED = (ProcessEDequest! = Request); // Déterminer le gestionnaire de la demande actuelle. maptedHandler = Gethandler (processEDequest); if (mappedHandler == null || mappedHandler.Gethandler () == null) {noHandlerFound (processEDequest, réponse); retour; } // Déterminer l'adaptateur de gestionnaire pour la demande actuelle. Handleradapter ha = GethandlerAdapter (maptedHandler.Gethandler ()); // Profiter l'en-tête du dernier modifié, s'il est pris en charge par le gestionnaire. String Method = request.getMethod (); booléen isget = "get" .equals (méthode); if (isget || "head" .equals (méthode)) {long lastmodified = ha.getLastModified (request, mappedHandler.Gethandler ()); if (logger.isdebugeNabled ()) {logger.debug ("valeur de dernière modification pour [" + getRequesturi (request) + "] est:" + lastModified); } if (new ServletWebRequest (request, réponse) .checkNotModified (lastmodified) && isget) {return; }} if (new ServletWebRequest (request, réponse) .checkNotModified (lastmodified) && isget) {return; }} if (! mapedHandler.ApplyPrehandle (processEdRequest, réponse)) {return; } essayez {// invoque en fait le gestionnaire. mv = ha.handle (processEDequest, réponse, maptedHandler.Gethandler ()); } enfin {if (asyncManager.isConCurrentHandlingStarted ()) {return; }} appliquedEfaultViewName (request, mv); mappedHandler.ApplyPoSthandle (ProcessEDequest, réponse, MV); } catch (exception ex) {DispatchException = ex; } processDispatchResult (ProcessEDequest, Response, MaptedHandler, MV, DispatchException); } catch (exception ex) {TriggerAfterCompletion (ProcessEDequest, Response, MaptedHandler, ex); } catch (error err) {TriggerAfterCompletionWitHerror (ProcessEDequest, Response, maptedHandler, err); } Enfin {if (asyncManager.isConCurrentHandlingStarted ()) {// au lieu de posthandle et de aprèscomplétion maptedHandler.ApplyafterCurrentHandlingStarted (ProcessEDequest, Response); retour; } // Nettoyez toutes les ressources utilisées par une demande en plusieurs participants. if (multipartReQuestPaSed) {CleanUpMultupar (ProcessEDequest); }}}destruction du servlet
/ ** * Fermez le WebApplicationContext de ce servlet. * @see org.springframework.context.configurableApplicationContext # close () * / @Override public void destrement () {getServletContext (). Log ("destruction de frameworksserv de printemps '" + getServletName () + "'"); // appelle uniquement close () sur webApplicationContext si localement géré ... if (this.webApplicationContext instanceof configurableApplicationContext &&! This.webapplicationContextInjectEd) {((configurableApplicationContext) this.webapplicationContext) .Close (); }}résumé:
En raison des limites du chapitre, cet article n'introduit que le processus de traitement de la demande et ne procéde pas à une analyse approfondie du code. Le prochain article commencera à partir des détails et analysera la beauté du code de Spring.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.