JBoss Seam的一个特性就是具有RAD(快速应用开发)能力。虽然动态语言与RAD并非同一个意思,但它却是该领域内的一个十分有趣的工具。 直到最近,选择一种动态语言就必须选择完全不同的开发平台(一个带有一系列API和运行环境的开发平台,如果你不想再使用旧的Java API, 这可能是一种幸运,因为你可能不得不被迫使用平台提供的私有API)。 Groovy 打破了这个约束,它是构建在Java虚拟机之上的动态语言。
现在,JBoss Seam通过静态语言和动态语言的无缝集成把动态语言世界和Java EE世界结合起来。 JBoss Seam让开发人员在任务中使用最佳的工具,而不需要关心上下文切换。 编写一个动态Seam组件和编写普通的Seam组件没什么两样,你使用相同的注释、相同的API,所有的一切都是相同的。
Groovy是一个基于Java虚拟机的敏捷动态语言,它融合了从Python,Ruby和Smalltalk等语言中的诸多特性。Groovy的强大体现在两个方面:
Groovy支持Java语法:Java代码就是Groovy代码,使学习曲线非常平滑,即学习的难度变得非常低。
Groovy对象就是Java对象,Groovy类就是Java类:Groovy无缝集成所有已经存在的Java对象和类库。
TODO: 再写一个Groovy语法的快速入门
这个没有什么可多说的,Groovy对象就是Java对象,你可以使用Groovy编写任何Seam组件或者Java类并部署它们。 你也可以在一个应用中混合使用Groovy和Java类。
你可能已经注意到,Seam大量的使用注解(annotation)。要想Groovy支持注解必须确保其版本在1.1 Beta1以上。 下面是在Seam应用中使用Groovy代码的例子。
@Entity @Name("hotel") class Hotel implements Serializable { @Id @GeneratedValue Long id @Length(max=50) @NotNull String name @Length(max=100) @NotNull String address @Length(max=40) @NotNull String city @Length(min=2, max=10) @NotNull String state @Length(min=4, max=6) @NotNull String zip @Length(min=2, max=40) @NotNull String country @Column(precision=6, scale=2) BigDecimal price @Override String toString() { return "Hotel(${name},${address},${city},${zip})" } }
Groovy本身就支持(getter/setter)方法特性,所以你不用显示的编写冗长的getter和setter方法:在前面的例子中, Hotel类可以通过 <code>hotel.getCity()</code> 这样的语法被Java访问到,getter和setter方法是在Groovy编译时生成的。 这样的语法让实体代码变得非常简洁。
Groovy1.1 Beta1暂时还不支持泛型(Generics)。一个负面影响是实体关系没有内置的类型信息。 这就必须适当的使用 @*ToMany 注解来代替简单的范型定义,就像 <code>Collection<Entity></code>。 出于同样的原因,你也不能从非常有用的 Chapter 11, Seam应用程序框架 中受益。好消息是Groovy1.1正式版将支持范型(Groovy1.1 Beta2正在编写中)。
使用Groovy编写Seam组件与使用Java没有什么区别:使用注解将类标记为Seam组件。
@Scope(ScopeType.SESSION) @Name("bookingList") class BookingListAction implements Serializable { @In EntityManager em @In User user @DataModel List<Booking> bookings @DataModelSelection Booking booking @Logger Log log @Factory public void getBookings() { bookings = em.createQuery(''' select b from Booking b where b.user.username = :username order by b.checkinDate''') .setParameter("username", user.username) .getResultList() } public void cancel() { log.info("Cancel booking: #{bookingList.booking.id} for #{user.username}") Booking cancelled = em.find(Booking.class, booking.id) if (cancelled != null) em.remove( cancelled ) getBookings() FacesMessages.instance().add("Booking cancelled for confirmation number #{bookingList.booking.id}", new Object[0]) } }
部署Groovy类与部署Java类非常相像。(令人惊讶的是,不需要编写或者遵循某个3个字母的规范以支持多国语言组件框架)。
JBoss Seam拥有超越标准部署的能力,就是在开发时重新部署JavaBean Seam组件类而不必重启应用程序,这在开发/测试周期中节省了很多时间。 在 .groovy 文件被部署时,Seam对GroovyBean Seam 组件也提供了同样的热部署支持。
Groovy类就 是 Java类,和Java类有着同样的字节码。 部署一个Groovy实体、Groovy Session Bean或者Groovy Seam组件,编译步骤是不可缺少的。一个通用的方法是使用 groovyc Ant任务。 一旦编译,Groovy类和Java类不再有区别,应用服务器将它与Java类同样对待。这让Groovy与Java类无缝集成起来。
JBoss Seam本身支持 .groovy 文件(不用编译)的增量热部署(必须是开发模式)。这让编辑/测试周期非常短。 为了设置.groovy部署,请按照 Section 2.7, “Seam与增量热部署” 进行配置,然后部署你的Groovy代码(.groovy文件)到 WEB-INF/dev 目录下。 不需要重启应用程序,GroovyBean组件将被增量启用(当然运行应用程序的服务器也不必重启)。
本地的.groovy文件的部署和其他的Seam热部署有同样的局限:
组件必须是JavaBean或GroovyBean。不能是EJB3 Bean
实体不能热部署
被热部署的组件对部署在 WEB-INF/dev 以外的任何类都是不可见的
必须用Seam Debug模式