SSM源码解密-第2章 Spring MVC整体架构

第2章 Spring MVC整体架构

本章我们学习Spring MVC的各个组件的功能职责、组件之间的接口定义以及各个组件之间的交互和通信,进而从整体架构的层次上理解Spring MVC框架的基本工作原理。

2.1 组件之间的整体交互流程

一个HTTP请求发送到Web容器,Web容器就会封装一个HTTP请求(HttpServletRequest)对象,这个对象包含所有的HTTP请求信息,例如:HTTP参数以及参数值,HTTP请求头的各种元数据等。同时,Web容器会创建一个HTTP响应(HttpServletResponse)对象,用以发送HTTP响应内容给客户端用户。然后,Web容器传递HTTP请求(HttpServletRequest)对象和HTTP响应(HttpServletResponse)对象给Servlet对象的service方法。

实际上,Spring MVC的入口是一个定制化的Servlet,称为派遣器Servlet(DispatcherServlet)。这个派遣器Servlet得到HTTP请求(HttpServletRequest)对象和HTTP响应(HttpServletResponse)对象后,一个典型的Spring MVC工作流程就开始了。

接下来发生的Spring MVC工作流程如图2-1所示。

图2-1

派遣器Servlet首先查找所有注册的处理器映射器(HandlerMapping)对象,然后,遍历所有的处理器映射器对象,直到一个处理器映射器对象返回一个非空的处理器执行链(HandlerExecutionChain)对象。处理器执行链对象包含一个需要处理当前HTTP请求的一个处理器(Handler)对象,如图2-1的第1步所示。

一个处理器对象被设计成了一个通用的对象类型,这里需要一个处理器适配器(HandlerAdaptor)来派遣这个控制流到一个处理器对象,因为只有支持这种类型的处理器对象的处理器适配器才知道如何去传递控制流给这个类型的处理器对象。

拿到了处理器对象以后,派遣器Servlet对象查找所有注册的处理器适配器对象,然后,遍历所有的处理器适配器对象查询是否有一个处理器适配器对象支持这个处理器对象,如图2-1第2步所示。

如果有这样的一个处理器适配器对象,则派遣器Servlet对象将控制权转交给这个派遣器适配器对象,如图表2-1第3步所示。派遣器适配器对象和真正的处理器对象是成对出现的,所以,这个支持的处理器适配器对象知道如何去使用这个处理器来处理当前请求。

最简单的一个处理器则是控制器对象(Controller)。处理器适配器对象将传递HTTP请求对象和HTTP响应对象给控制器对象,并且期待控制器返回模型和视图(ModelAndView)对象,如图2-1第4步所示。这里,模型和视图对象包含着一组模型数据和视图逻辑名称,并且最终返回给派遣器Servlet对象。

派遣器Servlet对象然后查找所有注册的视图解析器(ViewResolver)对象,并且遍历所有的视图解析器对象,直到一个视图解析器对象返回一个物理的视图(View)对象,如图表2-1第5步所示。

最后,派遣器Servlet把得到的一组模型数据传递给得到的物理视图对象,如图表2-1第6步所示。然后,视图对象则会使用表现层技术,把模型数据展现成UI界面,并且通过HTTP响应对象发送给HTTP客户端。

2.2 组件以及组件的接口

通过上一节对组件之间的整体交互流程的分析,我们看到Spring MVC是由若干组件组成的,这些组件相互独立又相互协调共同完成Spring MVC的整体工作流程。其中,每个组件都有清晰的接口定义,接口后面都有一个设计良好的类实现体系结构,清晰的抽象出公用的逻辑并且实现在通用的抽象类里,同时提供各种常用的具体实现类,进而实现一个清晰的、高可扩展的、可插拔的MVC体系结构。

这里我们介绍这些典型的组件,组件的功能以及组件所定义的接口。

2.2.1 派遣器Servlet(DispatcherServlet)

派遣器Servlet对象是Spring MVC中最核心的组件之一,也是Spring MVC的总控组件。它是一个实现类而并不是一个接口,从类的继承角度来看,派遣器Servlet类继承自FrameworkServlet类,而FrameworkServlet继承自HttpServlet类,每一层集成完成一定的功能,集成的层次越往上完成的功能约通用,抽象的程度就越高,这样的类的层级划分使得派遣器Servlet的类体系结构清晰明了、任务分明、容易扩展,派遣器Servlet类结构如下图2-2所示。

图2-2

当应用初始化时,派遣器Servlet对象通过内部的Spring Web应用程序环境,找到相应的Spring MVC的各个组件,如果这些组件没有显式配置,Spring MVC将会根据默认加载策略初始化各个模块的默认实现。

当服务一个HTTP请求时,它通过一套注册的处理器映射对象找到一个处理器对象,然后,从一套注册的处理器适配器对象中找到一个支持这个处理器对象的处理器适配器对象,并且通过它把控制流转发给这个处理器对象,处理器对象结束业务逻辑的调用后把模型数据和逻辑视图传回派遣器Servlet对象。

派遣器Servlet对象再通过视图解析器对象得到真正的视图对象,把控制权交给视图对象,同时传入模型数据,视图对象会按照一定的视图层逻辑展现这些数据给HTTP的客户端用户。

2.2.2 处理器映射(HandlerMapping)

处理器映射对象是用于映射一个请求对象到一个处理器对象。一个Spring MVC实例可能会包含多个处理器映射对象,按照处理器映射对象所在的顺序,第一个返回非空处理器执行链对象的处理器映射,会被当作为有效的处理器映射对象。处理器执行链对象包含一个处理器对象和一组能够应用在处理器对象上的拦截器对象(Interceptor).

