Todos los beans de Spring Framework se duplican, debido al contexto doble (servlet + ContextLoaderListener)

  • Si creo el contexto de Spring por el servlet del despachador , recibí un error en el filtro DelegatingFilterProxy :

     java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered? org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:251) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) org.apache.logging.log4j.core.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:66) 
  • Si creo un contexto de resorte por ContextLoaderListener , simplemente tengo un error de 404 porque no hay un servlet

  • Si creo el contexto de Spring by servlet y listener , tengo un contexto duplicado, por lo que todos los beans están duplicados, incluidos los controladores con asignaciones de solicitud, los métodos @Scheduled doble ejecución, etc.

¿Cómo crear una aplicación Spring avanzada (incluyendo muchos filtros, etc.) sin duplicar el contexto?

Mi web.xml:

   MyWebApplication  springDispatcher org.springframework.web.servlet.DispatcherServlet  contextConfigLocation /WEB-INF/spring.xml  1   springDispatcher /    org.springframework.web.context.ContextLoaderListener    contextConfigLocation  /WEB-INF/spring.xml     encoding-filter  org.springframework.web.filter.CharacterEncodingFilter   encoding UTF-8   forceEncoding true    encoding-filter /*    springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy   springSecurityFilterChain /*   

Si usa filtros de servlet relacionados con Spring y también usa controladores mvc, entonces necesita ambos:

  • ContextLoaderListener Y
  • DispatcherServlet-spring-configuration

(Ver ContextLoaderListener o no? )

Ambos crean su propio contexto de servlet. El ContextLoaderListener crea el contexto padre (a veces llamado el contexto interno). Y el DispatcherServlet crea un contexto secundario (del contexto principal) (a veces denominado contexto externo). Los beans del contexto hijo pueden acceder a los beans del contexto padre, pero no al revés.

En una aplicación web no demasiado simple, necesita ambos contextos, porque hay muchos filtros de servlet que requieren un contexto de resorte ya creado. Por otro lado, todas las cosas del controlador necesitan un ServletContext, y esto solo lo crea el Servlet Dispatcher.

Otro punto es que no debe haber creado cada bean dos veces (a veces esto no es un problema, otras veces lo es). Por lo tanto, debe tener dos configuraciones de resorte, una para el contexto interno, una para el otro contexto. Y debe decidir para cada bean si pertenece al contexto interno o externo.

La regla de oro es: poner todas las cosas en el contexto interno, excepto las cosas que requieren un contexto Servlet o que están fuertemente ligadas a la interfaz web, como los controladores MVC, la configuración de Tiles, …