El controlador frontal es la parte más central de todo el marco MVC. Se utiliza principalmente para interceptar solicitudes externas que cumplan con los requisitos y distribuyan las solicitudes a diferentes controladores para el procesamiento. Según los resultados del procesamiento del controlador, genera respuestas correspondientes y las envía al cliente. El controlador frontal se puede implementar utilizando Filter (Struts2 usa este método) o Servlet (marco de Spring MVC).
Como precontrolador, el desplazamiento del servidor es la entrada al servidor web y es la clase más importante de MVC de Spring. A través de su ciclo de vida, la comprensión del servidor web se puede profundizar.
Ciclo de vida de servlet
Primero, recordemos el ciclo de vida del servlet:
El ciclo de vida del servlet se divide en tres etapas: [Explicación detallada del ciclo de vida del servlet y el principio de trabajo]
1. El método init () se llama init () en la fase de inicialización. Después de cargar el servlet, el contenedor de servlet crea una instancia de servlet y llama al método init () del servlet para la inicialización. El método init () se llama solo una vez durante toda la vida de un servlet.
2. Llame al método del servicio () en respuesta a la etapa de solicitud del cliente
3. Llame al método destruir () en la etapa de terminación
Fase de inicialización de servlet
En los siguientes momentos, el contenedor de servlet carga el servlet:
1. Cuando se inicia el contenedor de servlet, algunos servlets se cargan automáticamente. Para implementarlo, solo necesita agregar el siguiente código entre <ervlet> </servlet> en el archivo web.xml:
<Loadon-startup> 1 </loadon-startup>
2. Después de iniciar el contenedor de servlet, el cliente envía una solicitud al servlet por primera vez
3. Después de actualizar el archivo de clase de servlet, recargue el servlet
La estructura del compatibilidad
Después de revisar el conocimiento anterior, echemos un vistazo a la estructura de DispatcherServlet:
DispatcherServlet hereda de la clase abstracta: FrameWorkServlet, hereda indirectamente httpservlet (FrameWorkServlet hereda de httpservletBean, y httpservletBean hereda de httpservlet)
Inicialización de servlet
Initstrategies de voides protegidos (contexto de applicationContext) {initMultipARTRESOLver (context); // Libra de archivo y analización. Si el tipo de solicitud es multipart, la carga de archivos y analiza a través de multipartresolver; initLocaleresolver (contexto); // Localización analizando InitThemeresolver (contexto); // Asumiendo el tema inithandlermappings (contexto); // Mapeo de solicitudes al procesador InithandlerAdapters (contexto); // mapeo de múltiples tipos de procesadores inithandlerExceptionResolvers (contexto); // admite múltiples tipos de procesadores a través de HandlerAdapter; // Si se encuentra una excepción durante la ejecución, se entregará a HandlerExceptionResolver para analizar el initrequestToviewNnametranslator (contexto); // analizar directamente la solicitud al nombre de vista InitViewResolvers (contexto); // Resolver el nombre de la vista lógica a la vista específica a través de ViewResolver para implementar initFlashMapManager (contexto); // Flash Map Manager}Cómo manejar las solicitudes:
El método de servicio del servlet maneja las solicitudes HTTP.
FrameWorkServlet.java define el servicio y destruye los métodos de servlet, como se muestra a continuación:
/** * Anule la implementación de la clase principal para interceptar las solicitudes de parche *. */ @Override Servicio vacío protegido (solicitud httpservletRequest, respuesta httpservletResponse) lanza ServLetException, ioException {String Method = request.getMethod (); if (método.equalSignorEcase (requestMethod.patch.name ())) {ProcessRequest (solicitud, respuesta); } else {super.service (solicitud, respuesta); }}Sabemos que hay siete tipos de tipos de solicitudes HTTP (más una opción), que se definen de la siguiente manera:
Public Enum requestMethod {get, head, publicar, poner, parche, eliminar, opciones, rastrear} El servicio () del FrameWorkServlet maneja diferentes solicitudes. Usamos publicaciones comunes para ilustrar:
/*** Procese esta solicitud, publicando un evento independientemente del resultado. * <p> El manejo de eventos real se realiza mediante el método de plantilla resumen * {@link #doservice}. */ Process de procesos void final protegido (solicitud httpservletRequest, httpservletResponse respuesta) arroja servletException, ioexception {long starttime = system.currentTimemillis (); FailureCause de lanzamiento de lanzamiento = NULL; LocalEcontext anteriorLocalecontext = localeContexTholder.getLocaleContext (); LocalContext localContext = buildLocaleContext (solicitud); RequestAttributes anteriorTtributes = requestContexTholder.getRequestatTributes (); ServLetRequestAttributes requestAttributes = buildRequestAttributes (solicitud, respuesta, anteriorTributes); WebasyncManager asyncManager = webasyncutils.getAsyncManager (solicitud); asyncmanager.registerCallableInterceptor (frameWorkServlet.class.getName (), nueva requestbindingInterceptor ()); initContexTholders (solicitud, localeContext, requestAttributes); intente {doservice (solicitud, respuesta); } catch (ServLetException ex) {faileurecause = ex; tirar ex; } catch (ioException ex) {faileurecause = ex; tirar ex; } catch (throwable ex) {faileurecause = ex; tirar nueva NestedServletException ("Fallado de procesamiento de solicitud", ex); } Finalmente {ResetContexTholders (solicitud, anteriorLocalecontext, anteriorattributes); if (requestAttributes! = null) {requestAttributes.RequestCompleted (); } if (logger.isDeBugeNable ()) {if (fauseurEraus! = null) {this.logger.debug ("no se pudo completar la solicitud", fauseRecause); } else {if (asyncmanager.isconCurrenthandlingStarted ()) {logger.debug ("dejando la respuesta abierta para el procesamiento concurrente"); } else {this.logger.debug ("solicitud completada con éxito"); }}} PublishRequestHandledEvent (solicitud, tiempo de inicio, failurecause); }} FrameWorkServlet define de manera abstracta el flujo de procesamiento y lo deja a subclases para implementar el método y completa el procesamiento de solicitudes específico.
/** * Las subclases deben implementar este método para hacer el trabajo de manejo de solicitudes, * recibir una devolución de llamada centralizada para obtener, publicar, poner y eliminar. * <p> El contrato es esencialmente el mismo que para los métodos de * {@code doget} o {@code dopost} de httpservlet. * <P> Esta clase intercepta las llamadas para garantizar que se realice el manejo de excepciones y la publicación de eventos *. * @param request current HTTP request * @param response current HTTP response * @throws Exception in case of any kind of processing failure * @see javax.servlet.http.HttpServlet#doGet * @see javax.servlet.http.HttpServlet#doPost */ protected abstract void doService(HttpServletRequest request, Respuesta httpservletResponse) arroja excepción;La implementación específica es la siguiente:
/** * Expone los atributos de solicitud específicos de despachadores y delegados a {@link #DodisPatch} * para el envío real. */ @Override Proteged Void Doservice (solicitud httpservletRequest, httpservletResponse) lanza la excepción {if (logger.isdebugeNabled ()) {string reumed = webasyncutiliSs.getAsyncManager (solicitud) .hasconcurrentResult ()? "reanudado": ""; logger.debug ("DispatcherServlet con nombre '" + getServletName () + "'" + reanudado + "procesamiento" + request.getMethod () + "solicitud para [" + getRequesturi (request) + "]"); } // Mantenga una instantánea de los atributos de solicitud en caso de incluir, // para poder restaurar los atributos originales después de la inclusión. Map <string, object> attributessnapshot = null; if (webutil.isinCludeRequest (request)) {attributessNapShot = new HashMap <String, Object> (); Enumeración <?> AttrNames = request.getAttributeNames (); while (attrNames.hasmoreElements ()) {String attrname = (string) attrNames.NextElement (); if (this.cleanupafterinClude || attrname.startswith ("org.springframework.web.servlet")) {attributessnapshot.put (attrname, request.getAttribute (attrname)); }}}} // Haga que los objetos Framework estén disponibles para los manejadores y vea objetos. request.setAttribute (Web_Application_Context_Attribute, getWebApplicationContext ()); request.setAttribute (locale_resolver_attribute, this.localeresolver); request.setAttribute (thema_resolver_Attribute, this.themeResolver); request.setAttribute (thema_source_attribute, getThemesource ()); Flashmap inputFlashMap = this.FlashMapManager.retRieveAndupdate (solicitud, respuesta); if (inputFLASHMAP! = NULL) {request.setAttribute (input_flash_map_attribute, colección.unmodifiablemap (inputFLASHMAP)); } request.SetAttribute (output_flash_map_attribute, new FlashMap ()); request.setAttribute (flash_map_manager_attribute, this.flashmapManager); intente {dodispatch (solicitud, respuesta); } Finalmente {if (webasyncutils.getAsyncManager (request) .IsconCurrentHandlingStarted ()) {return; } // Restaurar la instantánea de atributo original, en caso de incluir. if (attributessnapshot! = null) {restaurreeatTributesAfterinClude (request, attributessnapshot); }}}Lo más destacado, como la implementación del distribuidor de solicitudes:
Funciones: 1. Distribuir la solicitud al controlador (obtener la relación de mapeo de servlet en el orden de configuración); 2. Consulte el primer manejador que se puede procesar en función de los HandlerAdapters instalados por el Servlet; 3. El controlador activa el procesamiento de la solicitud
/*** Procese el envío real al controlador. * <P> El controlador se obtendrá aplicando las manejadores de handlerm de servlet en orden. * El HandlerAdapter se obtendrá consultando los HandlerAdapters instalados del Servlet * para encontrar el primero que admite la clase del controlador. * <P> Todos los métodos HTTP se manejan por este método. Depende de los manejadores o los manejadores * para decidir qué métodos son aceptables. * @param Solicitud actual HTTP Solicitud * @param Respuesta HTTP actual * @throws Excepción en caso de cualquier tipo de falla de procesamiento */ Protected void dodispatch (httpservletRequest solicitud, respuesta httpServletResponse) lanza la excepción {httpServletRequest processedRequest = solicitud; HandLerExecutionChain MappedHandler = NULL; boolean multipartRequestparsed = false; WebasyncManager asyncManager = webasyncutils.getAsyncManager (solicitud); intente {modelandView mv = null; Exception DispatchException = NULL; intente {ProcessedRequest = checkMultipart (solicitud); multipartRequestParsed = (ProcessedRequest! = request); // Determinar el controlador para la solicitud actual. MappedHandler = Gethandler (ProcessedRequest); if (mappedHandler == null || mappedHandler.gethandler () == null) {noHandlerFound (ProcessedRequest, respuesta); devolver; } // Determinar el adaptador de controlador para la solicitud actual. HandlerAdapter ha = gethandlerAdapter (MappedHandler.gethandler ()); // Procese el último encabezado modificado, si el manejador es compatible con el controlador. Método de cadena = request.getMethod (); boolean isget = "get" .equals (método); if (isget || "head" .equals (método)) {long LastModified = ha.getLastModified (request, mappedHandler.gethandler ()); if (logger.isdeBugeNabled ()) {logger.debug ("último valor modificado para [" + getRequesturi (request) + "] es:" + lastModified); } if (new ServletWebRequest (solicitud, respuesta) .CheckNotModified (lastModified) && isget) {return; }} if (new ServletWebRequest (solicitud, respuesta) .CheckNotModified (lastModified) && isget) {return; }} if (! MappedHandler.AplyPrehandle (ProcessedRequest, Respuesta)) {return; } try {// realmente invoca el controlador. mv = ha.handle (ProcessedRequest, respuesta, mappedhandler.gethandler ()); } Finalmente {if (asyncmanager.isconCurrenthandlingStarted ()) {return; }} ApplyDefaultViewName (solicitud, MV); MappedHandler.AplyPosthandle (ProcessedRequest, Respuesta, MV); } catch (Exception Ex) {DispatchException = ex; } processDisPatchResult (ProcessedRequest, respuesta, MappedHandler, MV, DispatchException); } catch (Exception Ex) {TriggerAfterCompletion (ProcessedRequest, Respuesta, MappedHandler, EX); } capt (error err) {TriggerAfterCompletionWithError (ProcessedRequest, Respuesta, MappedHandler, err); } Finalmente {if (asyncmanager.isconCurrentHandlingStarted ()) {// en lugar de postthandle y después de la Completion MappedHandler.applyAfterConCurrentHandlingStarted (ProcessedRequest, respuesta); devolver; } // Limpiar cualquier recurso utilizado por una solicitud de multipart. if (multipRequestparsed) {CleanUpMultipart (ProcessedRequest); }}}destrucción de servlet
/*** Cierre el WebApplicationContext de este servlet. * @see org.springframework.context.configurableApplicationContext#Close () */ @Override public void destruye () {getServletContext (). log ("destruir spring frameWorkServlet '" + getServletName () + "'"); // Solo llame a Cerrar () en WebApplicationContext si se administra localmente ... if (this.webApplicationContext instancia de configururaAplaPlicationContext &&! This.webApplicationContextInsected) {((configuableApplicationContext) this.webapplicationContext) .Cloe (); }}resumen:
Debido a las limitaciones del capítulo, este artículo solo presenta el proceso de procesamiento de solicitudes y no realiza un análisis en profundidad del código. El próximo artículo comenzará a partir de los detalles y analizará la belleza del código de Spring.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.