DispatcherServlet
:前端控制器,不需要工程师开发,由框架提供
作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求
HandlerMapping
:处理器映射器,不需要工程师开发,由框架提供
作用:根据请求的url、method等信息查找Handler,即控制器方法
Handler
:处理器,需要工程师开发
作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理
HandlerAdapter
:处理器适配器,不需要工程师开发,由框架提供
作用:通过HandlerAdapter对处理器(控制器方法)进行执行
ViewResolver
:视图解析器,不需要工程师开发,由框架提供
作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、 RedirectView
View
:视图
作用:将模型数据通过页面展示给用户。
DispatcherServlet也是一个servlet,那么就有service方法,接下了我们看一下这两个方法是如何从Servlet一步步继承过来的。
GenericServlet中:
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
在该类中并没有实现service方法,交给了子类去实现。
HttpServlet中:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
在HttpServlet中已经将service方法实现,并且它调用的doPost、doGet等一系列方法都被实现。
HttpServletBean中:在该类中并没有重写父类的service方法,所以它的service方法与HttpServlet相同。
FrameworkServlet中:
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
super.service(request, response);
} else {
this.processRequest(request, response);
}
}
从该方法可以看出,如果请求方式等于PATCH并且不等于null,那么就会调用processRequest方法,否则就会执行父类的service方法。我们知道父类的service方法根据请求方式调用的是doPost、doGet等一系列方法,在该类中这些方法都被重写,如下:
protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (this.dispatchOptionsRequest || CorsUtils.isPreFlightRequest(request)) {
this.processRequest(request, response);
if (response.containsHeader("Allow")) {
return;
}
}
super.doOptions(request, new HttpServletResponseWrapper(response) {
public void setHeader(String name, String value) {
if ("Allow".equals(name)) {
value = (StringUtils.hasLength(value) ? value + ", " : "") + HttpMethod.PATCH.name();
}
super.setHeader(name, value);
}
});
}
protected void doTrace(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (this.dispatchTraceRequest) {
this.processRequest(request, response);
if ("message/http".equals(response.getContentType())) {
return;
}
}
super.doTrace(request, response);
}
我们可以看出,无论哪种请求方式,最中都会调用processRequest
方法,下面我们来看一下该方法。
我们只看该方法的核心部分,如下:
try {
this.doService(request, response);
} catch (IOException | ServletException var16) {
failureCause = var16;
throw var16;
} catch (Throwable var17) {
failureCause = var17;
throw new NestedServletException("Request processing failed", var17);
} finally {
this.resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
this.logResult(request, response, (Throwable)failureCause, asyncManager);
this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
}
该方法又调用了doServic
方法,该方法如下:
protected abstract void doService(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
该方法并没有在该类中实现,我们需要去它的子类中看这个方法。
DispatcherServlet中:
在该类中并没有重写service、processRequest方法,但是它实现了父类的doService方法,下面是该方法的核心:
try {
this.doDispatch(request, response);
} finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
this.restoreAttributesAfterInclude(request, attributesSnapshot);
}
if (requestPath != null) {
ServletRequestPathUtils.clearParsedRequestPath(request);
}
}
在这个方法中又调用了doDispatch
,该方法在该类中实现。
我们一步步分析,最终找出doDispatch方法
是SpringMVC处理请求的核心方法,该方法的调用关系如下:
下面我们从源代码(部分代码)的角度来分析这一过程。
DispatcherServlet通过HandleMapping获取handler:HandlerMapping根据请求信息(URL),找到具体的handler,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给DispatcherServlet。
我们看一下HandlerExecutionChain里面有什么:
DispatcherServlet调用HandlerAdapter的handle()方法,来执行控制器方法。 HandlerAdapter调用handler的handleRequest()方法获取ModelAndView对象,并将该对象返回给DispatcherServlet。