SpringMVC原理剖析
SpringMVC框架和Servlet容器具体详细图,周舟
1 初始环境是 tomcat 容器!
根据你的web.xml 读取配置信息,
2 Tomcat 依赖servlet.jar规范
--- Init(config) 初始化配置,配置从web.xml 通过servlet规范读取
--- Service 请求进行服务
--- Destory 销毁
3 SpringMVC (Servlet服务) 实现了Servlet规范
这边重写了init,service,destory
SpringMVC入口在 DispatcherServlet
可以从继承树上找到SpringMVC是Servlet的扩展,
上图是servlet的规范
总结,延续Servlet体系的半封装框架
1. 如何初始化SpringMVC上下文
a) Init()方法在httpServlet的父类GenericServlet
b) Destory()方法也在GenericServlet中(如下图所示)
c) httpServlet只重写了service()
d) 而HttpServletBean中重写了init()方法
HttpServletBean 重写了GenericServlet里面的init()方法而进入了SpringMVC自身上下文初始化
public final void init() throws ServletException{ if (logger.isDebugEnabled()) { logger.debug("Initializing servlet '" + getServletName() + "'"); } // 将Servlet中封装的参数封装到PropertyValues // requiredProperties:必须的参数数据,如果没有会报异常 try { // 这里的getServletContext就是获取web.xml中的 PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); // 属性编辑器,控制修改我们的ServletConfig属性 BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); // 获取资源加载器 ResourceLoaderresourceLoader = new ServletContextResourceLoader(getServletContext()); // 注册我们的资源类型 bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader)); // 初始化属性编辑器对象bw initBeanWrapper(bw); bw.setPropertyValues(pvs, true); } catch (BeansExceptionex) { logger.error("Failed to set bean properties onservlet '" + getServletName()+ "'", ex); throw ex; } // 模板方法, 给我们子类FramworkServlet具体实现了他 // 他用来初始化SpringMvc框架Bean组件Controller 还有九大组件 initServletBean(); if (logger.isDebugEnabled()) { logger.debug("Servlet '" + getServletName() + "' configured successfully"); } }
init这个方法主要调用了(initServletBean()方法),protected修饰, 在FramworkServlet中实现了
// initServletBean方法里主要调用了initWebApplicationContext()方法, 由于SpringMVC的上下文继承了WebApplicationContext
所以这个方法主要是用来刷新和获取上下文, 详情如下
刷新后!! 执行最注重要的onRefresh()
if (!this.refreshEventReceived) { // Apparently not a ConfigurableApplicationContext with refresh support: // triggering initial onRefresh manually here. onRefresh(wac); }
最终调用了DispatcherServlet的OnRefresh方法, 初始化九大组件
@Override protected void onRefresh(ApplicationContext context) { initStrategies(context); } /** * Initialize the strategy objects that this servlet uses. * <p>May be overridden in subclasses in order to initialize further strategy objects. */ protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); // 本地解析 initLocaleResolver(context); // 主题解析 initThemeResolver(context); // 映射器组件 initHandlerMappings(context); // 初始化适配器 initHandlerAdapters(context); // 初始化程序异常解析器 initHandlerExceptionResolvers(context); // initRequestToViewNameTranslator(context); //初始化视图解析器 initViewResolvers(context); }
Init完成点done
2. 接受业务请求!
a) 来到HttpServlet这里,寻找service()请求;
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; try { request = (HttpServletRequest) req; response = (HttpServletResponse) res; } catch (ClassCastException e) { throw new ServletException("non-HTTP request or response"); } service(request, response); }
总结:SpringMVC的业务请求流程是重写HttpServlet的service方法中的分派方法(例如doPost())
b) protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < lastModified) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. // String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }
c) 分类方法在FramworkServlet中重写了, 主要调用了processRequest(request,response)方法
@Override protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); }
d) 真正执行的是doService()方法, 他在DispatcherServlet里重写
try { doService(request, response); }
e) doService()方法中,快照备份后, 组装一些组件,和解析器执行doDispatch(request,response);方法
/** /* *处理实际调度到处理程序。 * <p>处理程序将通过按顺序应用servlet的HandlerMappings来获得。 HandlerAdapter将通过查询Servlet的已安装HandlerAdapter获得 *找到支持处理程序类的第一个。 * <p>所有HTTP方法都由此方法处理。 这取决于HandlerAdapters或Handler *自己决定哪些方法可以接受。 @param response current HTTP response * @throws Exception in case of any kind of processing failure */ protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; int interceptorIndex = -1; try { // 模型视图对象 ModelAndView mv; boolean errorView = false; try { // 检查是否是上传 请求 processedRequest = checkMultipart(request); // 根据请求找到handler. mappedHandler = getHandler(processedRequest, false); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // 根据HandlerAdapter 找到HandlerExecutionChain处理执行链来确定handler HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // 处理GET/HEAD请求的LastModified String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); // 查看是否有缓存 if (logger.isDebugEnabled()) { String requestUri = urlPathHelper.getRequestUri(request); logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } // 执行相应的拦截器的PreHandle HandlerInterceptor[] interceptors = mappedHandler.getInterceptors(); if (interceptors != null) { for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) { triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); return; } interceptorIndex = i; } } // 执行handle处理请求返回modelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); // 当view为空(比如Handler返回为void),根据request设置默认的mv if (mv != null && !mv.hasView()) { mv.setViewName(getDefaultViewName(request)); } // 拦截器后处理, 在modeAndView返回DispatcherServlet前,按照执行链的反顺序操作 if (interceptors != null) { for (int i = interceptors.length - 1; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv); } } } catch (ModelAndViewDefiningException ex) { logger.debug("ModelAndViewDefiningException encountered", ex); mv = ex.getModelAndView(); } catch (Exception ex) { Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); mv = processHandlerException(processedRequest, response, handler, ex); errorView = (mv != null); } // Did the handler return a view to render? if (mv != null && !mv.wasCleared()) { render(mv, processedRequest, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else { if (logger.isDebugEnabled()) { logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() + "': assuming HandlerAdapter completed request handling"); } } // 处理完成后的回调! 回调 triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); } catch (Exception ex) { // Trigger after-completion for thrown exception. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex); throw ex; } catch (Error err) { ServletException ex = new NestedServletException("Handler processing failed", err); // Trigger after-completion for thrown exception. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex); throw ex; } finally { // Clean up any resources used by a multipart request. if (processedRequest != request) { cleanupMultipart(processedRequest); } } }
f) 拦截器的三种方法全部执行到
3.
4.
5.