MVC简介,SpringMVC简介及基本流程

目录

MVC简介

Spring MVC流程简介

HandlerMapplng先生(Web请求的处理协调人)

org.springframework.Web.servlet.Controller(Web请求的具体处理者)

ViewResolver和View (视图独立战争的领导者)

流程图

SpringMVC流程实践

Spring MVC应用的物理结构

ContextLoaderListener与/WEB-INF/applicationContext.xml

DispatcherServlet与XXX-servtet.xml

扫描二维码关注公众号,回复: 10855803 查看本文章

按部就班地开始工作

配置基础装备

开发独立的业务逻辑

添加Web请求入口

添加HandlerMapping

实现对应的Controller井添加到配置文件

添加ViewResover

实现相应视图


MVC简介

MVC (Model-View-Controller,模型-视图-控制器)在当今Java界尤其是Web开发领域已经是耳熟能详的一个名词了。

如图所示,最初意义上的MVC模式中,各个组件的作用如下所述。

控制器负责接收视图发送的请求并进行处理,它会根据请求条件通知模型进行应用程序状态的更新,之后选择合适的视图显示给用户。

模型通常封装了应用的逻辑以及数据状态。当控制器通知模型进行状态更新的时候,模型封装的相应逻辑将被调用。执行完成后,模型通常会通过事件机制通知视图状态更新完毕,从而视图可以显示最新的数据状态。

视图是面向用户的接口。当用户通过视图发起某种请求的时候,视图将这些请求转发给控制器进行处理。处理流程流经控制器和模型之后,最终视图将接收到模型的状态更新通知,然后视图将结合模型数据,更新自身的显示。

可见,最初意义上的MVC模式,在视图与模型间的数据同步工作是采用从模型Push到视图的形式完成的。而对于Web应用来说,局限于所用的协议以及使用场景,无法实现从模型Push数据到视图这样的功能。所以,我们只能对MVC中的组件的最初作用定义做适当的调整。

由控制器与模型进行交互,在原来通知模型更新应用程序状态的基础上,还要获取模型更新的结果数据,然后将更新的模型数据一并转发给视图。也就是说,我们现在改由控制器从模型中Pull数据给视图,这种意义上的MVC称为Web MVC,也就是现在大多web的架构模式。

Spring MVC流程简介

Spring MVC框架的处理控制器的实现策略,与其他的请求驱动的Web框架在总体思路上是相似 的,就如我们之前所说的那样,通过引入Front Controller和Page Controller的概念来分离流程控制逻辑 与具体的Web请求处理逻辑。org.springframework.web.servlet.DispatcherServlet就是 SpringMVC框架中的Front Controller, 它负责接收并处理所有的Web请求。

只不过针对具体的处理逻辑, 它会委派给它的下一级控制器去实现,即org.springfrarnework. web. servlet .mvc. Controller, 而 org.springframework.web.servlet. mvc.Controller则对应Page Controller的角色定义,具体关 系如图所示。

当然,只有它们两个还远远称不上一个完整的Web开发框架,要使得整个的Web开发框架能够运 作起来,我们还需要更多的角色相助。下面,让我带你走过DispatcherServlet这道长廊,井乘机一 一介绍SpringMVC中的各位“掌权者”。

在我们开始Dispatcherservlet的旅程之前,不妨先回顾一下控制器Servlet常会做哪些工作。

就以我们JSPModel2架构中提到的MockMagicServlet为例,它在处理Web 请求的过程中所做的工作,我们可以简单归纳为如下三点。

获取请求信息,比如请求的路径、各种参数值等,如下所示:

根据请求信息,调用具体的服务对象处理具体的Web请求,如下所示:

处理完成后,将要在视图中显示的模型数据通过request进行传递,最后通过Request­Dispatcher选择具体的jsp视图井显示,如下所示:

有了以上Mock.MagicServlet处理流程的剖析作为基础,现在我们再来看Dispatcherservlet 在整个Web请求处理过程中所做的布情,就会发现,DispatcherServlet在实现上并没有太多不同 或者说改变,唯一的差异或者改变是,DisPatcherServlet将各项工作细化并分离给了较为独立的角色来完成。

DispatcherServlet的处理流程。可以简单概括如下。

HandlerMapplng先生(Web请求的处理协调人)

