preface
When sending an HTTP request, Spring MVC will perform a series of processing after receiving it, and then respond to the resource. How is the whole process handled?
Execution process
Core components
Dispatcher servlet: front-end controller, which does not need to be developed by engineers. It is provided by the framework to uniformly process requests and responses. It is the center of the whole process control, which calls other components to process user requests
Handler mapping: a processor mapper, which does not need to be developed by an engineer. It is provided by the framework. It finds the handler, that is, the controller method, according to the requested url, method and other information
Handler: processor, which needs to be developed by engineers. Under the control of dispatcher servlet, handler processes specific user requests
HandlerAdapter: processor adapter. It does not need to be developed by engineers. It is provided by the framework. The processor (controller method) is executed through HandlerAdapter
ViewResolver: a view parser, which does not need to be developed by an engineer. It is provided by the framework to parse the view and obtain the corresponding views, such as ThymeleafView, InternalResourceView and RedirectView
View: a view that displays model data to users through a page
technological process
- The user initiates a request and enters the front-end controller DispatcherServlet;
- DispatcherServlet request processing mapper HandlerMapping lookup Handler;
- HandlerMapping finds the matching Handler according to the url requested by the user (that is, a method configured with the corresponding path in the Controller) and returns an execution chain;
- The dispatcher servlet then requests the Handler adapter to execute the Handler;
- Handler is executed;
- Handler returns ModelAndView object;
- HandlerAdapter returns ModelAndView to DispatcherServlet;
- Dispatcher servlet requests View resolver to parse the view;
- The View resolver matches the corresponding View result according to the View information and returns it;
- After receiving the View, the dispatcher servlet renders the View, fills the data in the Model into the request area in the View, and generates the final View;
- Return response.
Core class
Servlet in JDK
You can view the information about servlets file.
The servlet interface is located under the javax.servlet package and defines the methods that all servlets must implement. Servlets are small Java programs that run in a Web server. Servlets receive and respond to requests from Web clients, usually through HTTP and hypertext transfer} protocol.
The ServletConfig interface is also located under the javax.servlet package and contains Servlet configuration and initialization parameters, which are passed to the init method during Servlet initialization.
The ServletContext interface is also located under the javax.servlet package. ServletContext is officially called servlet context. The server will create an object for each project, which is the ServletContext object. This object is globally unique, and all servlets within the project share this object. So it is called global application sharing object.
The functions of ServletContext are as follows:
-
Is a domain object
-
Global configuration parameters can be read
-
You can search the resource files under the current project directory
-
You can get the name of the current project
The ServletRequest interface defines an object to provide client request information to the servlet. The servlet container creates a ServletRequest object and passes it as a parameter to the service method of the servlet. The ServletRequest object provides data including parameter names and values, attributes, and input streams. The interface of servletrequests can provide additional protocol specific data (for example, HTTP data is provided by javax.servlet.http.HttpServletRequest).
The ServletResponse interface defines an object to help the servlet send a response to the client. The servlet container creates a ServletResponse object and passes it as a parameter to the service method of the servlet. To send binary data in a MIME body response, use the {@ link ServletOutputStream} returned by {@ link #getOutputStream}. To send character data, use the PrintWrite object returned by * {@ link #getWriter}. For example, to mix binary and text data to create a multipart response, use ServletOutputStream and manually manage character parts.
GenericServlet abstract class
GenericServlet abstract class implements Servlet and ServletConfig interface, and defines a general and protocol independent Servlet. The new Servlet program directly inherits GenericServlet, which will make the development more concise. To write a generic Servlet, you simply override the abstract service method.
HttpServlet abstract class
HttpServlet abstract class inherits GenericServlet and is customized for HTTP protocol. In service() method, directly convert ServletReuqest and ServletResponse into HttpServletRequest and HttpServletResponse.
There are many constants that define the HTTP request method:
private static final String METHOD_DELETE = "DELETE"; private static final String METHOD_HEAD = "HEAD"; private static final String METHOD_GET = "GET"; private static final String METHOD_OPTIONS = "OPTIONS"; private static final String METHOD_POST = "POST"; private static final String METHOD_PUT = "PUT"; private static final String METHOD_TRACE = "TRACE"; private static final String HEADER_IFMODSINCE = "If-Modified-Since"; private static final String HEADER_LASTMOD = "Last-Modified"; private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings"; private static ResourceBundle lStrings = ResourceBundle.getBundle(LSTRING_FILE);
HttpServlet defines a series of methods for HTTP request processing.
Servlet in Spring
Spring Web MVC is a Web framework originally built on the Servlet API.
From the source code, we can see that the code of the spring webmvc module is under the servlet package.
HttpServletBean abstract class
The HttpServlet bean abstract class implements the EnvironmentCapable and EnvironmentAware interfaces, and inherits the HttpServlet class.
His main functions are:
- Extend HttpServlet and re init method.
- The EnvironmentAware interface is implemented to rewrite the setEnvironment method.
- Implements the EnvironmentCapable interface and overrides the getEnvironment method.
The init method mainly obtains the configuration attributes in web.xml and sets these attributes to the object of HttpServletBean.
The two interfaces implemented are to provide getter and setter methods for the Environment, which is the Environment in which the servlet runs, including profile and properties.
FrameworkServlet abstract class
The FrameworkServlet abstract class is the basic servlet of Spring's web framework, inherits the HttpServletBean class and implements ApplicationContextAware.
ApplicationContextAware can get applicationContext and set it into the current object.
FrameworkServlet has a very important method initServletBean. This method is a hook method in the parent HttpServletBean, that is, it is defined in the parent class, but implemented in the child class.
initServletBean will call the initWebApplicationContext method to initialize a WebApplicationContext. Then we call the initFrameworkServlet method. This method is also a hook method. There is only one empty implementation in the current class, and the real implementation is in the subclass DispatcherServlet.
Dispatcher servlet class
The dispatcher servlet class inherits from the FrameworkServlet abstract class. It is the central scheduler of the HTTP request handler in MVC. Registered handlers can be scheduled to handle a web request, providing mapping and exception handling facilities. This servlet is very flexible: it can be used for almost any workflow.
Its entire inheritance relationship is as follows:
First, take a look at the constants defined in the dispatcher servlet:
// The well-known name of the MultipartResolver object in the bean factory of this namespace public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver"; // The well-known name of the LocaleResolver object in the bean factory of this namespace public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver"; // The well-known name of the ThemeResolver object in the bean factory of this namespace public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver"; // The well-known name of the HandlerMapping object in the bean factory of this namespace public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping"; // The well-known name of the HandlerAdapter object in the bean factory of this namespace public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter"; // The well-known name of the HandlerExceptionResolver object in the bean factory of this namespace public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver"; // The well-known name of the RequestToViewNameTranslator object in the bean factory of this namespace public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator"; // The well-known name of the ViewResolver object in the bean factory of this namespace public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver"; // The well-known name of the FlashMapManager object in the bean factory of this namespace public static final String FLASH_MAP_MANAGER_BEAN_NAME = "flashMapManager"; // Request properties to save the current Web application context public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.class.getName() + ".CONTEXT"; // Request properties to save the current LocaleResolver, which can be retrieved from the view public static final String LOCALE_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".LOCALE_RESOLVER"; // Request properties to save the current ThemeResolver, which can be retrieved from the view public static final String THEME_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_RESOLVER"; public static final String THEME_SOURCE_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_SOURCE"; public static final String INPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".INPUT_FLASH_MAP"; public static final String OUTPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".OUTPUT_FLASH_MAP"; public static final String FLASH_MAP_MANAGER_ATTRIBUTE = DispatcherServlet.class.getName() + ".FLASH_MAP_MANAGER"; public static final String EXCEPTION_ATTRIBUTE = DispatcherServlet.class.getName() + ".EXCEPTION"; // The log category to use when the requested mapping handler cannot be found public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound"; // The name of the classpath resource (relative to the DispatcherServlet class) defines the default policy name of the DispatcherServlet. private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties"; // Public prefix starting from the default policy attribute of the dispatcher servlet private static final String DEFAULT_STRATEGIES_PREFIX = "org.springframework.web.servlet"; protected static final Log pageNotFoundLogger = LogFactory.getLog("org.springframework.web.servlet.PageNotFound");
Then look at the properties:
@Nullable // Storage default policy implementation private static Properties defaultStrategies; // Detect all handlerMapping or just expect "handlerMapping" bean s? private boolean detectAllHandlerMappings = true; // Detect all handleradapters or only expect "handlerAdapter" bean s? private boolean detectAllHandlerAdapters = true; // Detect all handlerexceptionresolvers or only expect "handlerExceptionResolver" bean s? private boolean detectAllHandlerExceptionResolvers = true; // Detect all viewresolvers or only expect "viewResolver" bean s? private boolean detectAllViewResolvers = true; // If no handler is found to handle this request, throw NoHandlerFoundException? private boolean throwExceptionIfNoHandlerFound = false; // Perform cleanup of request properties after the request is included? private boolean cleanupAfterInclude = true; // Resolvers parser @Nullable private MultipartResolver multipartResolver; @Nullable private LocaleResolver localeResolver; @Nullable private ThemeResolver themeResolver; @Nullable // HandlerMapping collection private List<HandlerMapping> handlerMappings; @Nullable // HandlerAdapter collection private List<HandlerAdapter> handlerAdapters; @Nullable private List<HandlerExceptionResolver> handlerExceptionResolvers; @Nullable private RequestToViewNameTranslator viewNameTranslator; @Nullable private FlashMapManager flashMapManager; @Nullable private List<ViewResolver> viewResolvers; private boolean parseRequestPath;
Core approach:
- initStrategies(), which is responsible for initializing the policies used by this servlet. You can see that many init methods are called for initialization. This method will be called when the FrameworkServlet calls initWebApplicationContext when initializing ApplicationContext.
protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
-
The doService method is the entrance for us to process requests. It mainly sets some parsers in the Request, and the real Request processing is in the doDispatch method.
-
doDispatch is the core method for processing requests and scheduling. The specific logic processing process will be introduced later