各位老铁们,大家好,今天由我来为大家分享mvc网站源码分享响应式,以及响应式网站源代码的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!
前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet处理请求的过程的源码解析。本文是第二篇:DispatcherServlet处理请求的过程的源码解析。@pdai
DispatcherServlet处理请求的过程?
一个请求发出,经过DispatcherServlet进行了什么样的处理,最后将内容返回的呢?
回顾整理处理流程
首先让我们整体看一下SpringWebMVC处理请求的流程:
核心架构的具体流程步骤如下:
首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;DispatcherServlet——>HandlerMapping,HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);ModelAndView的逻辑视图名——>ViewResolver,ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
doGet入口
我们以上个demo中这个GET请求为例,请求URL是http://localhost:8080/011_spring_framework_demo_springmvc_war_exploded/user
我们知道servlet处理get请求是doGet方法,所以我们去找DispatcherServlet类结构中的doGet方法。
@Override\nprotectedfinalvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)\nthrowsServletException,IOException{\n\nprocessRequest(request,response);\n}\n
processRequest处理请求的方法如下:
/**\n*Processthisrequest,publishinganeventregardlessoftheoutcome.\n*<p>Theactualeventhandlingisperformedbytheabstract\n*{@link34;Requestprocessingfailed&doDispatch}\n*fortheactualdispatching.\n*/\n@Override\nprotectedvoiddoService(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{\nlogRequest(request);\n\n//保存下请求之前的参数.\nMap<String,Object>attributesSnapshot=null;\nif(WebUtils.isIncludeRequest(request)){\nattributesSnapshot=newHashMap<>();\nEnumeration<?>attrNames=request.getAttributeNames();\nwhile(attrNames.hasMoreElements()){\nStringattrName=(String)attrNames.nextElement();\nif(this.cleanupAfterInclude||attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)){\nattributesSnapshot.put(attrName,request.getAttribute(attrName));\n}\n}\n}\n\n//方便后续handlers和view要使用它们.\nrequest.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,getWebApplicationContext());\nrequest.setAttribute(LOCALE_RESOLVER_ATTRIBUTE,this.localeResolver);\nrequest.setAttribute(THEME_RESOLVER_ATTRIBUTE,this.themeResolver);\nrequest.setAttribute(THEME_SOURCE_ATTRIBUTE,getThemeSource());\n\nif(this.flashMapManager!=null){\nFlashMapinputFlashMap=this.flashMapManager.retrieveAndUpdate(request,response);\nif(inputFlashMap!=null){\nrequest.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE,Collections.unmodifiableMap(inputFlashMap));\n}\nrequest.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE,newFlashMap());\nrequest.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE,this.flashMapManager);\n}\n\nRequestPathpreviousRequestPath=null;\nif(this.parseRequestPath){\npreviousRequestPath=(RequestPath)request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);\nServletRequestPathUtils.parseAndCache(request);\n}\n\ntry{\n//看这里,终于将这个请求分发出去了\ndoDispatch(request,response);\n}\nfinally{\nif(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()){\n//Restoretheoriginalattributesnapshot,incaseofaninclude.\nif(attributesSnapshot!=null){\nrestoreAttributesAfterInclude(request,attributesSnapshot);\n}\n}\nif(this.parseRequestPath){\nServletRequestPathUtils.setParsedRequestPath(previousRequestPath,request);\n}\n}\n}\n
请求分发
doDispatch方法是真正处理请求的核心方法
protectedvoiddoDispatch(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{\nHttpServletRequestprocessedRequest=request;\nHandlerExecutionChainmappedHandler=null;\nbooleanmultipartRequestParsed=false;\n\nWebAsyncManagerasyncManager=WebAsyncUtils.getAsyncManager(request);\n\ntry{\nModelAndViewmv=null;\nExceptiondispatchException=null;\n\ntry{\n//判断是不是文件上传类型的request\nprocessedRequest=checkMultipart(request);\nmultipartRequestParsed=(processedRequest!=request);\n\n//根据request获取匹配的handler.\nmappedHandler=getHandler(processedRequest);\nif(mappedHandler==null){\nnoHandlerFound(processedRequest,response);\nreturn;\n}\n\n//根据handler获取匹配的handlerAdapter\nHandlerAdapterha=getHandlerAdapter(mappedHandler.getHandler());\n\n//如果handler支持last-modified头处理\nStringmethod=request.getMethod();\nbooleanisGet=HttpMethod.GET.matches(method);\nif(isGet||HttpMethod.HEAD.matches(method)){\nlonglastModified=ha.getLastModified(request,mappedHandler.getHandler());\nif(newServletWebRequest(request,response).checkNotModified(lastModified)&&isGet){\nreturn;\n}\n}\n\nif(!mappedHandler.applyPreHandle(processedRequest,response)){\nreturn;\n}\n\n//真正handle处理,并返回modelAndView\nmv=ha.handle(processedRequest,response,mappedHandler.getHandler());\n\nif(asyncManager.isConcurrentHandlingStarted()){\nreturn;\n}\n\n//通过视图的prefix和postfix获取完整的视图名\napplyDefaultViewName(processedRequest,mv);\n\n//应用后置的拦截器\nmappedHandler.applyPostHandle(processedRequest,response,mv);\n}\ncatch(Exceptionex){\ndispatchException=ex;\n}\ncatch(Throwableerr){\n//Asof4.3,we&34;Handlerdispatchfailed&34;Handlerprocessingfailed&createInvocableHandlerMethod(HandlerMethod)\n*/\n@Nullable\nprotectedModelAndViewinvokeHandlerMethod(HttpServletRequestrequest,\nHttpServletResponseresponse,HandlerMethodhandlerMethod)throwsException{\n\nServletWebRequestwebRequest=newServletWebRequest(request,response);\ntry{\n\nWebDataBinderFactorybinderFactory=getDataBinderFactory(handlerMethod);\nModelFactorymodelFactory=getModelFactory(handlerMethod,binderFactory);\n\n//重要:设置handler(controller34;Resumewithasyncresult[&34;]&34;ModelAndViewDefiningExceptionencountered&34;Noviewrendering,nullModelAndViewreturned.&39;saproblemrenderingtheview\n*/\nprotectedvoidrender(ModelAndViewmv,HttpServletRequestrequest,HttpServletResponseresponse)throwsException{\n//Determinelocaleforrequestandapplyittotheresponse.\nLocalelocale=\n(this.localeResolver!=null?this.localeResolver.resolveLocale(request):request.getLocale());\nresponse.setLocale(locale);\n\nViewview;\nStringviewName=mv.getViewName();\nif(viewName!=null){\n//Weneedtoresolvetheviewname.\nview=resolveViewName(viewName,mv.getModelInternal(),locale,request);\nif(view==null){\nthrownewServletException(&39;&34;&39;&34;&34;);\n}\n}\nelse{\n//Noneedtolookup:theModelAndViewobjectcontainstheactualViewobject.\nview=mv.getView();\nif(view==null){\nthrownewServletException(&34;+mv+&34;+\n&39;&34;&34;);\n}\n}\n\n//DelegatetotheViewobjectforrendering.\nif(logger.isTraceEnabled()){\nlogger.trace(&34;+view+&34;);\n}\ntry{\nif(mv.getStatus()!=null){\nresponse.setStatus(mv.getStatus().value());\n}\nview.render(mv.getModelInternal(),request,response);\n}\ncatch(Exceptionex){\nif(logger.isDebugEnabled()){\nlogger.debug(&34;+view+&34;,ex);\n}\nthrowex;\n}\n}\n
后续就是通过viewResolver进行解析了,这里就不再继续看代码了,上述流程基本上够帮助你构建相关的认知了。
最后无非是返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户。
最后的最后我们看下请求的日志:
21:45:53.390[http-nio-8080-exec-6]DEBUGorg.springframework.web.servlet.DispatcherServlet-GET&34;,parameters={}\n21:45:53.400[http-nio-8080-exec-6]DEBUGorg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping-Mappedtotech.pdai.springframework.springmvc.controller.UserController39;userList',model{dateTime=FriApr2221:45:53CST2022,userList=[tech.pdai.springframework.springmvc.entity.User@7b8c8dc]}\n22:51:14.550[http-nio-8080-exec-6]DEBUGorg.springframework.web.servlet.view.JstlView-Forwardingto[/WEB-INF/views/userList.jsp]\n22:51:44.395[http-nio-8080-exec-6]DEBUGorg.springframework.web.servlet.DispatcherServlet-Completed200OK\n
更多文章
首先,从Spring框架的整体架构和组成对整体框架有个认知。
Spring基础-Spring和Spring框架组成Spring是什么?它是怎么诞生的?有哪些主要的组件和核心功能呢?本文通过这几个问题帮助你构筑Spring和SpringFramework的整体认知。
其次,通过案例引出Spring的核心(IoC和AOP),同时对IoC和AOP进行案例使用分析。
Spring基础-Spring简单例子引入Spring的核心上文中我们简单介绍了Spring和SpringFramework的组件,那么这些SpringFramework组件是如何配合工作的呢?本文主要承接上文,向你展示SpringFramework组件的典型应用场景和基于这个场景设计出的简单案例,并以此引出Spring的核心要点,比如IOC和AOP等;在此基础上还引入了不同的配置方式,如XML,Java配置和注解方式的差异。Spring基础-Spring核心之控制反转(IOC)在Spring基础-Spring简单例子引入Spring的核心中向你展示了IoC的基础含义,同时以此发散了一些IoC相关知识点;本节将在此基础上进一步解读IOC的含义以及IOC的使用方式Spring基础-Spring核心之面向切面编程(AOP)在Spring基础-Spring简单例子引入Spring的核心中向你展示了AOP的基础含义,同时以此发散了一些AOP相关知识点;本节将在此基础上进一步解读AOP的含义以及AOP的使用方式。
基于Spring框架和IOC,AOP的基础,为构建上层web应用,需要进一步学习SpringMVC。
Spring基础-SpringMVC请求流程和案例前文我们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那我们如何更好的构建上层的应用呢(比如web应用),这便是SpringMVC;SpringMVC是Spring在SpringContainerCore和AOP等技术基础上,遵循上述WebMVC的规范推出的web开发框架,目的是为了简化Java栈的web开发。本文主要介绍SpringMVC的请求流程和基础案例的编写和运行。
Spring进阶-IoC,AOP以及SpringMVC的源码分析
Spring进阶-SpringIOC实现原理详解之IOC体系结构设计在对IoC有了初步的认知后,我们开始对IOC的实现原理进行深入理解。本文将帮助你站在设计者的角度去看IOC最顶层的结构设计Spring进阶-SpringIOC实现原理详解之IOC初始化流程上文,我们看了IOC设计要点和设计结构;紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的Spring进阶-SpringIOC实现原理详解之Bean实例化(生命周期,循环依赖等)上文,我们看了IOC设计要点和设计结构;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中存放的是Bean的定义即BeanDefinition放到beanDefinitionMap中,本质上是一个ConcurrentHashMap<String,Object>;并且BeanDefinition接口中包含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文主要研究的内容?Spring进阶-SpringAOP实现原理详解之切面实现前文,我们分析了SpringIOC的初始化过程和Bean的生命周期等,而SpringAOP也是基于IOC的Bean加载来实现的。本文主要介绍SpringAOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理增强实现做准备的过程)。Spring进阶-SpringAOP实现原理详解之AOP代理上文我们介绍了SpringAOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor)。本文在此基础上继续介绍,代理(cglib代理和JDK代理)的实现过程。Spring进阶-SpringAOP实现原理详解之Cglib代理实现我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理。Spring进阶-SpringAOP实现原理详解之JDK代理实现上文我们学习了SpringAOPCglib动态代理的实现,本文主要是SpringAOPJDK动态代理的案例和实现部分。Spring进阶-SpringMVC实现原理之DispatcherServlet初始化的过程前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet处理请求的过程的源码解析。本文是第一篇:DispatcherServlet的初始化过程的源码解析。Spring进阶-SpringMVC实现原理之DispatcherServlet处理请求的过程前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet处理请求的过程的源码解析。本文是第二篇:DispatcherServlet处理请求的过程的源码解析。
好了,文章到这里就结束啦,如果本次分享的mvc网站源码分享响应式和响应式网站源代码问题对您有所帮助,还望关注下本站哦!