既然DispatcherServlet是整个框架的FrontController, 当将它注册到web.xml时,就注定了它要 服务于规定的一组Web请求的命运而不是单独的一个Web请求。代码清单是Dispatcherser:vlet 注册到web.xml配贾文件的通常示例。

不能够像“一个Web请求对应一个Servlet"那样获取Web容器对URL映射匹配的支持,Dispat­cherServlet现在只好自己来处理具体的Web请求和具体的处理类之间的映射关系匹配了。

对于Web请求与具体的处理类之间的映射匹配来说,具体的处理方式或者说策略可能多种多样, 完全可能随着应用程序,甚至每个具体的Web请求的不同而发生变化,如下所述。

最常见的就是,那种“抬头去尾"的处理方式,将Web请求的URL路径去除前面的上下文路径 (context path)和最后的扩展名,取最终剩下的路径信息,作为匹配的结果。比如,如下代码 将最终以resource作为匹配结果。

http://www.nosuchna:me.com/yourapp/resource.html

以Web请求的URL中存在的某个参数的值作为匹配的标准。比如,当发现请求的路径中存在 controller这个参数的话,其值就会被作为匹配结果用来调用具体的处理类,对于如下所示 的URL:

http://www.nosuchname.com/yourapp/resource.htm?controller=yourController

匹配的结果就是yourController。

以cookie或者session中的某些信息作为匹配标准。比如,针对某个客户的Web请求,全部转发 给一个处理类进行处理。

甚至于,结合Ruby On Rails的理念,我们在开发中规定一些惯例或者说约定,然后以这些惯例或 者约定来解析Web请求的URL路径信息,以获取具体的处理类匹配。可见,要将映射匹配的逻辑写死 到DispatcherServlet, 是无法有效扩展的,而且匹配的方式也可能随着需求而变化。

所以,SpringMVC 为了能够灵活地处理映射的匹配,引入了org.springframework.Web.servlet.HandlerMapping 来专门管理Web请求到具体的处理类之间的映射关系。在Web请求到达DispatcherServlet之后, Dispatcher将寻求具体的HandlerMapping实例,以获取对应当前Web请求的具体处理类,即 org.springframework.web.servlet.Controller。

org.springframework.Web.servlet.Controller(Web请求的具体处理者)

org.springframework.Web.servlet.Controller是对应DispatcherServlet的次级控 制器,它本身实现了对应某个具体Web请求的处理逻辑。

在我们所使用的HandlerMapping查找到 当前Web请求对应哪个org.springframework.web.servlet.Controller的具体实例之后, Dispatcherservlet即可获得HandlerMapping所返回的结果,并调用org.springframework. web.servlet.Controller的处理方法来处理当前的Web请求。

org.springframework.Web.servlet.Controller的处理方法执行完毕之后,将返回一个org.springframework.Web.servlet.ModelAndView实例,MoclelAndView含了如下两部分信息。

视图的逻辑名称(或者具体的视图实例)。DispatcherServlet将根据该视图的逻辑名称, 来决定为用户显示哪个视图。

模型数据。视图渲染过程中需要将这些模型数据并入视图的显示中。

有了ModelAndView所包含的视图与模型二者的信息之后,DispatcherServlet就可着手视图的 渲染工作了。

ViewResolver和View (视图独立战争的领导者)

按照MockMagicServlet的处理流程,我们已经走到了最后一步,即选择并转到最终的JSP视图文 件,即如下代码所展示的逻辑:

但是,对于一个Web框架来说,我们是不可以这么简单处理的。为什么呢?不要忘了,现在可 用的视图技术可不只JSP一家,Velocity、Freemarker等通用的模板引擎,都可以帮助我们构建相应 的视图,而它们是不依赖于request对象来传递模型数据的,甚至,我们也不只依赖JSP专用的RequestDispatcher输出最终的视图。否则,我们也没有必要通过ModelAndView返回视图以及 模型数据了,直接在org.springframework.web.servlet.Controller内部完成视图的渲染工作就 可以了。不是吗?鉴于此,Spring提出了一套基于viewResolver和View接口的Web视图处理抽象层, 以屏蔽Web框架在使用不同的Web视图技术时候的差异性

