2019独角兽企业重金招聘Python工程师标准>>>

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);// Determine handler for the current request.mappedHandler = getHandler(processedRequest, false);if (mappedHandler == null || mappedHandler.getHandler() == 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 (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;}}// Apply preHandle methods of registered interceptors.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;}}// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// Do we need view name translation?if (mv != null && !mv.hasView()) {mv.setViewName(getDefaultViewName(request));}// Apply postHandle methods of registered interceptors.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");}}// Trigger after-completion for successful outcome.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);}}}

首先请求会经过各种filter最后进入DispatcherServlet类中的doDispatch方法。这个方法时整个请求转发最核心的方法,请求最终汇聚到这个方法被处理。者个方法时整个spring mvc框架的精华所在。它通过高度抽象的接口描述了一个MVC设计模式的实现方案。
HandlerExecutionChain这个对象是通过请求的url获得的处理器执行链,这个对象里面持有两个属性。一个是处理器,一个是拦截器数组。而请求将会最终通过处理器和拦截器进行处理。这儿的处理器是一个Object是java中最高的抽象,这样的设计有高度的扩展性,这个处理器可以是任何的实现,甚至是一个框架。
HandlerAdapter是一个处理器适配器接口,里面有一个很核心的抽象方法 ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
处理器的执行流程将在这个方法中定义,而且这个方法有高度可扩展性。里面可以实现任何的处理流程。这个方法最后会返回一个视图对象。
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;}}

这段代码主要是判断用户请求的资源文件有没有被修改。当用户第二次请求同一个资源,服务器端的资源也没有变化,那么这个请求将不会再被执行下去。
HandlerInterceptor是拦截器,这个接口有三个方法
public interface HandlerInterceptor {/*** Intercept the execution of a handler. Called after HandlerMapping determined* an appropriate handler object, but before HandlerAdapter invokes the handler.* <p>DispatcherServlet processes a handler in an execution chain, consisting* of any number of interceptors, with the handler itself at the end.* With this method, each interceptor can decide to abort the execution chain,* typically sending a HTTP error or writing a custom response.* @param request current HTTP request* @param response current HTTP response* @param handler chosen handler to execute, for type and/or instance evaluation* @return <code>true</code> if the execution chain should proceed with the* next interceptor or the handler itself. Else, DispatcherServlet assumes* that this interceptor has already dealt with the response itself.* @throws Exception in case of errors*/boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception;/*** Intercept the execution of a handler. Called after HandlerAdapter actually* invoked the handler, but before the DispatcherServlet renders the view.* Can expose additional model objects to the view via the given ModelAndView.* <p>DispatcherServlet processes a handler in an execution chain, consisting* of any number of interceptors, with the handler itself at the end.* With this method, each interceptor can post-process an execution,* getting applied in inverse order of the execution chain.* @param request current HTTP request* @param response current HTTP response* @param handler chosen handler to execute, for type and/or instance examination* @param modelAndView the <code>ModelAndView</code> that the handler returned* (can also be <code>null</code>)* @throws Exception in case of errors*/void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;/*** Callback after completion of request processing, that is, after rendering* the view. Will be called on any outcome of handler execution, thus allows* for proper resource cleanup.* <p>Note: Will only be called if this interceptor's <code>preHandle</code>* method has successfully completed and returned <code>true</code>!* <p>As with the {@code postHandle} method, the method will be invoked on each* interceptor in the chain in reverse order, so the first interceptor will be* the last to be invoked.* @param request current HTTP request* @param response current HTTP response* @param handler chosen handler to execute, for type and/or instance examination* @param ex exception thrown on handler execution, if any* @throws Exception in case of errors*/void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;}

preHandle是在处理器处理请求前执行,postHandle是在处理器处理请求后执行,afterCompletion是在 视图渲染完后执行。这样在进入处理流程的前后,视图渲染的前后都可以同过实现一个拦截器实现很多事情。比如spring-mobile就实现了一个DeviceResolverHandlerInterceptor,在preHandle这个方法里面实现创建了一个 Device对象,这个对象可以用来检查请求的来源,是手机,平板还是桌面电脑。
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {Device device = deviceResolver.resolveDevice(request);request.setAttribute(DeviceUtils. CURRENT_DEVICE_ATTRIBUTE, device);return true ;}

转载于:https://my.oschina.net/u/1583086/blog/342104

