Descripción general
Para los desarrolladores web, el modelo MVC es muy familiar para todos. En SpringMVC, la solicitud que cumple con las condiciones entre en el despachador de servicio responsable de la distribución de la solicitud. El desplazamiento mapea la URL de solicitud al controlador (guarde en Handlermapping). Handlermapping finalmente devuelve el HandleRexecutionChain, que contiene el controlador de objetos de procesamiento específico (es decir, lo que escribimos cuando lo programamos). Controlador) y una serie de interceptores. En este momento, el desplazamiento encontrará un HandlerAdapter que admite este tipo de procesador basado en el controlador en el controlador en la HandLerExecutionChain devuelta. En el adaptador del procesador, eventualmente llamará al método de respuesta de solicitud del controlador y devolverá la vista de resultados (modelandview). Después de obtener la vista del resultado, el resultado se muestra a través del método de renderizado.
Sistema de herencia Handermapping:
SpringMVC solicita distribución al procesador de controladores. Este paso se resuelve a través del módulo Handlermapping. Handlermapping también maneja interceptores.
Echemos un vistazo al árbol de herencia de Handlermapping primero
Puedes hacer una clasificación como esta:
1. Una interfaz Handlermapping, defina una API: HandleRexecutionChain Gethandler (HTTPServletRequest Solicitud) arroja excepción;
2. Una clase abstracta básica: prepara principalmente el entorno de contexto, proporciona el gancho gethandlerinternal, encapsula el interceptor a la cadena de identificación
3. Uso de @Controller, @RequestMapping basado en la anotación
4. Configure el SimpleUrlHandlermapping desde la URL al controlador en el archivo de configuración
5. BeanNameUrlHandlermapping se implementa de forma predeterminada
6. Mapeo de subclases de controlador
Echemos un vistazo a Handlermapping, solo una API de Gethandler es muy simple.
// handlermappingpackage org.springframework.web.servlet; interfaz pública handlermapping {handleRexecutionChain Gethandler (httpservletrequest solicitud) arroja excepción;} El abstractthandlermappap no es tan simple
Primera mira a la clase heredada por AbstractthandLermapping y la interfaz implementada
paquete org.springframework.web.servlet.handler; clase pública abstractthandlermapping extiende webapplicationObjectSupportImplements Handlermapping, ordenado {// ...} WebApplicationObjectSupport se utiliza para proporcionar contexto AplicationContext y ServletContext.
También está el método InitApplicationContext aquí, que a menudo se usa en el futuro. El abstracto se anula directamente.
Las interfaces AplicationContextAware y ServletContextAware todavía se implementan en la clase principal, y el concepto de primavera está muy unificado.
Pedido se usa para la clasificación de la recolección.
Continuemos observando las propiedades de la absorción de abstracturación
// AbstractThandLermapping // El pedido asigna el valor máximo, y la prioridad es el pedido privado más pequeño de privado = integer.max_value; // predeterminado: igual que el no ordenado // el controlador predeterminado, el obEJCT utilizado aquí y la implementación de la subclase, use Handlermethod, HandLerExecutionChain y otro objeto privado Defaulthandler; // La clase Auxiliary para el cálculo de URL URL URLPATHHELPER URLPATHHELPER = NEW URLPATHHELPER (); // Matching Matching se basa en el rutero privado y soldado. AntpathMatcher (); // Configuración del interceptor :, Configuración de propiedad HandLermapping ;, ExtendInterceptors Establece la lista final privada <SPET> Interceptores = new ArrayList <SPET> (); // Parse de Interceptors y agregue directamente a todos los HandlerPrivate Final Lister <DannerCeptor> ADAPTITORS = New ArrayList <DandLerCeptor>; Si se pasa la coincidencia, se utilizará la lista final privada <Mappedinterceptor> MappedInterceptors = new ArrayList <Mappedinterceptor> ();
Consulte la inicialización del interceptor:
// AbstractThandLermapping@overRideProtected initApplicationContext () lanza BeanSexception {ExtendInterceptors (this.interceptores); DetectMappedInterceptors (this.MappedInterceptors); initinterceptors ();}/*** proporcionados a los interceptores de extensión de subclass, pero desafortunadamente no se usan*/protegidos void Extendors (Object (Object (Object) {}/*** Scan the MappedInterceptors under the application and add them to mappedInterceptors*/protected void detectMappedInterceptors(List<MappedInterceptor> mappedInterceptors) {mappedInterceptors.addAll(BeanFactoryUtils.beansOfTypeIncludedAncestors(getApplicationContext(),MappedInterceptor.class, true, falso) .Values ());}/*** Recopile Mappedinterceptor y adapte a HandlerInterceptor y WebRequestInterceptor*/Protected Void initinterceptors () {if (! this.interceptors.isempty ()) {for (int i =; i <this.interceptors.); i ++) {Object Interceptors = this.interceptors.get (INTERCETCETORS. null) {throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");}if (interceptor instance of MappedInterceptor) {mappedInterceptors.add((MappedInterceptor) interceptor);}else {adaptedInterceptors.add(adaptInterceptor(interceptor));}}}} protected HandlerInterceptor adaptinterceptor (object interceptor) {if (interceptor instanceOf handlerInterceptor) {return (handlerInterceptor) interceptor;} else if (Interceptor instanceOf WebRequestInterceptor) {return New WebRequestHanderInterceptorAdapter ((WebRequestInterceptoreTorsceptor);} más interceptor.getclass (). getName ());}}Luego está la implementación de Gethandler (solicitud httpservletrequest), y aquí también se reserva GethandlerInternal (solicitud httpservletrequest) para la implementación de la subclase.
// AbstractThandlermapping Public HandleReXecutionChain Gethandler (HttpServletRequest Solicitud) Lanza la excepción {Handler de objetos = GethandlerInternal (request); if (handler == null) {Handler = getFeFaUnthandler ();} if (Handler == null) {return null;} // name o name o resolved handler? {String handlername = (String) Handler; Handler = GetApplicationContext (). GetBean (HandLername);} return gethandLerExecutionChain (handler, request);} objeto abstracto protegido gethandlerinternal (httpservletrequest solicitud) lanza excepción; Finalmente, encapsula el interceptor a HandleRexecutionChain
Agregue adaptadores adaptados directamente
Deben agregarse a los interceptores mapeados después de coincidir de acuerdo con la URL
// AbstractThandlermapping HandleRExecutionChain GethandLerExecutionChain (Handler de objetos, HttPservletRequest) {HandleRexecutionChain Chain = (Handler Instance de HandleRexecutionChain) Handler: New HandleRexecutionChain (Handler); Chain.addinterceptors (getAdaptedInterceptors ()); string lookUppath = urlpathHelper.getLoightUppathForRequest (solicitud); para (MappedInterceptor MappedInterceptor: Mappedinterceptors) {if (MappedInterceptor.Matches (Lookuppath, Pathmatcher))) {Chain.addinterceptor (mappedinterceptor.getinterceptor ());}} cadena de retorno;} El mapeo de las subclases del controlador, esta rama primero analiza la herencia de la clase
Hablemos sobre las principales responsabilidades de cada categoría aquí
1. Abstractthandlermapping Prepare el entorno de contexto; Proporcione gethandlerinternal gancho; Interceptor encapsulado a HandleRexecutionChain
2. AbstractUrlHandlermapping implementa el método de registro del controlador para el uso de la subclase; Implementa GethandlerInternal y encuentra el controlador basado en la información de configuración inicializada por subclases.
3. Abstract DetectInGurlHandlermapping escanea el objeto debajo de la aplicación, y después de la iteración, proporcione el método de gancho DetermlSSforHandler para determinar cómo filtrarlo.
4. AbstractControllerUrlHandlermapping implementos DetermlSforHandler, agrega la operación del controlador (configuración del archivo de configuración) y se reserva el método de gancho BuildUrlsforHandler para la implementación de la subclase; Al mismo tiempo juzga la subclase del controlador
5. ControlerBeanNameHandlermapping Genere URL basado en el nombre de la frijoles
ControllerClassNameHandlermapping genera URL basado en el nombre de la clase
Comencemos con abstracturlhandlermapping. Aquí solo miramos el código aproximadamente. Si necesita analizarlo cuidadosamente, muévase a <Interpretación del código fuente de SpringMVC - HandLermapping - Distribución de solicitudes de la serie de ManderLispaping de resumen>
Registro de controlador
protegido void registreHandler (string [] urlpaths, string beanName) lanza Beansexception, ilegalStateException {} protegido Void RegisterHandler (String UrlPath, Handler de Object) lanza BeanSexCeption, IlegalStateException {} La búsqueda del controlador
objeto protegido gethandlerInternal (httpservletRequest) lanza excepción {} // Buscar handlerProtectected lookupHandler (String urlPath, httpservletRequest solicitud) se lanza la excepción {} // verificar el handlerprotected void validateLer (manejador de objeto, httpservletRequest) SHOLES SHILLSE SHILLSE {} // //// COMECTURELELELETOR DE INTERSECTOR DE INTERSECTOR HandLerExecutionChainprotected Object BuildPathExPositingHandler (Object RawHandler, String BestMatchingPattern, String PathWitHInMapping, Map <String, String> UritaMateVariables) {}AbstractDetectingUrlHandlermapping, esto no se expande, mueva en detalle <Interpretación del código fuente de SpringMVC - HandLermapping - AbstractDetectInGurlHandlermapping Inicialización de la serie>
Qué hacer:
1. Llame a los detectores de detección para escanear OBJCT sobrescribiendo InitApplicationContext
2. Proporcione el método de gancho DetermlsSforHandler para subclase generar URL de acuerdo con el manejador
3. Llame al Registro de registro de la clase principal para registrarse
@OverridePublic void initApplicationContext () lanza ApplicationContextException {super.InitApplicationContext (); DetEdThandLers ();} protegido void detectthandLers () lanza beansexception {// ...}/*** Determinar las urls para el handler dado.*Solo gancho*/protegido String [] Determine (] Determinar (determinar (stringhandler); AbstractControllerUrlHandlermapping, esto no se expande, mueva en detalle <Interpretación del código fuente de SpringMVC - Handlermapping - AbstractDetectInGurlHandlermapping Inicialización de la serie> Qué hacer específicamente;
1. Sobrescribe el DetermlSforHandler para agregar lógica para eliminar algunas clases y use las clases excluidas y los paquetes excluidos configurados en el archivo de configuración.
2. Determine si la subclase del controlador
3. Reserve BuildUrlsForHandler para generar URL para subclases
@OverrideProtected String [] DetermlsforHandler (String BeanName) {class BeanClass = GetApplicationContext (). GetType (BeanName); if (isEligibleFormapping (beanName, beanClass)) {return BuildUrlsforHandler (beanName, beanClass);} else {return null;}} boolean iseLigIleping (string -beanClass);} el más {return null;}} boolean iseLigIlejer (string -beanClass); Class beanClass) {} protegido boolean isControllerType (class beanClass) {} cadena abstracta protegida [] buildUrlsForHandler (String BeanName, Class BeanClass); ControlerBeanNameHandLermapping y ControllerClassNameHandlermapping Mira el código fuente directamente, o mueve <Interpretación del código fuente de SpringMVC - HandLermapping - AbstractDetectingUrlHandlermapping Series Inicialización> SimpleUrlHandLermapping configura directamente la URL en el controlador en el archivo de configuración, que es utilizar Registrandlers para registrar el controlador en el documento de configuración, leer el código directamente o mover <Interpretación del código fuente de SpringMVC - HandLermapping - Inicialización de SimpleUrlHandlermapping>
BeanNameUrlHandlermapping implementos DetermlSforHandler para generar URL, mire el código directamente o mueva <Interpretación del código fuente de SpringMVC - HandLermapping - AbstractDetectingUrlHandlermapping Inicialización de la serie>
Uso de @Controller, @RequestMapping basado en la anotación
El hueso más duro
Veamos primero la herencia de clase
Hablemos sobre las responsabilidades de cada categoría. Para un análisis específico, pase al siguiente artículo
<Interpretación del código fuente de SpringMVC - HandLermapping - RequestMappingHandlermapping Initialización>
<Interpretación del código fuente de SpringMVC - HandLermapping - Solicitando distribución de solicitudes de manchas de mano>
1. Abstractthandlermethodmaping define el proceso de inicialización y cómo mapearlo al solicitar
Inicialización:
1.1.1 Escanear el objeto en la aplicación
1.1.2 Reserve el método ISHandler Hook para subclase para determinar si el objeto es controlador
1.1.3 Escanear iterativamente cada controlador para encontrar un método que cumpla con los requisitos. El juicio aquí todavía se deja a la subclase para implementar GetMappingFormethod
1.1.4 Al registrar el procesador encontrado, debe asegurarse de que una condición coincidente SolicitMappingInfo solo pueda asignar a un controlador
1.1.5 Obtenga la URL de acuerdo con las condiciones de correspondencia, y lo mismo es solo definir el proceso. El algoritmo específico se deja a la subclase para implementar GetMappingPathPatns
Procesamiento de distribución de solicitudes:
1.2.1 Método de coincidencia de cadenas directas, busque el controlador
1.2.2 Búsqueda de condición coincidente, el algoritmo específico aquí se entrega a la subclase para obtenermatchingmapping
1.2.3 Ordene y obtenga el mejor manejador a juego. El método de clasificación aquí sigue siendo el procesador de subclase GetMappingConparator
1.2.4 Encapsulación de manejadores coincidentes y no coincidentes respectivamente
2. SELITMingMappingInfoHandlermapping utiliza requestMappingInfo para implementar condiciones de coincidencia, y la inicialización de requestMappingInfo se deja a la subclase
2.1 Generar URL -> GetMappingPathPatterns de acuerdo con SolicitarMappingInfo
2.2 Encuentre el controlador utilizando condiciones de correspondencia -> getMatchingMapping
2.3 Algoritmo de comparación -> GetMappingComparator
2.4 sobrescribir a mano de mano y caché n múltiples información para solicitar
Patrón de registro, mejor patrón de coincidencia, parámetros analizados en URL, parámetros de valores múltiples analizados en URL, Mediatype
2.1.5 Sobrescribir a Handlernomatch, intente igualarlo nuevamente después de la última lucha
3. SELITMingMappingHandlermapping Genere requestMappingInfo de acuerdo con la anotación @Controller @RequestMapping y Verify ISHandler
3.1 sobrescribir después de la propiedad y agregar sufijo de archivo a juzgar
3.2 Implementar ISHANDLER, y una de las anotaciones en la clase es correcta.
3.3 Analizar el contenido de anotación y producir instancias de solicitud de SolicsMappingInfo