那么,Spring MVC是如何以统一的方式,将相同的模型数据纳入不同的视铅形式井显示的呢? 实际上,撇开JSP使用的RequestDispatcher不谈,Servlet自身就提供了两种最基本的视图输出方 式。不知道你还是否记得最初的out..println? 基本来说,我们要向客户端输出的视图类型,可以 分为文本和二进制两种方式,比如JSP/JSTL、Velocity/Freemarker等最终的输出结果都是以(X)HTML 等标记文本形式表现的,而PDFffixcel之类则属于二进制内容行列。对于这两种形式的视图内容的输 出,Servlet自身公开给我们的HttpServletResponse已经足够可以应付了。代码清单展示了 HttpServletResponse是如何帮助我们处理这两种形式的视图输出的。

在HttpServletResponse可以同时支持文本形式和二进制形式的视图输出的前提下,我们只要在 最终将视图数据通过HttpServletResponse输出之前,借助于不同的视图技术API, 并结合模型数据 和相应的模板文件,就能生成最终的视图结果,如下伪代码所示:

这样,不管最终生成的视图内容如何,我们都可以以几乎相同的方式输出它们。但唯一的问题 在于,我们不可能将每个视图的生成代码都纳入DispatcherServlet的职权范围,毕竞,每种视图 技术的生成代码是不同的,而且所使用的视图技术也可能随着具体环境而变化。

Spring MVC通过引 入org.springframework.Web.servlet.View接口定义,来统一地抽象视图的生成策略。之后, DispatcherServlet只需要根据Spring Controller处理完毕后通过ModelAndView返回的逻辑视图名称 查找到具体的View实现,然后委派该具体的View实现类来根据模型数据,输出具体的视图内容即可。

Spring的View抽象策略示意图如图所示。

现在,视图模板与模型数据的合并逻辑,以及合并后的视图结果的输出逻辑,全部封装到了相应 的View实现类中。DispatcherServlet只需要根据ModelAndView返回的信息,选择具体的View实现 类做最终的具体工作即可。

不过,与HandlerMapping帮助Dispatcherservlet查找具体的Spring Controller以处理Web请求类似,Dispatcherservlet现在需要依赖于某一个org.springframework. web.servlet.ViewResolver来帮它处理逻辑视图名与具体的View实例之间的映射对应关系。 ViewResolver将根据ModelAndView中的逻辑视图名查找相应的View实现类,然后将查找的结果返回 DispatcherServlet。DispatcherServlet最终会将ModelAndView中的模型数据交给返回的View处理最终的视图渲染工作。

至此,整个DispatcherServlet的处理流程即告结束。

流程图

如果你还不足以从以上流程概略中分出哪个角色对应什么样的工作,图所展示的Sequence图 或许可以帮助大家加深一下印象。

SpringMVC流程实践

如果你已经读到了这里,我完全能够理解你要实现第一个基于Spring MVC的Web应用程序的迫切心 情,毕竟一味地纸上谈兵令人腻烦,那么让我们开始一个我称之为SimpleFX的Web应用程序的开发吧!

一个外汇交易系统与其他的软件系统在本质上没有任何差别,为了能够便于一些数据的管理,我 们也需要一个用于后台管理的应用程序。既然是讲解SpringMVC, 我们打绊以Web应用程序的形式来 开发后台管理功能,这个用于后台管理的Web应用程序我们暂且就称其为SimpleFX。因为不打算完全 实现它所有的功能,只要能够通过几个功能的开发阐明SpringMVC的相应特点即可。整个后台管理程 序的显示布局如图所示。

其中,左边的各个FunctionSe氓示相应的管理功能集合,我们可以通过点击这些FunctionSct的链 接来触发相应的笥理诸求,剩下的部分为主画面显示,一看便知。

本次我们要开发的是一个简单的显示外汇交易当天评价汇率的Web请求处理流程。在点击相 应的链接之后,我们可以获取当天评价汇率的显示信息,类似于图所示的主画面显示。

Spring MVC应用的物理结构

虽然我们已经从总体上了解了SpringMVC框架在处理Web请求过程中所涉及的几个主要成员,但 目前为止,它们只是逻辑上的概念,对于我们来说,只是一座座的空中楼阁。我们现在得面对现实, 从实体结构上看一下,一个典型的基于SpringMVC的Web应用程序,通常是如何组装而成的(听起来 好像我们在造一辆汽车的感觉),然后再真正地开始咯手构建我们的第一个基于SpringMVC的Web应 用程序。

