Currently, DispatcherServlet#initHandlerMappings
is initialized in org.springframework.web.servlet.HttpServletBean#init
, But it is already executed in the servlet thread http-nio-8081-exec-1
,I hope it can be executed in advance to play the role of preloading,In this way, I can also get HandlerMapping
earlier through DispatcherServlet#getHandlerMappings
for example:DispatcherServlet can impl SmartInitializingSingleton and invoke DispatcherServlet#initHandlerMappings
in method SmartInitializingSingleton#afterSingletonsInstantiated
Comment From: poutsma
initHandlerMappings
is called by Servlet::init
, part of the Servlet environment (i.e. Tomcat). Servlet::init
is called by the servlet container to indicate to a servlet that the servlet is being placed into service. Before init
is called, the ServletConfig
is not yet available, and that's required for the web application context to be instantiated. Therefore, init
is the earliest possible moment where Spring Framework can safely instantiate beans such as handler mappings.
Comment From: brucelwl
@poutsma
but we can get the ServletContext
before Servlet::init
For example, implement the following interfaces:
javax.servlet.ServletContainerInitializer#onStartup(Set<Class<?>> c, ServletContext ctx)
和javax.servlet.ServletContextListener#contextInitialized(ServletContextEvent sce)
Comment From: poutsma
What problem are you trying to solve by having the HandlerMappings
available earlier than Servlet::init
?
Comment From: brucelwl
What problem are you trying to solve by having the
HandlerMappings
available earlier thanServlet::init
?
Because I want to intercept the handler
corresponding to the httpServletRequest
through the javax.servlet.Filter
, so I can add my own current limit statistics to the handler
. Therefore, I must know all HandlerMapping
, Coincidentally, I found that all HandlerMapping
will be loaded in DispatcherServlet
, and method DispatcherServlet#getHandlerMappings
is also provided, but the initialization time is a little over
Comment From: brucelwl
What problem are you trying to solve by having the
HandlerMappings
available earlier thanServlet::init
?
In addition, loading HandlerMapping
in advance can warm up, instead of initializing the HandlerMapping
after the user request arrives, because it is locked in the servlet thread http-nio-8081-exec-xxx
, so the first request will be slow.
Therefore, it is suggested that the whole method DispatcherServlet#initStrategies(applicationContext)
should be initialized in advance, not in the servlet thread
Comment From: brucelwl
@poutsma Can you tell me how to deal with this issue in the future?
Comment From: poutsma
Looking at the code you shared, I think you're running into problems because your component is dependant on the Servlet lifecycle as well as the Spring lifecycle.
So, instead of implementing a Servlet Filter
, you should consider implementing org.springframework.web.servlet.HandlerInterceptor
, as handler interceptor are Spring components that live in the Spring lifecycle. Then, you can simply detect the handler mappings in your ApplicationContextAware::setApplicationContext
implementation, which will be called before your HandlerInterceptor
method implementations. I would also not implement SmartLifecycle
, as all the initialization you need can be done in setApplicationContext
.
As for the suggestion made in your original comment: DispatcherServlet
is a Servlet that is instantiated by the web container (i.e. Tomcat). DispatcherServlet
is not a Spring Bean, and therefore implementing SmartInitializingSingleton
will not work.
As for implementing ServletContainerInitializer
: I don't think that's going to help either, because Filters are executed (and initialized) before Servlets are, so you will most likely face the same problem of the servlet not being initialized yet. By implementing a handler interceptor as I suggested above, you are part of the same lifecycle of the DispatcherServlet
that you're trying to query, so that seems the best way forward.