1. MVC framework
1.1 FrontController: DispatcherServlet
FrontController
Namely Spring Provided DispatcherServlet
, and No Spring Provided @Controller
,xml The configuration file needs to specify Tomcat Load this… First at startup Servlet Mapping path write /
, Forward all requests
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--tomcat When it starts , Load this... First Servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
DispatcherServlet
It’s essentially a HttpServlet
track HttpServlet.service() Method call chain
-
FrameworkServlet
Inherited from the parent classHttpServlet.service
,Spring The expansion realization ofprocessRequest
FrameworkServlet.processRequest
,==Spring Will block all types of requests , Include HttpServlet There is no definition in ,== Keep trackingprocessRequest
The implementation of the@Override protected void service(HttpServletRequest request, HttpServletResponse response) { HttpMethod httpMethod = HttpMethod.resolve(request.getMethod()); if (httpMethod == HttpMethod.PATCH || httpMethod == null) { processRequest(request, response); } else { super.service(request, response); } }
-
FrameworkServlet.processRequest
CombineddoService
Logicprotected final void processRequest(HttpServletRequest request, HttpServletResponse response) { try { doService(request, response); } // Leave it for later research publishRequestHandledEvent(request, response, startTime, failureCause); } }
-
FrameworkServlet
Abstract method ofdoService
Is left to subclasses Must be realized , That is to sayDispatcherServlet.doService()
protected abstract void doService(HttpServletRequest request, HttpServletResponse response);
/** * DispatcherServlet.doService() * */ @Override protected void doService(HttpServletRequest request, HttpServletResponse response) { // Omit data preparation try { doDispatch(request, response); } }
track FrameworkServlet.doPost() / doGet() …
FrameworkServlet.doGet/doPost/..
Use… Without exception processRequest The implementation of the , That is to say DispatcherServlet.doService
To explore the FrameworkServlet.service() Template method implementation
-
super.service()
Using the template design pattern ,Spring Compatible with PATCH The implementation of the , Give the rest to HttpServlet The template of service()
@Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpMethod httpMethod = HttpMethod.resolve(request.getMethod()); if (httpMethod == HttpMethod.PATCH || httpMethod == null) { processRequest(request, response); } else { super.service(request, response); } }
-
HttpServlet.service()
Templates , No concrete implementation . becauseFrameworkServlet.doGet/doPost..
It’s all coveredHttpServlet The implementation of the
, One Get The request went through DispatcherServlet after , There are the following processesFrameworkServlet.service()
->super.service()
->FrameworkServlet.doGet()
->
FrameworkServlet.processRequest()
->DispatcherServlet.doService
->
DispatcherServlet.doDispatch()
/** * super.service() Always call to HttpServlet Template method * */ protected void service(HttpServletRequest req, HttpServletResponse resp) { String method = req.getMethod(); if (method.equals(METHOD_GET)) { doGet(req, resp); } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } }
Summary
DispatcherServlet
As MVC Front end controller in Architecture , It’s also the core controller , adopt HttpServlet.service()
The template mode puts the request Forward to Spring ,DispatcherServlet.doService() Subsequent analysis
,
About DispatcherServlet
Other parents of , The role of online collection :
-
HttpServletBean, yes FrameworkServlet Parent class of
Mainly do some initialization work , take web.xml The parameters configured in are set to Servlet in . such as servlet Child of the tag init-param Parameters configured in the tag .
-
FrameworkServlet
take Servlet And Spring Container context . In fact, initialization FrameworkServlet Properties of
webApplicationContext
, This property represents SpringMVC Context , It has a parent contextServletContext
, Both web.xml Configured in ContextLoaderListener Listener initialized container context . -
DispatcherServlet ( It will be mentioned later )
Initialize the implementation classes of each function . Like exception handling 、 The view 、 Request mapping processing, etc .
2. MVC Interaction process
2.1 Controller: DispatcherServlet.doService()
track DispatcherServlet.doDispatch()
doService() The internal call is doDispatch()
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
HttpServletRequest processedRequest = request;
// Determine handler for the current request.( track )
HandlerExecutionChain mappedHandler = getHandler(processedRequest)
// Determine handler adapter for the current request.( track )
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Actually invoke the handler.( track )
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
track DispatcherServlet.getHandler()
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
Handler It’s based on HandlerMapping Acquired , Corresponding Controller Of @RequestMapping
track DispatcherServlet. getHandlerAdapter()
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (ha.supports(handler)) {
return ha;
}
}
}
track HandlerAdapter.handle()
ModelAndView handle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception;
stay DispatcherServlet Find ModelAndView The return value of
track HandlerAdapter Implementation class SimpleControllerHandlerAdapter
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
track Controller Realization
public interface Controller {
@Nullable
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
Final eureka Controller return MV Code for , It also confirms DispatcherServlet.doDispatcher Will eventually return to Controller Made up of ModelAndView
2.2 Model And View
Different view parsers decide how to handle parsing View name , therefore SpringMVC You need to configure the view parser
public interface ViewResolver {
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}
3. summary
DispatcherServlet Will be looking for HandlerMapping and HandlerMapping , When you parse a view, you use ViewResolver
If manual integration SSM,SpringMVC You need to manually inject these three bean. It is worth mentioning that ,XML Configure if annotation support is enabled ,HandlerMapping and HandlerMapping It also loads . See the figure below for details