做产品的淘宝客网站,设计图片大全 效果图,别人是怎么建设网站的,强生公司营销网站为什么要这样做SpringMVC执行流程
原理图 1、SpringMVC常用组件
DispatcherServlet#xff1a;前端控制器#xff0c;不需要工程师开发#xff0c;由框架提供
作用#xff1a;统一处理请求和响应#xff0c;整个流程控制的中心#xff0c;由它调用其它组件处理用户的请求
HandlerMa…SpringMVC执行流程
原理图 1、SpringMVC常用组件
DispatcherServlet前端控制器不需要工程师开发由框架提供
作用统一处理请求和响应整个流程控制的中心由它调用其它组件处理用户的请求
HandlerMapping处理器映射器不需要工程师开发由框架提供
作用根据请求的url、method等信息查找Handler即控制器方法
Handler处理器需要工程师开发
作用在DispatcherServlet的控制下Handler对具体的用户请求进行处理
HandlerAdapter处理器适配器不需要工程师开发由框架提供
作用通过HandlerAdapter对处理器控制器方法进行执行
ViewResolver视图解析器不需要工程师开发由框架提供
作用进行视图解析得到相应的视图例如ThymeleafView、InternalResourceView、RedirectView
View视图
作用将模型数据通过页面展示给用户
2、DispatcherServlet初始化过程
DispatcherServlet 本质上是一个 Servlet所以天然的遵循 Servlet 的生命周期。所以宏观上是 Servlet 生命周期来进行调度。 a初始化WebApplicationContext
所在类org.springframework.web.servlet.FrameworkServlet
protected WebApplicationContext initWebApplicationContext() {WebApplicationContext rootContext WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext wac null;if (this.webApplicationContext ! null) {// A context instance was injected at construction time - use itwac this.webApplicationContext;if (wac instanceof ConfigurableWebApplicationContext) {ConfigurableWebApplicationContext cwac (ConfigurableWebApplicationContext) wac;if (!cwac.isActive()) {// The context has not yet been refreshed - provide services such as// setting the parent context, setting the application context id, etcif (cwac.getParent() null) {// The context instance was injected without an explicit parent - set// the root application context (if any; may be null) as the parentcwac.setParent(rootContext);}configureAndRefreshWebApplicationContext(cwac);}}}if (wac null) {// No context instance was injected at construction time - see if one// has been registered in the servlet context. If one exists, it is assumed// that the parent context (if any) has already been set and that the// user has performed any initialization such as setting the context idwac findWebApplicationContext();}if (wac null) {// No context instance is defined for this servlet - create a local one// 创建WebApplicationContextwac createWebApplicationContext(rootContext);}if (!this.refreshEventReceived) {// Either the context is not a ConfigurableApplicationContext with refresh// support or the context injected at construction time had already been// refreshed - trigger initial onRefresh manually here.synchronized (this.onRefreshMonitor) {// 刷新WebApplicationContextonRefresh(wac);}}if (this.publishContext) {// Publish the context as a servlet context attribute.// 将IOC容器在应用域共享String attrName getServletContextAttributeName();getServletContext().setAttribute(attrName, wac);}return wac;
}b创建WebApplicationContext
所在类org.springframework.web.servlet.FrameworkServlet
protected WebApplicationContext createWebApplicationContext(Nullable ApplicationContext parent) {Class? contextClass getContextClass();if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {throw new ApplicationContextException(Fatal initialization error in servlet with name getServletName() : custom WebApplicationContext class [ contextClass.getName() ] is not of type ConfigurableWebApplicationContext);}// 通过反射创建 IOC 容器对象ConfigurableWebApplicationContext wac (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);wac.setEnvironment(getEnvironment());// 设置父容器wac.setParent(parent);String configLocation getContextConfigLocation();if (configLocation ! null) {wac.setConfigLocation(configLocation);}configureAndRefreshWebApplicationContext(wac);return wac;
}cDispatcherServlet初始化策略
FrameworkServlet创建WebApplicationContext后刷新容器调用onRefresh(wac)此方法在DispatcherServlet中进行了重写调用了initStrategies(context)方法初始化策略即初始化DispatcherServlet的各个组件
所在类org.springframework.web.servlet.DispatcherServlet
protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);initLocaleResolver(context);initThemeResolver(context);initHandlerMappings(context);initHandlerAdapters(context);initHandlerExceptionResolvers(context);initRequestToViewNameTranslator(context);initViewResolvers(context);initFlashMapManager(context);
}3、DispatcherServlet调用组件处理请求
aprocessRequest()
FrameworkServlet重写HttpServlet中的service()和doXxx()这些方法中调用了processRequest(request, response)
所在类org.springframework.web.servlet.FrameworkServlet
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {long startTime System.currentTimeMillis();Throwable failureCause null;LocaleContext previousLocaleContext LocaleContextHolder.getLocaleContext();LocaleContext localeContext buildLocaleContext(request);RequestAttributes previousAttributes RequestContextHolder.getRequestAttributes();ServletRequestAttributes requestAttributes buildRequestAttributes(request, response, previousAttributes);WebAsyncManager asyncManager WebAsyncUtils.getAsyncManager(request);asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());initContextHolders(request, localeContext, requestAttributes);try {// 执行服务doService()是一个抽象方法在DispatcherServlet中进行了重写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);}
}bdoService()
所在类org.springframework.web.servlet.DispatcherServlet
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.MapString, 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);}RequestPath requestPath null;if (this.parseRequestPath !ServletRequestPathUtils.hasParsedRequestPath(request)) {requestPath ServletRequestPathUtils.parseAndCache(request);}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);}}if (requestPath ! null) {ServletRequestPathUtils.clearParsedRequestPath(request);}}
}cdoDispatch()
所在类org.springframework.web.servlet.DispatcherServlet
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);// Determine handler for the current request./*mappedHandler调用链包含handler、interceptorList、interceptorIndexhandler浏览器发送的请求所匹配的控制器方法interceptorList处理控制器方法的所有拦截器集合interceptorIndex拦截器索引控制拦截器afterCompletion()的执行*/mappedHandler getHandler(processedRequest);if (mappedHandler null) {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.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()if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// Actually invoke the handler.// 由处理器适配器调用具体的控制器方法最终获得ModelAndView对象mv ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(processedRequest, mv);// 调用拦截器的postHandle()mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException ex;}catch (Throwable err) {// As of 4.3, were 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) {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 afterCompletionif (mappedHandler ! null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {// Clean up any resources used by a multipart request.if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}
}dprocessDispatchResult()
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,Nullable HandlerExecutionChain mappedHandler, Nullable ModelAndView mv,Nullable Exception exception) throws Exception {boolean errorView false;if (exception ! null) {if (exception instanceof ModelAndViewDefiningException) {logger.debug(ModelAndViewDefiningException encountered, exception);mv ((ModelAndViewDefiningException) exception).getModelAndView();}else {Object handler (mappedHandler ! null ? mappedHandler.getHandler() : null);mv processHandlerException(request, response, handler, exception);errorView (mv ! null);}}// Did the handler return a view to render?if (mv ! null !mv.wasCleared()) {// 处理模型数据和渲染视图render(mv, request, response);if (errorView) {WebUtils.clearErrorRequestAttributes(request);}}else {if (logger.isTraceEnabled()) {logger.trace(No view rendering, null ModelAndView returned.);}}if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {// Concurrent handling started during a forwardreturn;}if (mappedHandler ! null) {// Exception (if any) is already handled..// 调用拦截器的afterCompletion()mappedHandler.triggerAfterCompletion(request, response, null);}
}4、SpringMVC的执行流程 用户向服务器发送请求请求被SpringMVC 前端控制器 DispatcherServlet捕获。 DispatcherServlet对请求URL进行解析得到请求资源标识符URI判断请求URI对应的映射
a) 不存在
i. 再判断是否配置了mvc:default-servlet-handler
ii. 如果没配置则控制台报映射查找不到客户端展示404错误 iii. 如果有配置则访问目标资源一般为静态资源如JS,CSS,HTML找不到客户端也会展示404错误
b) 存在则执行下面的流程 根据该URI调用HandlerMapping获得该Handler配置的所有相关的对象包括Handler对象以及Handler对象对应的拦截器最后以HandlerExecutionChain执行链对象的形式返回。 DispatcherServlet 根据获得的Handler选择一个合适的HandlerAdapter。 如果成功获得HandlerAdapter此时将开始执行拦截器的preHandler(…)方法【正向】 提取Request中的模型数据填充Handler入参开始执行HandlerController)方法处理请求。在填充Handler的入参过程中根据你的配置Spring将帮你做一些额外的工作
a) HttpMessageConveter 将请求消息如Json、xml等数据转换成一个对象将对象转换为指定的响应信息
b) 数据转换对请求消息进行数据转换。如String转换成Integer、Double等
c) 数据格式化对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
d) 数据验证 验证数据的有效性长度、格式等验证结果存储到BindingResult或Error中 Handler执行完成后向DispatcherServlet 返回一个ModelAndView对象。 此时将开始执行拦截器的postHandle(…)方法【逆向】。 根据返回的ModelAndView此时会判断是否存在异常如果存在异常则执行HandlerExceptionResolver进行异常处理选择一个适合的ViewResolver进行视图解析根据Model和View来渲染视图。 渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。 将渲染结果返回给客户端。