一个基于Spring MVci匡架的Web应用,依然是一个遵循Servlet规范的Web应用程序,自然,它也 就拥有一个遵循Servlet规范的Web应用程序应有的目录结构和相应的部署描述符(Deployment Descriptor)文件。只不过,在此基础上,基于SpringMVC框架的Web应用会再增加两个(或者多个) 配汽文件,整个图景如图所示。

我们以Web.xml作为出发点,它是整个Web应用程序的部署描述符文件,这是所有基于Servlet 规范的Web应用程序都有的东西,我想大家对它应该井不陌生。在图右边的就是web.xml的具体 内容。当然,在这个部署描述符文件中,我们还可以根据需要添加其他元素,比如可能需要进行字 符编码的转换,那会增加一个Filter的定义,或者添加welcome文件列表以及异常处理页面相关内容 等。不过为了避免混淆视听,我们这里仅挑了与Spring MVC有关的元素进行重点阐述。

ContextLoaderListener与/WEB-INF/applicationContext.xml

从web.xml开始,我们首先通过<listener>元素增加了一个ServletContextListener的定义,即 org.springfrarnework.Web.context.ContextLoaderListener。ContextLoaderListener的职责在 于,它将为整个的Web应用程序加载顶层的WebApplicationContext (ROOT WebApplication­Context)。该顶层WebApplicationContext主要用于提供应用所使用的中间层服务。

我们所使 用的数据源(DataSource)定义、数据访问对象(DAO)定义、服务对象(Services)定义等,都在 该WebApplicationContext中注册。你完全可以将其比作独立运行的应用程序中我们所使用的 ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext。只不过,WebAp­plicationContext专门用于Web环境下,在这种容器中,我们可以使用在讲解Spring的loC容 器部分提到的自定义scope来注册相应的bean定义了,包括request、session等。

ContextLoaderListener加载的WebApplicationContext的默认配置文件路径为/WEB-INF/ applicationContext.xml, 这也就是图中的/WEB-INF/目录下存在一个applicationContext.xml 配置文件的原因。该文件符合通用的Spring IoC容器配览文件格式。实际开发中,不管是出于团队 并行开发效率的考虑,还是出于便于管理的因素考虑,很少会使用默认的单一的/WEB-INF/ applicationContext.xml来管理整个Web应用程序的所有中间层服务对象。我们要么会按照应用程序的 层次进行配置文件的分割,要么会按照系统功能模块进行配置文件的分割。当存在多个分割后的配 置文件的时候,ContextLoaderListener的默认加载行为将成为我们的制约。这时,我们可以通 过在web.xml中指定名称为contextConfigLocation的配置参数来打破默认行为的制约,如代码洁 单所示。

ContextLoaderListener或者ContextLoaderServlet加载相应路径下的容器配置文件, 并在构建完成相应的顶层WebApplicationContext后,将该顶层WebApplicationContext绑定 到ServletContext。

如果想获取绑定到ServletContext的WebApplicationContext, 我们可 以通过org.springframework.web.context.support.WebApplicationContextlJtils类。 这样就不需要知道顶层WebApplicationContext绑定到ServletContext的时候使用的Key是什 么,例如:

了解这一点的主要目的在于,绑定到ServletContext的顶层WebApplicationContext并非 只能在基于Spring MVC的Web应用程序中使用。通过ContextLoaderListener或者ContextLoa­derServlet将其绑定到ServletContext, 任何类型的Web应用程序(当然指的是基于Java平台技术 的Web应用程序),只要能够获取ServletContext的引用,就能获取并使用该WebApplication­Context。

换句话说就是,即使当前使用的Web开发框架没有类似于Spring提供的基于IoC容器的中间 层业务对象眢理支持,通过在web.xml中注册ContextLoaderListener或者ContextLoaderServlet, 也可以获取这种支持。所谓的集成Spring与第三方Web应用框架,最多只是在此基础上做进一步的 扩展。

DispatcherServlet与XXX-servtet.xml

对于web.xml中org.springframework.Web.servlet.DispatcherServlet的注册,表面看起来 并无太多玄机,与注册其他Servlet并无二致,但事实并非如此。我们说过,DispatcherServlet是 基于SpringMVC框架Web应用程序的Front Controller, 它将负责几乎所有对应当前Web应用程序的 Web请求的处理。

