一、概述
SpringMVC处理请求的大致流程如下图,本篇文章将会大概的介绍请求流程,等到下篇文章会从九大组件的角度来具体分析请求的具体处理流程。
二、请求流程
FrameworkServlet.service是请求的入口。
FrameworkServlet.processRequest是具体进行请求处理的具体方法。
通过FrameworkServlet.doService进入DispatcherServlet.doService。
DispatcherServlet.doDispatch是具体的处理方法。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 实际处理时所用的request,如果不是上传请求,则直接使用接收到的request,否则封装成上传类型的request
HttpServletRequest processedRequest = request;
// 处理请求的处理器链(包含处理器和对应的interceptor)
HandlerExecutionChain mappedHandler = null;
// 是不是上传请求的标志
boolean multipartRequestParsed = false;
// 获取异步管理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
// 封装model和view的容器
ModelAndView mv = null;
// 处理请求过程中抛出的异常,但是不包含渲染过程中抛出的异常
Exception dispatchException = null;
try {
// 检测请求是否为上传请求,如果是则通过multipartResolver将其封装成MultipartHttpServletRequest对象
processedRequest = checkMultipart(request);
// 设置上传请求的标志
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
// 获得请求对应的HandlerExecutionChain对象(HandlerMethod和HandlerInterceptor拦截器们)
mappedHandler = getHandler(processedRequest);
// 如果获取不到,则根据配置抛出异常或返回404错误
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 获得当前handler对应的HandlerAdapter对象
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
// 处理GET、HEAD请求的Last-Modified,当浏览器第一次跟服务器请求资源时,服务器会在返回的请求头里包含一个last_modified的属性,
// 代表资源最后时什么时候修改的,在浏览器以后发送请求的时候,会同时发送之前接收到的Last_modified.服务器接收到带last_modified的请求后,
// 会跟实际资源的最后修改时间做对比,如果过期了返回新的资源,否则直接返回304表示未过期,直接使用之前缓存的结果即可
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;
}
}
// 执行响应的Interceptor的preHandler
// 注意:该方法如果有一个拦截器的前置处理返回false,则开始倒序触发所有的拦截器的 已完成处理
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 真正的调用handler方法,也就是执行对应的方法,并返回视图
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 如果需要异步处理,直接返回
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 当view为空时,根据request设置默认的view
applyDefaultViewName(processedRequest, mv);
// 执行响应的interceptor的postHandler方法
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);
}
// 处理返回结果,包括处理异常、渲染页面、触发Interceptor的afterCompletion
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);
}
}
}
}