El libro del Dr. Yan Hong "JAVA and Patterns" comienza con una descripción del modelo de Cadena de Responsabilidad:
El patrón de cadena de responsabilidad es un patrón de comportamiento de objeto. En el patrón de cadena de responsabilidad, muchos objetos están conectados para formar una cadena mediante la referencia de cada objeto a su descendiente. La solicitud asciende en la cadena hasta que un objeto de la cadena decide manejar la solicitud. El cliente que realiza la solicitud no sabe qué objeto de la cadena maneja finalmente la solicitud, lo que permite que el sistema se reorganice dinámicamente y asigne responsabilidades sin afectar al cliente.
Empezando por tocar tambores y esparcir flores.
Tocar el tambor y pasar flores es un juego de beber animado y tenso. Durante el banquete, los invitados se sientan en orden y una persona toca el tambor. El lugar donde se toca el tambor y el lugar por donde se pasan las flores están separados para mostrar equidad. Cuando empiezan los tambores, los ramos comienzan a pasarse, y tan pronto como caen los tambores, si el ramo está en la mano de alguien, esa persona tiene que beber.
Por ejemplo, Jia Mu, Jia She, Jia Zheng, Jia Baoyu y Jia Huan son cinco pasadores de flores que participan en el juego de tambores y pases de flores. El baterista le pasó las flores a Jia Mu y comenzó el juego de pasar flores. La flor pasó de Jia Mu a Jia She, de Jia She a Jia Zheng, de Jia Zheng a Jia Baoyu, de Jia Baoyu a Jia Huan, de Jia Huan a Jia Mu, y así sucesivamente, como se muestra en la figura siguiente. Cuando cesa el tamborileo, la persona que tiene la flor en la mano debe realizar la orden de beber.
Tocar el tambor y repartir flores es la aplicación del modelo de cadena de responsabilidad. La cadena de responsabilidad puede ser una línea recta, una cadena o parte de una estructura de árbol.
La estructura del modelo de cadena de responsabilidad.
A continuación se utiliza la implementación más simple de un patrón de cadena de responsabilidad.
Los roles involucrados en el modelo de cadena de responsabilidad son los siguientes:
● Rol de controlador abstracto (Handler): define una interfaz para procesar solicitudes. Si es necesario, la interfaz puede definir un método para configurar y devolver una referencia a la siguiente interfaz. Esta función suele implementarse mediante una clase abstracta de Java o una interfaz de Java. La relación de agregación de la clase Handler en la figura anterior proporciona la referencia de la subclase específica a la siguiente. El método abstracto handleRequest() estandariza el funcionamiento de la subclase en el procesamiento de solicitudes.
● Rol de controlador de concreto (ConcreteHandler): después de recibir la solicitud, el controlador de concreto puede optar por procesar la solicitud o pasarla a la siguiente parte. Dado que el procesador de concreto tiene una referencia a la siguiente casa, el procesador de concreto puede acceder a la siguiente casa si es necesario.
código fuente
rol de controlador abstracto
Copie el código de código de la siguiente manera:
Controlador de clase abstracta pública {
/**
* Tiene objetos de responsabilidad sucesoria.
*/
sucesor del controlador protegido;
/**
* Indica el método de procesamiento de la solicitud, aunque este método no pasa parámetros
* Sin embargo, los parámetros se pueden pasar. Puede elegir si desea pasar parámetros según las necesidades específicas.
*/
handleRequest público abstracto vacío ();
/**
* Método de valor
*/
Controlador público getSuccessor() {
sucesor de retorno;
}
/**
* Método de asignación para establecer objetos de responsabilidad posteriores.
*/
public void setSuccessor (sucesor del controlador) {
this.successor = sucesor;
}
}
Rol específico del procesador
Copie el código de código de la siguiente manera:
clase pública ConcreteHandler extiende Handler {
/**
* Método de procesamiento, llame a este método para procesar la solicitud
*/
@Anular
solicitud de mango vacío público () {
/**
* Determinar si existe un objeto responsable sucesor
* Si lo hay, remitir la solicitud al objeto responsable posterior.
* En caso contrario, tramitar la solicitud
*/
si(getSuccessor() != nulo)
{
System.out.println("Dejar ir la solicitud");
getSuccessor().handleRequest();
}demás
{
System.out.println("Solicitud de procesamiento");
}
}
}
clase de cliente
Copie el código de código de la siguiente manera:
Cliente de clase pública {
público estático vacío principal (String [] argumentos) {
//Montar la cadena de responsabilidad
Controlador controlador1 = nuevo ConcreteHandler();
Controlador controlador2 = nuevo ConcreteHandler();
handler1.setSuccessor(handler2);
//Enviar solicitud
controlador1.handleRequest();
}
}
Se puede ver que el cliente crea dos objetos de controlador y especifica que el siguiente objeto de controlador del primer objeto de controlador es el segundo objeto de controlador, mientras que el segundo objeto de controlador no tiene un siguiente hogar. Luego, el cliente pasa la solicitud al primer objeto controlador.
Porque la lógica de transferencia de este ejemplo es muy simple: siempre que haya un siguiente propietario, se pasará al siguiente propietario para su procesamiento; si no hay un siguiente propietario, lo manejará usted mismo; Por lo tanto, después de que el primer objeto controlador reciba la solicitud, la pasará al segundo objeto controlador. Dado que el segundo objeto controlador no tiene hogar, maneja la solicitud por sí mismo. El diagrama de secuencia de actividades se muestra a continuación.
Escenarios de uso
Consideremos una función de este tipo: solicitar la gestión de los gastos de la cena.
Muchas empresas tienen este tipo de beneficio, es decir, el equipo o departamento del proyecto puede solicitar algunos gastos de cena a la empresa, que se utiliza para organizar cenas para los miembros del equipo del proyecto o miembros del departamento.
El proceso general para solicitar gastos de cena es generalmente: el solicitante primero completa el formulario de solicitud y luego lo envía al líder para su aprobación. Si la solicitud es aprobada, el líder le notificará que la aprobación ha sido aprobada. y luego el solicitante irá al departamento de finanzas para cobrar la tarifa. Si no se aprueba, se notificará al líder que no se ha aprobado la aprobación y se abandonará el asunto.
Los líderes de diferentes niveles tienen diferentes límites de aprobación. Por ejemplo, el director de proyecto sólo puede aprobar solicitudes con un límite de 500 yuanes; los gerentes de departamento pueden aprobar solicitudes con un límite de 1.000 yuanes;
En otras palabras, cuando alguien solicita gastos de cena, la solicitud será procesada en consecuencia por uno de los gerentes de proyecto, gerentes de departamento y gerentes generales, pero la persona que realizó la solicitud no sabe qué sucederá al final. ¿Quién atenderá su solicitud? Generalmente, el solicitante presenta su solicitud al director del proyecto y quizás el director general finalmente atienda su solicitud.
Puede utilizar el modelo de cadena de responsabilidad para realizar la función anterior: cuando alguien solicita gastos de cena, la solicitud se transmitirá en una cadena de procesamiento de liderazgo, como gerente de proyecto -> gerente de departamento -> gerente general La persona. quien hizo la solicitud no sabe quién manejará su solicitud, cada líder juzgará si manejará la solicitud o la entregará a un líder de nivel superior en función de su propio alcance de responsabilidades, siempre que un líder la maneje. la transferencia ha terminado.
Es necesario aislar el procesamiento de cada líder e implementarlo en un objeto de procesamiento de responsabilidad separado, y luego proporcionarles un objeto de responsabilidad principal abstracto y común, de modo que la cadena de responsabilidad se pueda combinar dinámicamente en el cliente para lograr diferentes requisitos funcionales. .
código fuente
Clase de rol de controlador abstracto
Copie el código de código de la siguiente manera:
Controlador de clase abstracta pública {
/**
* Contiene el objeto que maneja la siguiente solicitud.
*/
Sucesor del controlador protegido = nulo;
/**
* Método de valor
*/
Controlador público getSuccessor() {
sucesor de regreso;
}
/**
* Establecer el siguiente objeto para manejar la solicitud.
*/
public void setSuccessor (sucesor del controlador) {
this.successor = sucesor;
}
/**
* Procesar solicitudes de gastos de fiesta.
* @param usuario solicitante
* @param fee La cantidad de dinero solicitada
* @return Notificación específica de éxito o fracaso
*/
public abstract String handleFeeRequest (usuario de cadena, tarifa doble);
}
Rol específico del procesador
Copie el código de código de la siguiente manera:
clase pública ProjectManager extiende Handler {
@Anular
public String handleFeeRequest (usuario de cadena, tarifa doble) {
Cadena cadena = "";
// La autoridad del director del proyecto es relativamente pequeña y solo puede estar dentro de 500
si(tarifa < 500)
{
// Para realizar las pruebas, manténgalo simple y solo acepte la solicitud de Zhang San.
if("Zhang San".equals(usuario))
{
str = "Éxito: el director del proyecto acepta la tarifa de la cena de [" + usuario + "], el monto es " + tarifa + "yuan";
}demás
{
//Nadie más está de acuerdo
str = "Error: el director del proyecto no está de acuerdo con la tarifa de la cena de [" + usuario + "], el monto es " + tarifa + "yuan";
}
}demás
{
// Si supera los 500, continúe pasándolo a personas de nivel superior para su procesamiento.
si(getSuccessor() != nulo)
{
return getSuccessor().handleFeeRequest(usuario, tarifa);
}
}
devolver cadena;
}
}
Copie el código de código de la siguiente manera:
clase pública DeptManager extiende Handler {
@Anular
public String handleFeeRequest (usuario de cadena, tarifa doble) {
Cadena cadena = "";
//La autoridad del director del departamento solo puede estar dentro de 1000
si(tarifa < 1000)
{
// Para realizar las pruebas, manténgalo simple y solo acepte la solicitud de Zhang San.
if("Zhang San".equals(usuario))
{
str = "Éxito: el gerente del departamento acepta la tarifa de la cena de [" + usuario + "], el monto es " + tarifa + "yuan";
}demás
{
//Nadie más está de acuerdo
str = "Error: el gerente del departamento no está de acuerdo con la tarifa de la cena de [" + usuario + "], el monto es " + tarifa + "yuan";
}
}demás
{
// Si excede 1000, continúe pasándolo a personas de nivel superior para su procesamiento.
si(getSuccessor() != nulo)
{
return getSuccessor().handleFeeRequest(usuario, tarifa);
}
}
devolver cadena;
}
}
Copie el código de código de la siguiente manera:
clase pública GeneralManager extiende Handler {
@Anular
public String handleFeeRequest (usuario de cadena, tarifa doble) {
Cadena cadena = "";
// El gerente general tiene gran autoridad, siempre que la solicitud llegue aquí, él puede manejarla.
si(tarifa >= 1000)
{
// Para realizar las pruebas, manténgalo simple y solo acepte la solicitud de Zhang San.
if("Zhang San".equals(usuario))
{
str = "Éxito: el gerente general acepta los gastos de la cena de [" + usuario + "], el monto es " + tarifa + "yuan";
}demás
{
//Nadie más está de acuerdo
str = "Error: el gerente general no está de acuerdo con la tarifa de la cena de [" + usuario + "], el monto es " + tarifa + "yuan";
}
}demás
{
// Si hay objetos de procesamiento posteriores, continúa pasándolos
si(getSuccessor() != nulo)
{
return getSuccessor().handleFeeRequest(usuario, tarifa);
}
}
devolver cadena;
}
}
clase de cliente
Copie el código de código de la siguiente manera:
Cliente de clase pública {
público estático vacío principal (String [] argumentos) {
// Primero ensambla la cadena de responsabilidad
Controlador h1 = nuevo GeneralManager();
Controlador h2 = nuevo DeptManager();
Controlador h3 = nuevo ProjectManager();
h3.setSuccessor(h2);
h2.setSuccessor(h1);
//Comenzar a probar
Prueba de cadena1 = h3.handleFeeRequest("Zhang San", 300);
System.out.println("prueba1 = " + prueba1);
String test2 = h3.handleFeeRequest("李思", 300);
System.out.println("prueba2 = " + prueba2);
System.out.println("------------------------------------------------");
Prueba de cadena3 = h3.handleFeeRequest("Zhang San", 700);
System.out.println("prueba3 = " + prueba3);
String test4 = h3.handleFeeRequest("李思", 700);
System.out.println("prueba4 = " + prueba4);
System.out.println("------------------------------------------------");
Prueba de cadena5 = h3.handleFeeRequest("Zhang San", 1500);
System.out.println("prueba5 = " + prueba5);
String test6 = h3.handleFeeRequest("李思", 1500);
System.out.println("prueba6 = " + prueba6);
}
}
Los resultados de ejecución son los siguientes:
Modelos de cadena de responsabilidad pura e impura
Un modelo de cadena de responsabilidad pura requiere que un objeto procesador específico solo pueda elegir una de dos acciones: una es asumir la responsabilidad, pero pasarla a la siguiente parte. No está permitido que un objeto procesador específico transmita la responsabilidad después de asumir algunas responsabilidades.
En un modelo de cadena de responsabilidad pura, una solicitud debe ser recibida por un objeto controlador; en un modelo de cadena de responsabilidad impura, ninguna solicitud puede ser recibida por ningún objeto receptor.
Es difícil encontrar ejemplos reales del modelo de cadena de responsabilidad pura, y los ejemplos que se ven generalmente son implementaciones del modelo de cadena de responsabilidad impura. Algunas personas piensan que una cadena de responsabilidad impura no es en absoluto un modelo de cadena de responsabilidad, y esto puede tener sentido. Pero en los sistemas reales es difícil encontrar una cadena pura de responsabilidad. Si insistes en que la cadena de responsabilidad es impura, no es un modelo de cadena de responsabilidad, entonces el modelo de cadena de responsabilidad no tendrá mucho sentido.
Aplicación del modelo de cadena de responsabilidad en Tomcat.
Como todos sabemos, Filter en Tomcat utiliza el modelo de cadena de responsabilidad. Además de realizar las configuraciones correspondientes en el archivo web.xml, crear un Filter también requiere implementar la interfaz javax.servlet.Filter.
Copie el código de código de la siguiente manera:
la clase pública TestFilter implementa el filtro {
doFilter público vacío (solicitud ServletRequest, respuesta ServletResponse,
cadena FilterChain) arroja IOException, ServletException {
chain.doFilter (solicitud, respuesta);
}
destrucción del vacío público () {
}
public void init (FilterConfig filterConfig) lanza ServletException {
}
}
Los resultados vistos usando el modo DEBUG son los siguientes:
De hecho, antes de ejecutar la clase TestFilter, pasará por muchas clases internas de Tomcat. Por cierto, la configuración del contenedor de Tomcat también es un modelo de cadena de responsabilidad. Preste atención a las clases rodeadas por el cuadro rojo. Desde el motor hasta el host, el contexto y el contenedor, las solicitudes se pasan a través de una cadena. Hay una clase llamada ApplicationFilterChain en el lugar rodeado por el cuadro verde. La clase ApplicationFilterChain desempeña el papel de procesador abstracto, y cada filtro desempeña el papel de procesador específico.
La primera pregunta es ¿dónde almacena ApplicationFilterChain todos los filtros?
La respuesta se almacena en una matriz de objetos ApplicationFilterConfig en la clase ApplicationFilterChain.
Copie el código de código de la siguiente manera:
/**
*Filtros.
*/
filtros privados ApplicationFilterConfig[] =
nuevo ApplicationFilterConfig[0];
Entonces, ¿qué es el objeto ApplicationFilterConfig?
ApplicationFilterConfig es un contenedor de filtro. La siguiente es la declaración de la clase ApplicationFilterConfig:
Copie el código de código de la siguiente manera:
/**
* Implementación de un <code>javax.servlet.FilterConfig</code> útil en
* gestionar las instancias de filtro instanciadas cuando una aplicación web
* se inicia por primera vez.
*
* @autor Craig R. McClanahan
* @version $Id: ApplicationFilterConfig.java 1201569 2011-11-14 01:36:07Z kkolinko $
*/
ApplicationFilterConfig se crea una instancia automáticamente cuando se inicia una aplicación web por primera vez. Lee la información del filtro configurado del archivo web.xml de la aplicación web y luego la carga en el contenedor.
Acabo de ver que la longitud de la matriz ApplicationFilterConfig creada en la clase ApplicationFilterChain es cero. ¿Cuándo se reasignó?
Copie el código de código de la siguiente manera:
filtros privados ApplicationFilterConfig[] =
nuevo ApplicationFilterConfig[0];
Es cuando se llama al método addFilter() de la clase ApplicationFilterChain.
Copie el código de código de la siguiente manera:
/**
* El int que proporciona el número actual de filtros en la cadena.
*/
privado int n = 0;
public static final int INCREMENT = 10;
Copie el código de código de la siguiente manera:
void addFilter(ApplicationFilterConfig filterConfig) {
// Evita que se agregue el mismo filtro varias veces
para (filtro ApplicationFilterConfig: filtros)
si(filtro==filtroConfig)
devolver;
if (n == filtros.longitud) {
ApplicationFilterConfig[] nuevosfiltros =
nuevo ApplicationFilterConfig[n + INCREMENT];
System.arraycopy(filtros, 0, nuevosfiltros, 0, n);
filtros = nuevosFiltros;
}
filtros[n++] = filterConfig;
}
La variable n se utiliza para registrar el número de filtros en la cadena de filtros actual. De forma predeterminada, n es igual a 0 y la longitud de la matriz de objetos ApplicationFilterConfig también es igual a 0, por lo que cuando se llama al método addFilter (). la primera vez, si (n == filtros .length) es verdadero y se cambia la longitud de la matriz ApplicationFilterConfig. Luego filters[n++] = filterConfig; coloque la variable filterConfig en la matriz ApplicationFilterConfig y agregue 1 al número de filtros en la cadena de filtros actual.
Entonces, ¿dónde se llama el método addFilter() de ApplicationFilterChain?
Está en el método createFilterChain() de la clase ApplicationFilterFactory.
Copie el código de código de la siguiente manera:
ApplicationFilterChain pública crearFilterChain
(Solicitud ServletRequest, contenedor Wrapper, servlet Servlet) {
// obtener el tipo de despachador
Despachador DispatcherType = nulo;
si (request.getAttribute(DISPATCHER_TYPE_ATTR) != nulo) {
despachador = (DispatcherType) request.getAttribute(DISPATCHER_TYPE_ATTR);
}
Cadena requestPath = nulo;
Atributo del objeto = request.getAttribute(DISPATCHER_REQUEST_PATH_ATTR);
si (atributo! = nulo) {
requestPath = atributo.toString();
}
// Si no hay ningún servlet para ejecutar, devuelve nulo
si (servlet == nulo)
retorno (nulo);
cometa booleano = falso;
// Crea e inicializa un objeto de cadena de filtro
ApplicationFilterChain filterChain = nulo;
if (solicitud instancia de Solicitud) {
Solicitud de solicitud = (Solicitud) solicitud;
cometa = req.isCometa();
si (Globals.IS_SECURITY_ENABLED) {
// Seguridad: No reciclar
filterChain = nueva AplicaciónFilterChain();
si (cometa) {
req.setFilterChain (cadena de filtro);
}
} demás {
filterChain = (ApplicationFilterChain) req.getFilterChain();
if (cadenafiltro == nulo) {
filterChain = nueva AplicaciónFilterChain();
req.setFilterChain (cadena de filtro);
}
}
} demás {
//Solicitar despachador en uso
filterChain = nueva AplicaciónFilterChain();
}
filterChain.setServlet(servlet);
filterChain.setSoporte
(((StandardWrapper)wrapper).getInstanceSupport());
// Adquirir las asignaciones de filtro para este contexto
Contexto StandardContext = (StandardContext) wrapper.getParent();
FilterMap filterMaps[] = contexto.findFilterMaps();
// Si no hay asignaciones de filtros, hemos terminado
if ((filterMaps == nulo) || (filterMaps.length == 0))
retorno (cadena de filtro);
// Adquirir la información que necesitaremos para hacer coincidir las asignaciones de filtros
Cadena servletName = wrapper.getName();
// Agrega los filtros de ruta relevantes a esta cadena de filtros
para (int i = 0; i < filterMaps.length; i++) {
if (!matchDispatcher(filterMaps[i], despachador)) {
continuar;
}
if (!matchFiltersURL(filterMaps[i], requestPath))
continuar;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
si (filterConfig == nulo) {
// FIXME - problema de configuración del registro
continuar;
}
booleano esCometFilter = falso;
si (cometa) {
intentar {
isCometFilter = filterConfig.getFilter() instancia de CometFilter;
} captura (Excepción e) {
// Nota: El try catch está ahí porque getFilter tiene muchos
// excepciones declaradas Sin embargo, al filtro se le asigna mucho.
// más temprano
Lanzable t = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(t);
}
si (esCometFilter) {
filterChain.addFilter(filterConfig);
}
} demás {
filterChain.addFilter(filterConfig);
}
}
// Agregar filtros que coincidan con el nombre del servlet en segundo lugar
para (int i = 0; i < filterMaps.length; i++) {
if (!matchDispatcher(filterMaps[i], despachador)) {
continuar;
}
if (!matchFiltersServlet(filterMaps[i], servletName))
continuar;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
si (filterConfig == nulo) {
// FIXME - problema de configuración del registro
continuar;
}
booleano esCometFilter = falso;
si (cometa) {
intentar {
isCometFilter = filterConfig.getFilter() instancia de CometFilter;
} captura (Excepción e) {
// Nota: El try catch está ahí porque getFilter tiene muchos
// excepciones declaradas. Sin embargo, al filtro se le asigna mucho.
// más temprano
}
si (esCometFilter) {
filterChain.addFilter(filterConfig);
}
} demás {
filterChain.addFilter(filterConfig);
}
}
// Devuelve la cadena de filtros completa
retorno (cadena de filtro);
}
El código anterior se puede dividir en dos secciones, la primera sección antes de la línea 51 y la segunda sección después de la línea 51.
El objetivo principal del primer párrafo es crear el objeto ApplicationFilterChain y establecer algunos parámetros.
El objetivo principal del segundo párrafo es obtener toda la información del filtro del contexto y luego usar un bucle for para recorrer y llamar a filterChain.addFilter(filterConfig); colocar filterConfig en la matriz ApplicationFilterConfig del objeto ApplicationFilterChain.
Entonces, ¿dónde se llama el método createFilterChain() de la clase ApplicationFilterFactory?
Se llama en el método invoke() de la clase StandardWrapperValue.
Dado que el método invoke() es largo, se omiten muchos lugares.
Copie el código de código de la siguiente manera:
invocación pública final de anulación (solicitud de solicitud, respuesta de respuesta)
lanza IOException, ServletException {
...Omitir código intermedio // Crear la cadena de filtros para esta solicitud
fábrica de ApplicationFilterFactory =
ApplicationFilterFactory.getInstance();
Cadena de filtro de aplicación cadena de filtro =
factory.createFilterChain (solicitud, contenedor, servlet);
...omitir código intermedio
filterChain.doFilter(request.getRequest(), respuesta.getResponse());
...omitir código intermedio
}
El proceso normal debería ser así:
Llame al método createFilterChain() de la clase ApplicationFilterChai en el método invoke() de la clase StandardWrapperValue ---> llame al método addFilter() de la clase ApplicationFilterChain en el método createFilterChain() de la clase ApplicationFilterChai ---> llame al Método addFilter() de la clase ApplicationFilterChain Asigne un valor a la matriz ApplicationFilterConfig.
De acuerdo con el código anterior, se puede ver que el método invoke () de la clase StandardWrapperValue continuará ejecutando el método doFilter () de la clase ApplicationFilterChain después de ejecutar el método createFilterChain (), y luego el método internalDoFilter () llamado en el método doFilter().
Lo siguiente es parte del código del método internalDoFilter()
Copie el código de código de la siguiente manera:
// Llama al siguiente filtro si lo hay
si (pos < n) {
//Obtiene el siguiente filtro y mueve el puntero una posición hacia abajo
// pos identifica qué filtro ejecuta la ApplicationFilterChain actual (cadena de filtros actual)
ApplicationFilterConfig filterConfig = filtros[pos++];
Filtro de filtro = nulo;
intentar {
//Obtener la instancia del filtro actualmente apuntado
filtro = filterConfig.getFilter();
support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
filtro, solicitud, respuesta);
si (request.isAsyncSupported() && "falso".equalsIgnoreCase(
filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
Booleano.FALSO);
}
si(Globals.IS_SECURITY_ENABLED) {
solicitud final de ServletRequest = solicitud;
final ServletResponse res = respuesta;
Director principal =
((HttpServletRequest) req).getUserPrincipal();
Objeto[] args = nuevo Objeto[]{req, res, esto};
SecurityUtil.doAsPrivilege
("doFilter", filtro, tipo de clase, argumentos, principal);
} demás {
//Llamar al método doFilter() de Filter
filter.doFilter(solicitud, respuesta, esto);
}
El filter.doFilter(solicitud, respuesta, esto); aquí es para llamar al método doFilter() en el TestFilter que creamos anteriormente. El método doFilter() en TestFilter continuará llamando al método chain.doFilter(solicitud, respuesta), y esta cadena es en realidad ApplicationFilterChain, por lo que el proceso de llamada vuelve a llamar al dofilter y al método internalDoFilter anterior, y esto. la ejecución continúa hasta que el filtro dentro Ejecutarlos todos.
Si se definen dos filtros, los resultados de la depuración son los siguientes: