spring mvc 源码分析
spring mvc 源码总流程
- spring mvc 源码分析
- 前言
- 一、断点开始分析源码
- 一、DispatcherServlet
- DispatcherServlet的继承关系
- doPost和doGet在哪里实现的
- 调用栈分析
- 先调用了FrameworkServlet .service方法
- super.service(request, response)
- FrameworkServlet 中的doGet和doPost
- FrameworkServlet 类中的processRequest(request, response) 进行一直处理
- DispatcherServlet.doService(request, response) 重定向携带的参数处理
- DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response) 开始真正的处理
- 总结
前言
废话不多说,直接上图。所有请求在spring mvc中的大致执行流程图
所有的请求都最终会被doPost和doGet所处理
一、断点开始分析源码
结合上一篇文章搭建的案例
搭建案例
开始分析
具体逻辑处理之前 打上断点
页面跳转之前 打上断点
一、DispatcherServlet
DispatcherServlet的继承关系
从源码来看 DispatcherServlet 继承了FrameworkServlet ,FrameworkServlet 继承HttpServletBean ,HttpServletBean 继承HttpServlet ,HttpServlet 继承GenericServlet抽象类。
// 从源码来看 DispatcherServlet 继承了FrameworkServlet
public class DispatcherServlet extends FrameworkServlet
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware
public abstract class HttpServlet extends GenericServlet
doPost和doGet在哪里实现的
通过源码查看 doGet和doPost 最终是在FrameworkServlet 进行重写。因此我们需要重点观察FrameworkServlet
调用栈分析
先调用了FrameworkServlet .service方法
/**
* Override the parent class implementation in order to intercept PATCH requests.
*/
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 解析出当前的请求方式
/*
因为HttpServlet中是没有定义doPatch方法的,所以规定
if(是doPatch类型)
就交由本类(FrameworkServlet)内的doPatch方法运行。
else
调用父类(HttpServlet)的service方法。
*/
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
processRequest(request, response);
}
else {
super.service(request, response);
}
}
super.service(request, response)
里面主要对各种请求简单处理 并没有正在处理,真正处理都在FrameworkServlet 中
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_get_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_post_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
FrameworkServlet 中的doGet和doPost
通过源码 可以看出无论是doGet还是doPost都调用了processRequest(request, response)方法进行处理
/**
* Delegate GET requests to processRequest/doService.
* <p>Will also be invoked by HttpServlet's default implementation of {@code doHead},
* with a {@code NoBodyResponse} that just captures the content length.
* @see #doService
* @see #doHead
*/
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Delegate POST requests to {@link #processRequest}.
* @see #doService
*/
@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
FrameworkServlet 类中的processRequest(request, response) 进行一直处理
/**
* Process this request, publishing an event regardless of the outcome.
* <p>The actual event handling is performed by the abstract
* {@link #doService} template method.
*/
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
// 获取上一个请求保存的LocaleContext
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
// 建立新的LocaleContext
LocaleContext localeContext = buildLocaleContext(request);
// 获取上一个请求保存的RequestAttributes
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
// 建立新的RequestAttributes
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
// 异步处理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
// 新的RequestAttributes设置进LocalThread
initContextHolders(request, localeContext, requestAttributes);
try {
// 开始处理 抽象方法交给子类去实现
doService(request, response);
}
catch (ServletException | IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
logResult(request, response, failureCause, asyncManager);
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
DispatcherServlet.doService(request, response) 重定向携带的参数处理
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// Make framework objects available to handlers and view objects.
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
// 处理重定向携带的参数
if (this.flashMapManager != null) {
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
}
try {
// 开始处理请求
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response) 开始真正的处理
请求到达DispatcherServlet 通过这个方法进行处理和返回
这个方法就是最关键的方法,里面包含了整个spring Mvc的执行流程,重要程度跟spring的refresh()一样十分重要,阅读源码时找到方法入口就不会太难了。
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);
/**
* 拿到当前的请求controller 也就是handler 处理器
* 这里并不会直接返回 controller 而是返回handlerExecutionChain 请求处理链对象
* 该对象封装了Handler 和 Inteceptor
*/
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
// 如果handler 为空,则返回404
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 获取处理请求的处理器适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
// 处理last-modified请求头
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;
}
}
// 处理拦截器 前置
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 实际处理器处理请求,返回结果视图对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 结果视图对象的处理
applyDefaultViewName(processedRequest, mv);
// 处理拦截器 后置
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);
}
// 跳转到页面
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
// 最终会调用HandlerInterceptor的afterCompletion方法
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
// 最终会调用HandlerInterceptor的afterCompletion方法
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);
}
}
}
}
步骤
第一步:
通过getHandler⽅法,获取到能够处理当前请求的handlerExecutionChain,它包含handler(处理器对象)和Inteceptor(拦截器对象)。
第二步 :
通过getHandlerAdapter⽅法,传入处理器对象,获取到能够处理当前handler的处理器适配器对象。
第三步:
mappedHandler.applyPreHandle(processedRequest, response)) 拦截器 进入handler之前拦截处理。也就是preHandle() 方法的调用,如果方法返回false将不在往后面执行。
第四步:
ha.handle(processedRequest, response, mappedHandler.getHandler())处理器适配器调用handler,处理请求并封装返回ModelAndView对象
第五步 :
mappedHandler.applyPostHandle(processedRequest, response, mv) 拦截器 跳出handler之前拦截处理 ,也就是调用其postHandle方法,进行处理。
第六步 :
processDispatchResult(processedRequest,response,mappedHandler,mv,dispatchException) 进行视图的解析和渲染。
总结
本文主要对spring mvc 对于一个请求时如何处理的 给出了一个大致的流程,后续将会通过关键步骤 源码的解析,一起来感受spring mvc的强大和处理流程与方法。