La belleza de los patrones de diseño-patrones de patrones de comportamiento (27)

¿Qué es el modo de plantilla?

El patrón de método de plantilla define un esqueleto de algoritmo en un método y difiere ciertos pasos a subclases. El patrón de método de plantilla permite que las subclases redefinan ciertos pasos en el algoritmo sin cambiar la estructura general del algoritmo.

El rol del modo plantilla

Reutilización y expansión

Implementación estándar

public  abstract  class AbstractClass {
     public  final  void templateMethod () { 
        .... maneja algunas operaciones de inicialización o lógica común 
        // ... 
        method1 ();
         // ... 
        method2 ();
         // ... 
    }
     // define Método de plantilla correcto 1 método de 
    vacío abstracto protegido1  ();
     // Método de plantilla definido 2 método de vacío abstracto protegido2 (); 
} // Implementación 1 clase pública ConcreteClass1 extiende AbstractClass {
     // 
      


 enfoque inicializado en su lógica de procesamiento de los padres 
    @ Override
     protegida  sin efecto la metodo1 () {
         // ... 
    } 

    @ Override 
    protegida  vacío metodo2 () {
         // ... 
    } 
} 
// aplicar 2 
pública  clase ConcreteClass2 la extiende el AbstractClass {
     // La clase padre inicializa su propia lógica de procesamiento 
    @Override
     protected  void method1 () {
         // ... 
    } 

    @Override 
    protected  void method2 () {
         // ... 
    } 
}

AbstractClass demo = ConcreteClass1 (); 
demo.templateMethod ();

 

Usar en código fuente

DispatcherServlet

org.springframework.web.servlet.FrameworkServlet realiza algunas operaciones de inicialización

 proceso de solicitud final  vacío protegido (solicitud HttpServletRequest, respuesta HttpServletResponse) arroja ServletException, IOException {
         long startTime = System.currentTimeMillis (); 
        Throwable failureCause = null ;
         / ** 
         * <31> Obtiene el contexto de internacionalización de subproceso actual desde dentro de 2 ThreadLocal Get 
         * org.springframework.web.filter.RequestContextFilter # initContextHolders 
         * Si este filtro está configurado aquí, todas las solicitudes se han inicializado Spring boot Verification 
         * / 
        LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext ();
         // Construye el hilo actual cuando esta solicitud es internacional Contextualización
        LocaleContext localeContext = this .buildLocaleContext (request);
         / ** 
         * <32> Obtenga el atributo RequestAttribute de la solicitud de subproceso actual que se obtendrá de 2 ThreadLocal 
         * org.springframework.web.filter.RequestContextFilter # initContextHolders ha inicializado la verificación de arranque de resorte 
         * / 
        RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes ();
         // <4> Si no se ha creado el caché de subprocesos, significa que 
        ServletRequestAttributes no se han inicializado antes de requestAttributes = this .buildRequestAttributes (request, response, previousAttributes);
         / **  
         * se obtendrá de requsetAttribute Para inicializar uno y luego configurarlo en key = WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE
         * significa que podemos seguir después reqeust.getAttribute (WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE) Get 
         * Se usa para administrar solicitudes asincrónicas
         * / 
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager (solicitud); 
        asyncManager.registerCallableInterceptor (FrameworkServlet. Class .getName (), nuevo FrameworkServlet.RequestBindingInterceptor ());
         / ** 
         * <5> Esto se almacenará de acuerdo con la variable de idioma del objeto actual A qué subproceso de caché threadContextInheritable se establece en falso 
         * Podemos usar el BeanWapper anterior para modificar 
         * Indica que podemos obtenerlo más tarde en función de LocaleContextHolder y RequestContextHolder 
         * 
         * / 
        this .initContextHolders (request, localeContext, requestAttributes); 

        try{
             // <6> 抽象 方法 由 子 类 实现 如: DispatcherServlet 
         实现    this .doService (solicitud, respuesta); 
        } catch (ServletException var17) { 
            failureCause = var17;
            tirar var17; 
        } catch (IOException var18) { 
            failureCause = var18;
            tirar var18; 
        } catch (Throwable var19) { 
            failureCause = var19;
            lanzar una  nueva NestedServletException ("Error al procesar la solicitud" , var19); 
        } finalmente {
             / ** 
             * <7> El valor predeterminado anteriorLocaleContext previousAttributes es nulo 
             * Esto es principalmente para borrar los anteriorLocaleContext previousAttributes almacenados en caché por el hilo 
             * / 
            this .resetContextHolders (request, previousLocaleContext, previousAttributes);
             if (requestAttributes! = null ) { 
                requestAttributes. requestCompleted (); 
            } 

            if ( this .logger.isDebugEnabled ()) {
                 if (failureCause! = null ) {
                     this .logger.debug ("No se pudo completar la solicitud" , (Throwable) failureCause); 
                } más  si(asyncManager.isConcurrentHandlingStarted ()) {
                     this .logger.debug ("Dejar respuesta abierta para procesamiento concurrente" ); 
                } else {
                     this .logger.debug ("Solicitud completada con éxito" ); 
                } 
            } 
            // El mecanismo de evento Spring publica el mensaje ServletRequestHandlerEvent , Si esta solicitud se ejecuta correctamente o no, publicará 
            este mensaje.publishRequestHandledEvent (request, response, startTime, (Throwable) failureCause); 
        } 

    } 