如果我们之前使用过Struts框架的话,那么可以将DispatcherServlet比做 Struts框架中的ActionServlet, 实际上二者所完成的工作,性质上应该是一致的。Struts框架中的 ActionServlet会从外部的struts-config.xml配置文件中读取Web处理过程中所需要的各种数据, 包括form bean定义、action以及action mapping等。

与之类似,DispatcherServlet也使用了一个 外部化的配置文件,用来配置Spring MVC框架在处理Web请求过程中所涉及的各个组件,包括 HandlerMapping定义、Controller定义、View Resolver定义等。该外部化的配置文件存在的默认路 径也是/WEB-INF/, 名称需要参照web.xml中定义的DispatcherServlet的<servlet-name>来决定。

比如,我们当前定义的DispatcherServlet对应的<servlet-name>为controller, 那么,默 认的配置文件即对应WEB-INF/controller-servlet.xml, 也就是说,DispatcherServlet对应的默认配 置文件名称,将在<servlet-name>的值的基础上后缀-servlet.xml。如果我们定义DispatcherServlet 的<servlet-name>为simplefx, 那么它的配置文件名称就应该为simplefx-servlet. xml, 以 此类推。

<Servlet-name>-servlet.xml与/WEB-INF/applicationContext.xml相同,也符合Spring IoC容器配置文件格式。只不过,相对于/WEB-INF/applicationContext.xml来说,<servlet-name>servlet.xml 有自己的职责。<servletname>-servlet.xml主要负责配置基于SpringMVC框架的Web应用程序所 使用的各种Web层组件,具体内容看起来如代码清单所示,

DispatcherServlet启动之后将加载<servlet-name>-servlet.xml配置文件,并构建相应的 WebApplicationContext。该WebApplicationContext将之前通过ContextLoaderListener加载的 顶层WebAppl icationcontext (ROOT WebAppliCationContext)作为父容器(Parent ApplicationContext)。

这样,如果需要,<servlet-name>-servlet.xml中注册的各种面向Web层的组件,也可以注入来 自顶层WebApplicationContext的依赖了。所以,我们也就不难想象出<servlet-name>-servlet .xml对应的WebApplicationContext和默认的/WEB-INF/applicationContext.xml对应的顶层 WebApplicationContext之间的逻辑依赖关系了。

即使Web层通常很簿,但随~Web应用程序的开发进程,单一的<servlet-name>-servlet. xml文件有可能成为团队并行开发的瓶颈,或者其身材也可能会越加擁肿。出于这些因素考虑,我 们需要寻求分割单一的<servlet-name>-servlet.xml文件的解决方法,而DispatcherServlet 的contextConfigLocation初始化参数就是为此而生的。代码洁单给出了该初始化参数的使 用配置代码示例。

按部就班地开始工作

我们要实现的当日评价汇率显示流程可以简单描述,如图所示。

从浏览器中点击后台管理画面的相应链接之后,Web请求将被发送到DispatcherServlet进行处理。DispatcherServlet将寻求相应的HandlerMapping对Web请求进行分析,然后调用匹 配结果对应的Controller实现,具体到当前场景就是我们要实现的TTMRateListController。

TTMRateListController处理完毕将视图名称ttmRatetist和模型数据一同返回,然后Dispatcherservlet则借助于相应的ViewResolver, 根据返回的视图名选择相应的视图Cttm­RateList.jsp并显示,这就是整个流程。下面则是实现这个Web处理流程的详细步骤,各位上眼 瞧啦!

当日评价汇率Web处理流程实现步骤概况如下。

配置基础装备

每个符合Java EE规范的Web应用程序都需要符合相应的目录结构,如图所示。工作之初,我们需要构建Web应用的基础结构。不过,现在的IDE通常都有良好的Web开发支 持,使用Eclipse IDE的话,添加WTP (Web Tools Platform)或者My氐lipse插件的支持即可。剩下的 只是按照Wizard的说明构建一个Web应用的工程就行了,我们这里要建立的是simplefx工程。 simplefx工程建立之后,我们还有如下两件事情要做。

a)配置web.xml。我们需要将org.springframework.Web.servlet.DisPatcherServlet和 org.springframework.Web.context.ContexttoaderListener通过<servlet>和<listener>元素添 加到web.xml部署描述符文件中,原因我们之前已经领教了。另外,出于其他目的考虑,我们还可以 添加相应的Filter以及ServletContextListener以处理字符编码和Log4j初始化等配党内容,这些 完全根据当前应用程序的需求情况来决定。现在,我们的web.xml看起来如代码清单所示。

