本文的主要内容是对 Grails 1.1 中 PetClinic-MVC 实例的代码分析。这个实例主要验证了如何在非 Grails 的项目中使用 GORM。此外也演示了 Spring MVC 2.5 的一些用法。本文假设大家对 Spring、Spring MVC、Groovy 和 Grails 有着初步的了解。OK, let's go!
Domain 层
目前 Grails 只提供了在普通 Spring 应用中独立使用 GORM 的方法(现在 Groovy 和 Grails 已是
SpringSource 旗下的产品了,自然要首先对自家产品提供支持)。不过相信以后在其它 Java EE 框架中也可独立使用 GORM。
在 Grails 以外使用 GORM,只需在 Domain 类上使用 grails.persistence.Entity 注释即可。其它的就像在 Grails 中的一样。
在配置方面也很简单,只要使用 <gorm:sessionFactory ... /> 即可。详细请见 Grails 的 PetClinic,这里就不拗述了。
Controller 层
同 Domain 层一样,Controller 层也全部使用 Groovy 实现。主要是因为 GORM 的大部分方法都是动态的。
1. ClinicController: ClinicController 实现了 InitializingBean
接口。这个接口只有一个方法 afterPropertiesSet。这个方法会在 Bean 完成属性设置之后执行。PetClinic
用这个方式实现了类似 Grails 中 BootStrap 的部分功能。在这个方法中我们可以看到 GORM 中的 save() 方法和
addTo* 动态方法都是可用的。
public void afterPropertiesSet() {
if (!Speciality.count()) {
def rad = new Speciality(name: "radiology").save()
...
new Vet(firstName: "Linda", lastName: "Douglas").
addToSpecialities(sur).save()
...
['dog', 'lizard', 'cat', 'snake', 'bird', 'hamster'].each {
new PetType(name: it).save()
}
}
}
可能有人会问,afterPropertiesSet()
这个方法的作用就是增加一些预定义的数据,为什么不使用构造函数来实现。实际上,在本例中,afterPropertiesSet()
的作用的确可以用构造函数来实现(经过测试)。至于作者是出于什么目的而选择了实现 InitializingBean 接口我也说不好。
ClinicController 的其它部分就是一些简单的不能再简单的 Http 请求处理函数了。需要说明的一点是 @RequestMapping 中的值代表了请求的 URL,这个是不用带后缀的,也就是说 ".do" 是多余的。
2. AddPetForm:
在 AddPetForm 类的级别上有三个注释,分别是 @Controller, @RequestMapping 和
@SessionAttributes。@Controller 不用多说,作用是这个类声明为一个 Spring Controller,并添加到
Context 中。下面介绍一下 @RequestMapping 和 @SessionAttributes 的功能:
- @RequestMapping 可以定义处理请求的路径和方法类型,即可放在类声明上,也可放在方法声明上。在 AddPetForm
中,类和方法上都有 @RequestMapping,类上的 @RequestMapping 用来定义请求路径。两个
@RequestMapping 的方法分别负责处理 get 请求和 post 请求。但我认为更好的方式是在一个 Controller
类中定义多个处理请求的方法,就像 Grails 的 Controller 那样。需要注意的是方法上面的 @RequestMapping
上面的值并不会覆盖类上的 @RequestMapping 中的值。
- @SessionAttributes 中的值代表了 org.springframework.ui.Model 中应该被设置为
Session 范围的变量。在 Spring MVC 应用中,这些变量往往是起到 ActionForm(Struts) 或
CommandObject(Spring MVC) 的作用。之所以要将表单对象放在 Session
中,是为了使其能够在表单显示和之后的表单提交这样过程中不丢失。@SessionAttributes 的这种用法是源于 Spring MVC
2.0 AbstractFormController 的 SessionForm 模式。
实际上,使用 @SessionAttributes
是很成问题的,有时是不可接受的。考虑以下场景:在 PetClinic 应用中,新建两个 Owner,然后为这两个 Owner 都添加新的
Pet。注意,只要显示出来 Add Pet 的页面即可。这时,这两个页面的 URL 应该是 addPet.do?ownerId=num1 和
addPet.do?ownerId=num2 。这时将先打开的表单
提交
,假设是 num1 的那个。你会发现你
实际上是为 num2 Owner
添加了一个 Pet。
这个问题的原因其实是很简单的,我就不解释了。从上面这个事实来看,@SessionAttributes
的缺点还是比较明显。是否采用这种方式还要看这个问题对你的应用的影响是否是致命的了。Spring MVC 有必要改进一下,像 Seam
那样可以很方便的使用 Conversation 是解决问题的一个好办法。(当然也可以使用 hidden 域来保存 id)。
Spring MVC 之所以要使用这种有较明显缺陷的方式的原因是要使用 Spring MVC
的表单数据绑定功能。由于目前还没有找到更好的方式,所以只能使用 @SessionAttribute 了。这一块还是 Spring MVC
的一个短板,需要在新版本中改进。
除此以外,AddPetForm 中还有两个特殊的方法,一个是注释了 @ModelAttribute 的方法;另一个是注释了 @InitBinder 的方法。下面分别介绍一下:
- @ModelAttribute 可以用在方法上,也可以用在形参上。如果放在方法上,那它会在进入请求处理方法是准备一些数据,作用和
SimpleFormController 的 referenceData() 一样。@ModelAttribute 的这种用法可能会让人联想到
Seam 中的 @Factory。但被 @ModelAttribute 注释的方法只会在同一个 Controller 中被注释了
@RequestMapping 的方法调用之前被调用,而 @Factory 方法则是全局的。
你可以在 setupForm 方法中向 request 或 session 中设置一些需要显示在页面上的数据,但是如果只放在 request
里的话,在表单验证发生时,数据便会丢失;放在 session 缺点自不必多说。在 Spring Web Flow 新加入的 flow 和 conversation 等新的 scope
无法很容易地在 Spring MVC 中使用的情况下,使用 @ModelAttribute 无疑是更好的选择。并且使用 @ModelAttribute 可以在多个
@RequestMapping 方法之间实现代码的重用。
- @InitBinder 适用于注册只属于本 Controller 的属性编辑器。但在 AddPetForm 中,@InitBinder
方法只是告诉 Spring MVC,路径为(<form: input path="id" />) id
的值不要使用属性编辑器。不过页面里也压根没有 路径为 id 的值。所以,我觉得这个又是一个多余的代码。(我试过将 @InitBinder
方法注释掉,对程序没有影响)
Controller 层中两个特殊的类:ClinicBindingInitializer 和 PetTypeEditor
- ClinicBindingInitializer 的作用是注册全句的属性编辑器
- PetTypeEditor 是用于处理 PetType 类型数据绑定的属性编辑器。对于像 PetType 这样的实体之间的关联属性,恰当地使用属性编辑器可以简化程序的开发。
(不知 Grails 是否实现了一个动态的属性编辑器,用于关联属性的数据绑定)
配置
1. applicationContext.xml
applicationContext 中大部分都是常见的 Spring 配置。特殊一点的配置除了 <gorm:sessionFactory ... /> 以外,还有 Hibernate StatisticsService JMX 的配置。
2. dispatcher-servlet.xml
Spring MVC 配置文件(也是一个 Spring 的配置文件)的默认名是 dispatcher-servlet.xml。
从上至下,第一个配置表明哪个 Package 下的 Class 使用了 Spring 的 @Controller 注释。这样 Spring 容器在启动的时候会自动扫描其下的 Class,将加注了 @Controller 注释的类加入到 Spring 的容器中。
第二个配置 DefaultAnnotationHandlerMapping
是 HandlerMapping
接口的一个最常用的实现类。用于映射 Handler 和请求路径之间的关系。通过这样的配置,Controller 中的 @RequestMapping 中的路径值就可以真正地和 Http 请求对应起来。HandlerMapping 的另外一个常用的实现类是 ControllerClassNameHandlerMapping
。
第三个配置 AnnotationMethodHandlerAdapter
的作用是使处理请求的 Handler 能够真正的具有处理请求的能力而提供一些服务,包括为请求参数绑定应用相应的属性编辑器(通过注册 webBindingInitializer 实现)。
==============================结束的分割线==============================
写到这里,PetClinic-MVC 中值得分析学习的代码都提到了。PetClinic-MVC 是一个很小的应用,但是其中演示了 GORM 在普通 Spring 中的应用和 Spring MVC 2.5 的使用。细看的话还是能学到不少东西的。我所写的只是我的理解,难免会有一些不足和错误,欢迎纠正。
分享到:
相关推荐
Grails1.1中文文档-----2009.3.25
Grails1.1中文文档
学习Grails 1.1,你需要掌握Groovy语言基础,理解MVC架构,熟悉GORM的使用方法,以及GSP模板的编写。同时,通过实践创建简单的Grails应用,了解控制器、服务、领域模型的创建和交互,以及插件的使用。此外,深入研究...
这份“Grails1.1中文文档”将详细解释以上知识点,并通过实例引导初学者逐步熟悉Grails的开发流程。无论是对Groovy语言的学习,还是对MVC架构的理解,或是如何利用GORM操作数据库,这份文档都将提供详尽的解释和示例...
《Grails 1.1 中文文档》是一个针对Grails框架1.1版本的详尽指南,旨在帮助中文用户理解并掌握这一强大的Groovy构建的Web应用开发平台。Grails是一个基于Groovy语言的开源框架,它采用了模型-视图-控制器(MVC)架构...
Grails1.1最新 中文 文档 当今的Java Web开发技术显得过于复杂,相对于它本身的需要来说。现在主流的Java Web框架也是异常复杂,而且没有很好的遵循 Don't Repeat Yourself (DRY) 法则。 因此我们要以一种新的思维...
### Grails 1.1 Web Application Development #### 核心知识点概述 《Grails 1.1 Web Application Development》是一本专注于使用Grails框架进行高效Web应用开发的技术书籍。本书由作者Jon Dickinson撰写,旨在...
5. `grails-app`:这是一个目录,通常包含了Grails应用的源代码、视图、控制器和服务等组件。 6. `lib`:库文件夹,通常存放插件或应用所需的外部库和依赖。 7. `web-app`:这是Web应用的标准目录结构,包含了静态...
Grails 最新的 v1.1版的中文文档,chm格式,Grails是一套快速开发Web应用的开源框架,基于Groovy编程语言,并构建于Spring、Hibernate和其它标准Java框架之上,能为大家带来超高效率的一站式框架。
标题"grails-bin-1.1"指的是Grails框架的1.1版本的二进制发行版。这个版本的Grails是一个免安装版,意味着用户可以直接将它解压到任何位置,而不需要通过传统的安装程序进行安装。 描述中的"本文件只需要放到相应...
在"prestige.zip"中包含的"Prestige-master"可能是项目源码的主分支,它可能包含了实现Android MVC模式的具体代码和结构。开发者可以从中学习到如何在Android应用中有效地运用MVC模式,例如如何创建模型类来处理数据...
Apress.Beginning.Groovy.and.Grails.From.Novice.to.Professional.Jun.2008 grails_programming Grails1.1中文文档-----2009.3.25 Grails入门指南(第二版) Groovy经典入门 Programming Groovy 2 合集,超实惠哦
本文将深入探讨Grails 1.1版本中的动态编码方案,这是该框架提供的一种强大且灵活的特性,使得开发者能够在运行时动态地创建和修改代码。 动态编码方法在Grails中主要体现在两个方面:GSP(Groovy Server Pages)和...
- **RaceTrack应用**:本书通过一个名为RaceTrack的应用实例介绍了Grails的基本用法。包括应用的创建、领域模型定义、控制器编写等。 - **Hello, Grails!**:通过创建一个简单的“Hello, Grails!”应用,展示了...
2. MVC架构:Grails遵循Model-View-Controller(MVC)设计模式,通过GORM(Grails Object Relational Mapping)进行数据访问,使用GSP(Groovy Server Pages)作为视图模板,Controller负责业务逻辑处理。...