本节内容
在写代码时都知道,在方法上添加 @RequestMapping 注解,可以让对应的 http 请求进来时,执行该方法,在源码中如何体现的呢?
小知识
入参前面加上 @PathVariable(“x”),能拿到 @RequestMapping("/{x}") 里的 x。
入参前面加上 @RequestParam(“x”),能拿到 URI 里 ?后面的 x 的值。
如果 @RequestParam 不加(),需要入参名和 URI 里的参数名一样。
doDispatch
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
//异步管理
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//文件上传
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//这个方法很重要,重点看 见 5.2.2
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
//获取跟HandlerMethod匹配的HandlerAdapter对象
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//请求所有拦截器里的preHandle方法,记录最后一个成功处理的索引interceptorIndex,
//一旦有处理失败的,立即从interceptorIndex到0调用所有afterCompletion,返回false
//一旦返回false,这里条件成立,直接返回,不会调用下面的postHandle
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//调用到Controller具体方法,核心方法调用,重点看看 见5.2.3
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
//从interceptorIndex开始到0请求拦截器数组里的所有postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
//视图渲染 见 5.2.4
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}