spring 从源码学设计1-doDispatch()相关推荐

  1. [从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用

    [从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用 文章目录 [从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用 0x00 摘要 0x01 业务领域 1.1 应用场景 0x02 ...

  2. 【赠书福利】掘金爆火小册同名《Spring Boot源码解读与原理剖析》正式出书了!...

    关注我们丨文末赠书 承载着作者的厚望,掘金爆火小册同名读物<Spring Boot源码解读与原理剖析>正式出书! 本书前身是掘金社区销量TOP的小册--<Spring Boot源码解 ...

  3. 视频教程-Spring底层源码分析-Java

    Spring底层源码分析 鲁班学院-子路老师曾就职于谷歌.天猫电商等多家互联网公司,历任java架构师.研发经理等职位,参与并主导千万级并发电商网站与后端供应链研发体系搭建,多次参与电商大促活动技术保 ...

  4. 实战:Spring Boot源码解读与原理分析

    承载着作者的厚望,掘金爆火小册同名读物<Spring Boot源码解读与原理剖析>正式出书! 本书前身是掘金社区销量TOP的小册--<Spring Boot源码解读与原理剖析> ...

  5. Spring Cloud源码分析(二)Ribbon(续)

    因文章长度限制,故分为两篇.上一篇:<Spring Cloud源码分析(二)Ribbon> 负载均衡策略 通过上一篇对Ribbon的源码解读,我们已经对Ribbon实现的负载均衡器以及其中 ...

  6. Spring AOP源码解析——专治你不会看源码的坏毛病!

    昨天有个大牛说我啰嗦,眼光比较细碎,看不到重点.太他爷爷的有道理了!要说看人品,还是女孩子强一些. 原来记得看到一个男孩子的抱怨,说怎么两人刚刚开始在一起,女孩子在心里就已经和他过完了一辈子.哥哥们, ...

  7. Spring Framework 源码解析课程大纲

    首先明确我们读Spring Framework的源码的目的是什么? 是为了显示自己很牛X么? Spring源码阅读的难度在于其呢内容庞大,并不是里面有很复杂的算法,需要高智商才能理解.所以你搞懂了Sp ...

  8. 一步一步手绘Spring AOP运行时序图(Spring AOP 源码分析)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  9. Spring AOP源码(1)—<aop:config/>AOP配置标签解析【一万字】

      基于最新Spring 5.x,对Spring AOP中的<aop:config/>标签的解析源码进行了详细分析,这是Spring AOP源码的入口!   此前我们已经详细学习了Spri ...

  10. C语言源码做的运动会管理系统课程设计(源码+课程设计报告)

    一.课程设计的目的: C语言程序设计课程设计是计算机科学与技术专业重要的实践性教学环节之一,本次设计结合实际应用的要求,使课程设计既覆盖C语言的知识点,又接近工程实际需要.目的是通过课程设计的综合训练 ...

最新文章

  1. MySQL中对varchar类型排序问题的解决
  2. Linux下实现apache代理tomcat
  3. hdu 5305 回溯+剪枝
  4. Android复习06【网络编程提高篇-安装GsonFormat、HttpUrlConnection封装、线程池、GsonFormat解析Json、自动加载下一页、自定义组件、页头页尾刷新、侧滑删除】
  5. 【Eclipse 字符集】Eclipse在哪里设置字符集?三个位置,分别控制不同的范围
  6. kuangbin专题十六 KMP扩展KMP HDU3068 最长回文
  7. Facebook将在印度测试联网无人机,可连续飞行90天
  8. textarea怎么占满整个td_保健品为什么偏偏盯上老人?作为子女,应怎么面对老人狂买保健品...
  9. C# 类型转换(is和as运算符)
  10. Cesium:搭建运行环境
  11. 汉字字符编码在线查询的网站
  12. 惠普m128fn中文说明书_惠普M128fn说明书
  13. hive会产生大量的tmp文件
  14. calendar java起始于结束时间,java获取一天的开始时间和一天的结束时间
  15. web版拳皇,使用html,css,js来制作一款拳皇游戏
  16. JS Knockoutjs 简单使用
  17. java 小偷_浅谈小偷程序之Java
  18. 网络编程 socket函数参数介绍
  19. visio首要任务闪退软件设置
  20. 水果做键盘控制跑跑卡丁车

热门文章

  1. Tomcat的设计模式
  2. CPU负载均衡之WALT学习
  3. 这个网站还不错,可以多看看(这个是学习的网站,没有广告)
  4. 吴锦华/明鑫: 用户态文件系统(FUSE)框架分析和实战
  5. Android WiFi 扫描并选择网络进行连接
  6. wireshark基本用法及过虑规则
  7. mysql 多版本删除_高性能MySQL(四):多版本并发控制
  8. java配环境变量_用于 Java 开发的配置工具 Simple Configuration Facade
  9. baum welch java_Baum Welch估计HMM参数实例
  10. python生成器推导式_python之推导式and生成器表达器笔记及面试坑