0. 前置概念
- JavaEE体系结构包括四层,从上到下分别是应用层、Web层、业务层、持久层。
- Struts和SpringMVC是Web层的框架
- Spring是业务层的框架
- Hibernate和MyBatis是持久层的框架。
- SpringMVC是一种基于Java,实现了Web MVC设计模式,请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦。基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发
1. SpringMVC 流程图
具体流程
- 发起请求到前端控制器(DispatcherServlet), 任务调度分发作用;
- 前端控制器请求HandlerMapping查找 Handler (可以根据xml配置、注解进行查找);
- 处理器映射器HandlerMapping向前端控制器返回Handler,HandlerMapping会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象,多个HandlerInterceptor拦截器对象),通过这种策略模式,很容易添加新的映射策略;
- 前端控制器调用处理器适配器去执行Handler
- 处理器适配器HandlerAdapter将会根据适配的结果去执行Handler;
- Handler执行完成给适配器返回ModelAndView
- 处理器适配器向前端控制器返回ModelAndView(ModelAndView是springmvc框架的一个底层对象,包括 Model和view);
- 前端控制器请求视图解析器去进行视图解析(根据逻辑视图名解析成真正的视图(jsp)),通过这种策略很容易更换其他视图技术,只需要更改视图解析器即可;
- 视图解析器向前端控制器返回View;
- 前端控制器进行视图渲染 (视图渲染将模型数据(在ModelAndView对象中)填充到request域);
- 前端控制器向用户响应结果;
2. doDispatch源码
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 1.用户请求
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);
// Determine handler for the current request.
// 2.根据Request查询找到handler,3.并返回处理器执行链
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 4.请求执行handler,根据handler找到HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
// 处理Get、Head请求的Last-Modified
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
// 是否使用缓存页面
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 执行相应的Interceptor的preHandle
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 5.HandlerAdapter执行Handler处理请求(6.返回ModelAndView),
// 7.返回ModelAndView到DispatcherServlet
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 如果需要异步处理直接返回
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 当mv的view为空时,根据request设置默认view
applyDefaultViewName(request, mv);
// 执行相应的Interceptor的preHandle
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
// 8、9、10.处理返回结果。(包括处理异常,渲染页面,发出完成通知触发Interceptor的afterCompletion)
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, 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);
}
}
}
}
3. 实际调用SpringMVC开发涉及部分
- DispatcherServlet 在 web.xml 中的部署描述,从而拦截请求到 Spring Web MVC
- HandlerMapping 的配置,从而将请求映射到处理器
- HandlerAdapter 的配置,从而支持多种类型的处理器
- ViewResolver 的配置,从而将逻辑视图名解析为具体视图技术
- 处理器(页面控制器)的配置,从而进行功能处理
4. 代码复现(简化版本)
// TODO:GitHub地址
参考
- 源码分析之动手实现手写一个自己的SpringMVC框架:https://blog.csdn.net/honhong1024/article/details/79531699
- SpringMVC流程:https://www.cnblogs.com/leskang/p/6101368.html
- 手写SpringMVC:https://github.com/yjy91913/jerry-mvcframework