// Método
abstracto protegido abstract void throwsdoService (HttpServletRequest var1, HttpServletResponse var2) Excepción;

org.springframework.web.servlet.DispatcherServlet # doService

protegida  vacío doService (HttpServletRequest solicitud, HttpServletResponse respuesta) lanza la excepción {
         si ( este .logger.isDebugEnabled ()) { 
            Cadena reanudó = WebAsyncUtils.getAsyncManager (petición) .hasConcurrentResult ()? "resumed": "" ;
            this .logger.debug ("DispatcherServlet con el nombre '" + this .getServletName () + "'" + resumed + "processing" + request.getMethod () + "request for [" + getRequestUri (request) + "]" ) ; 
        } 
        // 如果 是 incluir 请求 , 保存 atributo de solicitud 快照 数据 , 并 在 finalmente 中 进行 还原 
        Mapa <Cadena, Objeto>;
         / ** 
         * request.getAttribute ("javax.servlet.include.request_uri")! = null 
         * <jsp: incluede page = "xxx.jsp" /> 
         * JSP anidado sobre el compilador de etiquetas también es un servlet Use este atributo para determinar si es una etiqueta de inclusión 
         * / 
        if (WebUtils.isIncludeRequest (request)) { 
            atributosSnapshot = new HashMap (); 
            Enumeration attrNames = request.getAttributeNames (); 

            label108: 
            while ( true ) { 
                String attrName; 
                do {
                     if (! attrNames.hasMoreElements ()) {
                         breaketiqueta108; 
                    } 

                    attrName = (String) attrNames.nextElement (); 
                } while (! this .cleanupAfterInclude &&! attrName.startsWith ("org.springframework.web.servlet" )); 

                atributosSnapshot.put (attrName, request.getAttribute (attrName)); 
            } 
        } 
        // 保存 ApplicationContext 到 request 
        request.setAttribute (WEB_APPLICATION_CONTEXT_ATTRIBUTE, this .getWebApplicationContext ());
        // 保存 localeResolver 到 request 
        request.setAttribute (LOCALE_RESOLVER_ATTRIBUTE, esto.localeResolver);
         // guardar la solicitud de themeResolver 
        request.setAttribute (THEME_RESOLVER_ATTRIBUTE, la presente .themeResolver);
         // guardar la solicitud de gThemeSource 
        request.setAttribute (THEME_SOURCE_ATTRIBUTE, la presente .getThemeSource ());
         // se parece a un cinturón 302 para resolver la redirección El problema de la longitud del parámetro se guarda primero en el servidor y luego la redirección 302 solo necesita traer la clave correspondiente 
        FlashMap inputFlashMap = this .flashMapManager.retrieveAndUpdate (request, response);
         if (inputFlashMap! = Null ) { 
            request.setAttribute (INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodif. (inputFlashMap)); 
        } 

        //Guarde un flashMap 
        request.setAttribute vacío (OUTPUT_FLASH_MAP_ATTRIBUTE, nuevo FlashMap ());
         // Guarde flashMapManager 
        request.setAttribute (FLASH_MAP_MANAGER_ATTRIBUTE, este .flashMapManager); 

        intente {
             // <7> Ejecutar solicitud de procesamiento 
            esta .doDispatch (solicitud de respuesta, esta respuesta de respuesta, ; 
        } finalmente {
             // Restaurar datos de la instantánea 
            if (! WebAsyncUtils.getAsyncManager (request) .isConcurrentHandlingStarted () && atributosSnapshot! = null ) {
                 this .restoreAttributesAfterInclude (request, atributosSnapshot); 
            }

        } 

    }

Extracto de: "Lectura del código fuente SpringMVC : flujo de procesamiento principal de solicitud DispatcherServlet (cuatro)"

Supongo que te gusta

Origin www.cnblogs.com/LQBlog/p/12671929.html
Recomendado
Clasificación