`
fangzhouxing
  • 浏览: 213298 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JBoss Seam (POJO without EJB) 后台 + ExtJS 前台完整例子(十)

阅读更多

JBoss Seam (POJO without EJB) 后台 + ExtJS 前台完整例子(十)


1.引言

分层是分解复杂软件系统最常用的技术。当用分层的观点来设计系统时,各个子系统的形式类似“多层蛋糕”。每一层都依托在其下层之上,上层使用了下层定义的各种服务,而下层对上层一无所知。

分层设计的难点是决定建立哪些层次,以及每一层的职责是什么。本文介绍项目中采用的分层设计思路,最后说明了为何要强调使用POJO without EJB的设计。

需要特别说明的是,本文的很多想法和术语,均来自Martin Fowler大师的《企业应用架构模式》(2004年7月版)一书。如果你还没有阅读过这本书,可能会对本文所用的很多术语感到陌生。

2.分层概述

本项目采用的分层技术将后台系统划分为下列三层:
(1)远程外观层(Remote Facade Layer)
(2)服务层(Service Layer)
(3)领域模型层(Domain Model Layer)

服务层和领域模型层实际上都属于“领域层”。org.jboss.seam.example.divo.domain 包中的类构成了最低级的领域模型层。这些类是Hibernate的实体类,但它们可以在各层之间传递数据,从而消除了传统的DTO(数据传输对象)。实体类中只有数据,不包含业务逻辑。

服务层是从领域层中独立出来的,它用Martin Fowler所谓的“操作脚本方法”实现。服务层可以直接通过JDBC操作数据库,也可以通过Hibernate和实体类操作数据库。服务层的所有类在org.jboss.seam.example.divo.service 包中,类名表示为 XXXService.java。

远程外观层是在服务层之上添加的。通过远程外观层,为细粒度对象提供粗粒度的外观来改进网络上的效率。这一点在事务处理设计上体现得特别明显。我们总是假设远程外观层的一个方法是一个完整的事务,而服务层中的一个方法是某个事务的一部分。

3.用Seam Remoting实现远程外观

Seam Remoting是前后台通讯的主要机制之一。一般情况下,系统划分为若干“子系统”,一个子系统设计一个远程外观类,被客户端通过 Seam Remoting 调用,类名表示为 XXXFacade.java。

在本项目中,org.jboss.seam.example.divo.SampleFacade.java 就是一个远程外观类。SampleFacade 中一般不实现特定的业务逻辑,它把具体的操作交给服务层进行处理。

注意 SampleFacade 的@Transactional元注解:
java 代码
  1. @WebRemote
  2. @Transactional
  3. public void deleteBooking(int id) {
  4. bookingService.delete(id);
  5. }

按照Seam框架的规定,没有@Transactional元注解的方法,表示支持事务处理,即相当于使用了@Transactional(SUPPORTS)元注解,只可以参与某个事务。而使用了不带参数的@Transactional,则表示
@Transactional(REQUIRED),它会在方法执行完毕后自动提交事务。

4.用Servlet作为远程外观

JSON是前后台通讯的另外一种机制。需要通过Servlet才能实现JSON数据的传递。在本项目中,Servlet处于和远程外观类相同的地位,可以把它看成是另外的一种远程外观。

建议一个子系统只设计一个Servlet,通过action传递参数区分不同的客户端请求。SampleServlet 就是这样做的:

java 代码
  1. @Override
  2. public void doGet(HttpServletRequest request, HttpServletResponse response)
  3. throws ServletException, IOException {
  4. createHotelService();
  5. createBookingService();
  6. String action = request.getParameter("action");
  7. if (action.equals("hotelList"))
  8. runHotelList(request, response);
  9. if (action.equals("bookingList"))
  10. runBookingList(request, response);
  11. }

与远程外观类相同,Servlet中不要实现特定的业务逻辑,应把具体的操作交给服务层进行处理。

5.服务层

一般情况下,针对某个实体实现一个服务类,但也可以针对某种特定的用途设计服务类。

服务类设计应该遵循下列原则:
(1)使用@AutoCreate元注解,使服务类被注入时自动创建对象实例。
(2)通过自动注入的 org.hibernate.Session 对象访问和操作 Hibernate 实体类,实现业务逻辑。
(3)如果要直接用JDBC访问数据库,可以从org.hibernate.Session 对象中直接得到数据库连接,例如:

java 代码
  1. /**
  2. * 执行SQL语句(不返回结果)
  3. */
  4. protected void exec(String sql) {
  5. java.sql.PreparedStatement prepStatement = null;
  6. Connection conn = null;
  7. try {
  8. conn = hs.connection();
  9. prepStatement = conn.prepareStatement(sql);
  10. prepStatement.executeUpdate();
  11. } catch (SQLException e) {
  12. e.printStackTrace();
  13. } finally {
  14. if (conn != null)
  15. try {
  16. conn.close();
  17. } catch (SQLException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }

6.领域模型层


为了简化设计,直接使用Hibernate作为构建和持久化领域模型的基础。Hibernate数据源在
hibernate.cfg.xml 中进行配置。

基于Hibernate的实体类的设计应该遵循下列原则:
(1)尽量不用org.hibernate.validator包中的验证规则,相关业务逻辑改在服务层实现。
(2)避免使用序列自动生成Id, 采用下面的表生成Id方法:

java 代码
  1. @Id
  2. @GeneratedValue(strategy = GenerationType.TABLE, generator="nextid")
  3. @TableGenerator(name="nextid", table="T_NextId", allocationSize=1)
  4. public int getId()
  5. {
  6. return id;
  7. }
  8. public void setId(int id)
  9. {
  10. this.id = id;
  11. }

7. POJO without EJB

尽管EJB3做出了重大的改进,但是,对于大量的应用程序来说,仍然存在更易使用且更好的替代方案。《POJOs In Action》一书的作者认为在下面两种情况下,才需要使用EJB:
(1)使用由远程客户端发起的分布式事务的应用程序。
(2)极度消息导向,需要大量消息驱动bean的应用程序。

对于访问量大、并发用户多的大型网站,有人认为应该使用EJB ,才能保证系统的可扩展行和性能。实际上,采用POJO without EJB设计也是完全可行的,网站的性能瓶颈往往发生在数据库访问速度上。

在Seam框架下,使用POJO without EJB设计后,对集群(clustering)和故障恢复(failover)的实现有些什么
影响,有关文献似乎没有明确的说明。

8.结语

分层技术通过明确各层的职责,使系统的整体设计简洁而完整。Seam框架的组件模型极大地简化了分层设计的实现。有人可能对本项目采用的POJO without EJB设计不能认同,但其提高开发效率的效果是非常明显的。

附:下面是本系列所有文章的完整列表:
(1)下载示例项目并安装运行
(2)建立Eclipse开发环境
(3)熟悉项目中与JSF相关内容
(4)重新认识JS
(5)ExtJS之表单(Form)
(6)ExtJS之布局(Layout)
(7)ExtJS之网格(Grid)
(8)Java后台和前台的通讯机制
(9)Seam框架简化Java开发
(10)分层架构设计
(11)安全性
(12)单元测试
分享到:
评论
1 楼 springhill 2007-12-10  
这个系列的文章真棒

相关推荐

Global site tag (gtag.js) - Google Analytics