源码深度解析SpringMvc请求运行机制
来源:互联网 发布:python macd代码 编辑:程序博客网 时间:2024/05/01 07:00
本文依赖的是springmvc4.0.5.RELEASE,通过源码深度解析了解springMvc的请求运行机制。通过源码我们可以知道从客户端发送一个URL请求给springMvc开始,到返回数据给客户端期间是怎么运转的。
doDispatch方法就是处理用户请求的方法。
1、用户请求处理过程:
1、用户发送请求时会先从DispathcherServler的doService方法开始,在该方法中会将ApplicationContext、localeResolver、themeResolver等对象添加到request中,紧接着就是调用doDispatch方法:
源码:
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {if (logger.isDebugEnabled()) {String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +" processing " + request.getMethod() + " request for [" + getRequestUri(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<String, Object>();Enumeration<?> attrNames = request.getAttributeNames();while (attrNames.hasMoreElements()) {String attrName = (String) attrNames.nextElement();if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {attributesSnapshot.put(attrName, request.getAttribute(attrName));}}}// Make framework objects available to handlers and view objects. <strong>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());</strong>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 {<strong>doDispatch(request, response);</strong>}finally {if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {return;}// Restore the original attribute snapshot, in case of an include.if (attributesSnapshot != null) {restoreAttributesAfterInclude(request, attributesSnapshot);}}}
doDispatch方法就是处理用户请求的方法。
2、进入该方法后首先会检查该请求是否是文件上传的请求(校验的规则是是否是post并且contenttType是否为multipart/为前缀)即调用的是checkMultipart方法;如果是的将request包装成MultipartHttpServletRequest。见源码:
doDispatch:
processedRequest = checkMultipart(request);checkMultipart:
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {if (request instanceof MultipartHttpServletRequest) {logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +"this typically results from an additional MultipartFilter in web.xml");}else if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) instanceof MultipartException) {logger.debug("Multipart resolution failed for current request before - " +"skipping re-resolution for undisturbed error rendering");}else {return this.multipartResolver.resolveMultipart(request);}}// If not returned before: return original request.return request;}3、然后调用getHandler方法来匹配每个HandlerMapping对象,如果匹配成功会返回这个Handle的处理链HandlerExecutionChain对象,在获取该对象的内部其实也获取我们自定定义的拦截器,并执行了其中的方法
见源码:
doDispatch:
HandlerExecutionChain mappedHandler = null;mappedHandler = getHandler(processedRequest);getHandler方法:
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {for (HandlerMapping hm : this.handlerMappings) {if (logger.isTraceEnabled()) {logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");}HandlerExecutionChain handler = hm.getHandler(request);if (handler != null) {return handler;}}return null;}
hm.getHandler方法:
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {Object handler = getHandlerInternal(request);if (handler == null) {handler = getDefaultHandler();}if (handler == null) {return null;}// Bean name or resolved handler?if (handler instanceof String) {String handlerName = (String) handler;handler = getApplicationContext().getBean(handlerName);}return getHandlerExecutionChain(handler, request);}getHandlerExecutionChain:
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));chain.addInterceptors(getAdaptedInterceptors());String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {chain.addInterceptor(mappedInterceptor.getInterceptor());}}return chain;}4、执行拦截器的preHandle方法,如果返回false执行afterCompletion方法并理解返回
5、通过上述获取到了HandlerExecutionChain对象,通过该对象的getHandler()方法获得一个object通过HandlerAdapter进行封装得到HandlerAdapter对象
6、该对象调用handle方法来执行Controller中的方法,该对象如果返回一个ModelAndView给DispatcherServlet
7、DispatcherServlet借助ViewResolver完成逻辑试图名到真实视图对象的解析,得到View后DispatcherServlet使用这个View对ModelAndView中的模型数据进行视图渲染
4 0
- 源码深度解析SpringMvc请求运行机制
- SpringMVC解析请求响应请求过程-源码分析
- SpringMVC 深度解析@RequestMapping
- SpringMVC运行机制
- springmvc运行机制
- SpringMVC 运行机制
- springmvc运行机制
- JavaWeb——springMVC请求数据绑定分类解析(深度好文)
- Struts1 源码深度解析
- Struts 源码深度解析
- Spring源码深度解析
- spring源码深度解析
- 深度解析ReentrantLock源码
- 深度解析CountDownLatch源码
- 深度解析CyclicBarrier源码
- HashMap源码深度解析
- apscheduler 源码深度解析
- Redux源码深度解析
- 073.Traverse Array 遍历数组简化版
- 074.Traverse Array 遍历数组的常见错误
- 075.Quick Sort 快速排序
- SQLServer检查表字段是否存在,不存在则创建的脚本
- Android Studio AIDL 自定义类型找不到问题
- 源码深度解析SpringMvc请求运行机制
- 在VMware里的linux用minicom读取串口数据
- eclipse.ini
- Spring依赖注入的几种实现方式
- MongoDB安装、配置、启动(MAC)
- SQlife(数据库)
- 正确理解ThreadLocal,线程私有
- [leetcode] 204.Count Primes
- linux下svn的用法小结