其他配置元素可能随省内容的深入继续添加。

b)WebApplicationContext文件的添加。我们需要在WEB-INF/目录下添加org.springframe­work.Web.servlet.Dispatcherservlet和org.springframework.Web.context.Context­LoaderListener对应的WebApplicationContext配置文件(/WEB-INF/applicationContext.xml和 /WEB-INF/[servletname ]-servlet..xml)。

这完全可以从Spring下载文件包中的sample目录下任何一个Web 应用程序中复制过来。只不过,需要根据命名规则修改相应的文件名称。当然,复制过来的文件内容 最好是清空,只保留可以在当前应用中能够通用的配置内容。对于我们的simplefx来说,我们暂且消 空对应的两个WebApplicationContext配置文件内容。

以上基础设施构建完成之后,我们开始“盖楼”。

开发独立的业务逻辑

对于一个设计良好的Web应用程序来说,虽然Web层依赖于业务层对象, 但业务层却不应该对Web层有任何的依赖。Web层只应该看作是公开业务逻辑的一种视角或者交互方 式。这样做或者说这样吞待系统的好处在于,业务层可以独立设计并实现,而不需要关心最终通过什 么手段将服务公开给用户。鉴于这样的理念,我们完全可以从业务层开始眢手设计和实现我们的当日 评价汇率显示逻辑,而且在稍后介绍Spring Remoti'ng支持的时候,你将会更深地感受到这种看待系统 的视角所带给我们的系统设计与实现的福利。

既然涉及评价汇率,那么首先需要设计并实现的对象即对应评价汇率的域对象(Domain Object) , 其简单定义如代码清单所示。

每个营业日内对应系统中可交易的货币对,都存在一个评价汇率,所以,TrMRate中定义了必需 的三个字段分别对应营业日、货币对和对应的评价汇率值。

为了能够使各种客户端(当然包括Web客户端)能够获取当日的评价汇率,我们需要规定相应的 接口井公开给相应的客户端使用。现在这个接口定义很简单,定义如下:

只要客户端调用getTTMRatestoday ()方法,就将返回当前营业日内,系统所支持的所有货币对 对应的评价汇率。

单有接口并不能工作,我们还需要给出相应的实现。正常情况下,我们需要结合相应的数据访 问对象构建一个ITTMRateService的实现,以便能够从系统数据库中获取真正生产环境下的数据。 不过,我不打算这么做。出于简化实例考虑,我们现在只实现一个ITTMRateService的Mock对象。 真实环境下的ITTMRateService实现,如果你感兴趣可以自己把玩一下,ITTMRateService的 Mock对象定义如代码清单所示。

我们假设当天营业日对应20080302, 并将对应该日期的USD/JPY和EUR/USD两货币对的 评价汇率信息添加到返回列表中。整个Web应用的中间层服务支待,默认都是通过/WEB-INF/ applicationContext.xml注册(即ROOTypebAppl icationcontext)。所以,现在我们要将ITTMRate­Service的实现增加到Web应用程序顶层容器的配置文件中,如代码清单所示。

真实环境下,我们可能还需要向该容器配涩文件中添加数据源(DataSource)等一系列依赖对象。 在此之后,我们才真正开始Web层的开发。

添加Web请求入口

要让用户能够通过Web方式访问我们的评价汇率服务,我们得为用 户提供一个入口点。首先在后台管理的主画面左侧的functionSet中添加超链接,如下所示:

在用户点击该链接之后,浏览器将以http:// host: port/simplefx/ttmRateList.do的形式向服务器发起 Web请求。我们在web.xml中将所有以.do结尾的请求模式都映射给了DispatcherServlet来处理。接 下来的事情就由DispatcherServlet接手了。

添加HandlerMapping

DispatcherServlet在接收到Web请求之后,将寻求相应的 HandlerMapping进行Web请求到具体的Controller实现的匹配。所以,我们需要为Dispatcher­Servlet提供一个HandlerMapping的实现。

Spring MVC框架默认提供了多个HandlerMapping 的实现。我们将在稍后详细介绍。不过,当前我们暂且使用org.springframework.web.servlet. handler.BeanNameUrlHandlerMapping, 它将根据URL与Controller的bean定义的名称进行匹配。现 在我们将它添加到DispatcherServlet特定的WebApplicationContext中,即/WEB-INF/controller­serv let.xml, 如代码清单所示。

