Workflow
load DispatcherServlet
Tracing source code , Finally know that this is also related to Servlet Have something to do with , To complete a user's request , The first step is to load DispatcherServlet, Let's introduce the process :
class DispatcherServlet extends FrameworkServlet … ——>
class FrameworkServlet extends HttpServletBean … ——>
class HttpServletBean extends HttpServlet … ——>
class HttpServlet extends GenericServlet … ——>
abstract class GenericServlet implements Servlet …
analysis :
We look from bottom to top , Can know Servlet Is an interface , that Servlet What the hell is it , To put it bluntly, it is the technology of developing dynamic websites ,Sun The company in its API One is provided in servlet Interface , If users want to send a dynamic web resources ( That is, develop a Java The program outputs data to the browser ), You need to complete the following 2 Steps :
* Write a Java class , realization servlet Interface .
* Put the developed Java Class deployed to web Server .
Do you understand , In fact, when designing something, you often leave some questions , Because nothing can be designed at one time , For example, a good program is often updated , therefore Sun The company also provides two class implementations Servlet Interface , yes HttpServlet and GenericServlet, among
HttpServlet
Can handle HTTP Requested servlet, It's in the original Servlet Some interfaces with HTTP Protocol processing method , Its ratio Servlet Interface is more powerful . So developers are writing Servlet Time , You should normally inherit this class , And avoid direct implementation Servlet Interface . and
GenericServlet
The existence of this class makes writing Servlet More convenient . It provides a simple solution , This program is used to implement the relevant Servlet Method of life cycle and its application in initialization ServletConfig Object and ServletContext Object .
DispatcherServlet of init() method ( Initialization method ) In its parent class HttpServletBean
Medium implementation , The main function is loading web.xml( General profile ) in DispatcherServlet Configuration of , And call the initialization of subclasses .
* init() @Override public final void init() throws ServletException { // Set
bean properties from init parameters. PropertyValues pvs = new
ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); if (!
pvs.isEmpty()) { try { BeanWrapper bw = PropertyAccessorFactory.
forBeanPropertyAccess(this); ResourceLoader resourceLoader = new
ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(
Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
initBeanWrapper(bw); bw.setPropertyValues(pvs, true); } catch (BeansException ex
) { if (logger.isErrorEnabled()) { logger.error("Failed to set bean properties
on servlet '" + getServletName() + "'", ex); } throw ex; } } // Let subclasses
do whatever initialization they like. initServletBean(); }
stay HttpServletBean of init() Method is called initServletBean() method , This method is used in FrameworkServlet
Class , The main function is to establish WebApplicationContext container .
* initServletBean() Source code @Override protected final void initServletBean() throws
ServletException { getServletContext().log("Initializing Spring " + getClass().
getSimpleName() + " '" + getServletName() + "'"); if (logger.isInfoEnabled()) {
logger.info("Initializing Servlet '" + getServletName() + "'"); } long startTime
= System.currentTimeMillis(); try { this.webApplicationContext =
initWebApplicationContext(); initFrameworkServlet(); } catch (ServletException |
RuntimeException ex) { logger.error("Context initialization failed", ex); throw
ex; } if (logger.isDebugEnabled()) { String value = this.
enableLoggingRequestDetails? "shown which may lead to unsafe logging of
potentially sensitive data" : "masked to prevent unsafe logging of potentially
sensitive data"; logger.debug("enableLoggingRequestDetails='" + this.
enableLoggingRequestDetails+ "': request parameters and headers will be " +
value); } if (logger.isInfoEnabled()) { logger.info("Completed initialization
in " + (System.currentTimeMillis() - startTime) + " ms"); } }
* Initialization operation WebApplicationContext
initWebApplicationContext() Method is mainly used to create and refresh WebApplicationContext example , And to Servlet Initialize the variables used by the function .
initWebApplicationContext() Source code protected WebApplicationContext
initWebApplicationContext() { WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null; if (this.webApplicationContext != null) { //
A context instance was injected at construction time -> use it wac = this.
webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac
; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide
services such as // setting the parent context, setting the application context
id, etc if (cwac.getParent() == null) { // The context instance was injected
without an explicit parent -> set // the root application context (if any; may
be null) as the parent cwac.setParent(rootContext); }
configureAndRefreshWebApplicationContext(cwac); } } } if (wac == null) { // No
context instance was injected at construction time -> see if one // has been
registered in the servlet context. If one exists, it is assumed // that the
parent context (if any) has already been set and that the // user has performed
any initialization such as setting the context id wac =
findWebApplicationContext(); } if (wac == null) { // No context instance is
defined for this servlet -> create a local one wac = createWebApplicationContext
(rootContext); } if (!this.refreshEventReceived) { // Either the context is not
a ConfigurableApplicationContext with refresh // support or the context
injected at construction time had already been // refreshed -> trigger initial
onRefresh manually here. synchronized (this.onRefreshMonitor) { onRefresh(wac);
} } if (this.publishContext) { // Publish the context as a servlet context
attribute. String attrName = getServletContextAttributeName(); getServletContext
().setAttribute(attrName, wac); } return wac; }
* Well established WebApplicationContext after , adopt onRefresh(ApplicationContext context) Method callback , get into
DispatcherServlet In class , Because in DispatcherServlet Exists in class onRefresh() method .
onRefresh()
@Override protected void onRefresh(ApplicationContext context) { initStrategies
(context); }
initStrategies() be responsible for SpringMVC Initialization of nine components .
initStrategies()
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(
context); initHandlerMappings(context); initHandlerAdapters(context);
initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context)
; initViewResolvers(context); initFlashMapManager(context); }
This is the first step .
If not configured HandlerMapping,HandlerAdapter,ViewResolver The component will be used
DispatcherServlet.properties Default components in file .
DispatcherServlet.properties The contents of the document are as follows
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet
context. # Not meant to be customized by application developers.
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
org.springframework.web.servlet.function.support.RouterFunctionMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
org.springframework.web.servlet.function.support.HandlerFunctionAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
Then there is DispatcherServlet call HandlerMapping To handle request( request ) and handler( handle )
Mapping relationship between , call HandlerMapping Class getHandler() , and handler Packaged into
HandlerExecutionChain class , that is HandlerMapping Directly with HandlerExecutionChain Deal with ,
HandlerMapping of getHandler() The source code is as follows :
@Nullable HandlerExecutionChain getHandler(HttpServletRequest request) throws
Exception;
Can know , Indeed, with HandlerExecutionChain Deal directly with , Called its getHandler method , And so are the method parameters request
, This corresponds to HandlerMapping Yes, it is request and handler Mapping relationship between ,
HandlerExecutionChain of getHandler() The source code is as follows :
public Object getHandler() { return this.handler; }
Now you get the real handler( So called processor objects ).
HandlerExecutionChain This class can also be said to be handler execution chain , Contains handler and interceptor ,handler from
getHandler() Method can be obtained ,interceptor from getInterceptors() Method can be obtained , So the configuration file may also be added here .
Get handler Will be based on url,method,context-type Wait to find the corresponding controller (controller), Then call
getHandlerAdapter() Method obtained HandlerAdapter,
getHandlerAdapter() Source code
protected HandlerAdapter getHandlerAdapter(Object handler) throws
ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter
adapter: this.handlerAdapters) { if (adapter.supports(handler)) { return adapter
; } } } throw new ServletException("No adapter for handler [" + handler + "]:
The DispatcherServlet configuration needs to include a HandlerAdapter that
supports this handler"); }
stay HandlerAdapter Called first in supports() Method to determine whether the is supported handler , If it is supported, the specific operation is performed through adaptation Controller
,Controller Put the specific results of request processing into ModelAndView in ,handler Send results to ViewResolver
The final result of rendering analysis is returned to the user .
Technology