处理器映射的类结构如下图2-3所示。

图2-3

HandlerMapping是一个接口,在这个接口中,通过输入一个HTTP请求对象给方法getHandler,这个方法就会输出一个处理器执行链对象。进而我们能够从处理器执行链对象获得一个处理器对象。

2.2.3 处理器适配器(HandlerAdaptor)

处理器适配器对象是用来转接一个控制流到一个指定类型的处理器对象。一个类型的处理器对象通常会对应一个处理器适配器对象的一个实现。处理器适配器对象能够判断自己是否支持某个处理器对象。如果一个处理器适配器对象支持这种类型的处理器,那么这个处理器适配器对象就可以使用这个处理器对象处理当前的这个HTTP请求。

然而,处理器对象是通用的Object类型的一个实例, 这样做是为了提供高可扩展性,允许Spring MVC可以任意的去集成其他框架的处理器对象,只需要为这个需要支持的处理器对象提供一个定制化的处理器适配器对象即可,就可以在不改变任何上层派遣器Servlet代码以及下层控制器对象代码的前提下,实现集成任意其他框架。其中,HttpRequestHandlerAdapter是用来处理流文件的处理器适配器,SimpleServletHandlerAdapter是用来转接给Sevlet的处理器适配器,RequestMappingHandlerAdapter是用来处理注释的方法的控制器。

处理器适配器的类结构如下图2-4所示。

图2-4

在这个接口中,通过输入一个处理器对象给supports方法,这个方法就会返回是否支持这个处理器。通过传入一个HttpServletRequest,HttpServletResponse和一个Hanlder对象给handle方法,这个方法就会传递控制权给处理器对象。当处理器对象处理这个HTTP请求后返回数据模型和逻辑视图名称的组合对象,处理器适配器会把这个返回结果进而返回给派遣器Servlet。

最后,getLastModified方法是用来处理一个带有lastModified头信息的HTTP请求的。不是所有的处理器适配器都需要支持这个方法的。

2.2.4 处理器对象/控制器对象(Handler/Controller)

处理器对象是用于处理业务逻辑的一个基本单元,它通过传入的HTTP请求对象来决定如何处理业务逻辑和执行哪些服务,执行服务后返回相应的模型数据和逻辑视图名。一个请求的控制流是由处理器适配器传递给处理器对象的,一个类型的处理器对象一定会对应一个支持的处理器适配器。这样可以实现,处理器适配器和处理器之间的任意匹配,具有灵活的可插拔性。

处理器对象是一个通用的Object类型,控制器类型是最典型的一个处理器类型,控制器的类结构如下图2-5所示。

图2-5

控制器是Spring MVC中最简单的一个处理器,这个处理器有清晰的接口定义,通常这个类型的处理器对象是通过一个简单控制处理器适配器对象(SimpleControllerHandlerAdapter)来传递控制的。

在这个接口中,通过输入一个HTTP请求对象和一个HTTP响应对象给handleRequest方法,这个方法就会返回一个处理后的模型数据和逻辑视图名的组合对象。这个对象将通过处理器适配器进而返回给派遣器Servlet。

Spring MVC之所以具有高可扩展性,在于处理器适配器和处理器的设计。这样可以让任意的一个处理器对象插入到Spring MVC的体系结构中,使它具有无限的扩展性。

2.2.5 视图解析器(ViewResolver)

视图解析器对象用于映射一个逻辑视图名称到一个真正的视图对象。当控制器处理完业务逻辑之后,通常会返回需要显示的数据模型对象和视图的逻辑名称,这样就需要一个视图解析器对象通过视图的逻辑名称解析出一个真正的视图对象,然后传递控制流给这个视图对象,由视图对象展示数据给HTTP的客户端用户。

视图解析器的类结构如图2-6所示。

图2-6

在视图解析器接口中,通过输入一个逻辑视图名称和本地对象(Locale)给resolveViewName方法,这个方法就会返回一个事实上的物理视图对象。本地对象可以用来查找本地化的资源或者资源包。

2.2.6 视图(View)

视图用来把模型数据通过某种显示方式反馈给客户,通常是通过执行JSP页面来完成的。也可以通过其他的更复杂的显示技术来完成这个展示过程,例如,XML视图、JSON视图、JSTL视图,Tiles视图,报表视图和二进制文件视图等。

视图的类结构如图2-7所示。

图2-7

在视图接口中,通过输入HTTP请求对象、HTTP响应对象和一个模型Map对象,这个组件就会把模型Map通过一定的显示方式输出到客户的HTTP响应对象,这就是提供给用户请求的最终响应。getContentType()能够返回这个视图所支持的内容类型,例如,XML, JSON, text/html等。

2.3 本章小结

本章我们学习Spring MVC的实现原理,具体分析了Spring MVC架构中的各个组件、组件的功能以及组件的接口定义,并分析了组件之间的整体交互流程。

从下一章开始,我们将从源码开始,深入剖析Spring MVC架构的具体实现方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,724评论 6 342
  • Spring MVC一、什么是 Spring MVCSpring MVC 属于 SpringFrameWork 的...
    任任任任师艳阅读 3,369评论 0 32
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • 原始母爱注入,是心理学的一个词语,原始指的是生命早期的时候,(0-1岁),妈妈,全神贯注在孩子身上,因为投入,妈妈...
    王老师_92c3阅读 223评论 0 3