实际上,如果没有配置任何HandlerMapping的话,Spring MVC也会默认使用BeanNameUrl­HandlerMappin逃行URL到具体Controller的匹配。所以,以上的bean定义并非必须的。但是,这样 做的目的是要明确告知你,DispatcherServlet所使用的HandlerMapping要在哪里进行配置。稍后 你还将看到,如果默认的HandlerMapping的匹配模式并不讨人喜欢,我们还可以替换掉它,转而使 用自己喜欢的HandlerMapping实现。

总之,我们使用BeanNameUrlHandlerMapping进行URL到具体Controller的匹配之后,BeanName­UrlliandlerMapping将根据http:// host: port/simplefx/ttmRateListdo这一URL信息,在当前容器内寻找名 称为/ttrnRateList.do的Controller定义。这将是我们下一步要实现的东西。

实现对应的Controller井添加到配置文件

针对当前评价汇率的Web请求,我们需要实现一个 Controlle涞处理它。通常情况下,我们会扩展SpringMVC的org.springframework. Web. servlet. mvc.AbstractController来实现具体的Controller。正如我们的处理流程图所演示的那 样,我们的Controller名称为TTMRateListController, 具体定义如代码清单所示。

在TTMRateListController中,我们引用了ITTMRateService并借助它获取了当日的评价 汇率列表。viewName是将要转向的逻辑视图名称,可以将它写死到代码。不过,通过webAppli­cationContext的依赖注入,我们可以获取更多的灵活度。在视图名称和要显示的模型数据全都获 取之后,我们构造了一个ModelAndVie-w来封装这两部分信息,并返回。

只是实现了TTMRateListController, DispatcherServlet并不会知道它的存在,也不会知道 如何引用到它,所以,我们还得将TTMRateListController添加到DispatcherServlet特定的 WebApplicationContext中。现在/WEB-INF/controller-servlet~xml看起来更加充实了,如代码清单所示。

这里需要注意的是,TTMltateListController的ttmRateService注入的依赖来自org.springframework.Web.context.ContextLoaderListener加载的顶层WebApplicationContext

我们 说过,DispatcherServlet特定的WebApplicationContext以顶层WebApplicationContext 作为父容器。另外,BeanNameUrlHandlerMapping要求相应的Controller的bean定义名称以I开头, 所以,我们得使用<bean>的name属性来标志Controller对应的bean定义。

添加ViewResover

TTMRateListcontrolle工通过ModelAndView返回了一个逻辑视图名 ttmRateList, 而Dispatcherservlet要根据这个逻辑视图名查找相应的视图实现,就需要一个 ViewResolver来帮它。目前我们还不能在DispatcherServlet的特定WebApplicationContext中找 到一个ViewResolver的实现,所以至少得添加一个,否则也太令区spatcherservlet失望了。

Spring MVC也为ViewResolver提供了多种实现,我们当前决定使用比较眢及的JST/JSTL作为视 图技术,所以,将org.springframework.Web.servlet.view.InternalResourceViewResolver添 加到了DispatcherServlet特定的WebApplicationContext中,如代码清单所示。

我们为InternalResourceViewResolver指定了prefix,suffix这两个属性的自定义值。这样, 当我们的逻辑视图名(viewName)为ttmRateList的时候,InternalResourceViewResolver将去寻 找(prefix)+viewName+(suffix)名称的视图模板文件,也就是/WEB-INF/jsp/umRateList.jsp。不过看 来该JSP文件还没有创建。

实现相应视图

我们得提供InternalResourceViewResolver根据逻辑视图名所查找的 视图模板文件/WF,B-INF/jsp/ttmRateList.jsp。我们通过相应的IDE在/WEB-INF/jsp/目录下创建一个 ttroRateList.jsp文件如代码清单所示。

我们使用JSTL对模板中的显示逻辑进行管理,将在TTMRateListController中添加到Model­AndView的模型数据取出来并进行显示,也可以使用自己熟悉的自定义Taglib, 比如Struts的自定义 Taglib, 或者Spring MVC提供的自定义Taglib, 但绝不要使用Scriptlet来做这个工作,原因我们之前已 经说过了。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

发布了524 篇原创文章 · 获赞 80 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/xushiyu1996818/article/details/104158941
今日推荐