当前页面: 开发资料首页 → JSP 专题 → 用EJB 3.0开发企业级Bean组件初体验
摘要: EJB 3.0公共草案展示了一种创建企业级组件的相当简化的模型。这种新型范例的目的在于简化开发,只是引入了较少的超出前面讨论范围的新功能。
阅读提要 EJB 3.0规范的最终稿已经提交到JCP,如果不出意外EJB3.0将在2006年正式发布。本文作为探讨EJB 3.0公共草案三系列中的第一篇,将解释EJB 3.0和企业Bean组件的基本概念;另外,你还学习到怎样使用JBoss和Maven来开发基于EJB 3.0的企业级bean组件。
尽管EJB 3.0规范还没有正式发行,但是它已经在Java开发社群中引起广泛兴趣——无论是对其拥护者还是其竞争对手。所有人都承认迫切需要找到更有生产效率的软件开发方法;如今,他们的争论集中于在EJB 3.0。
尽管存在争论,但是EJB 3.0规范草稿的发行和在JBoss的初步支持意味着现在正是探索这种深具影响力的技术的时候。事实上,有关在生产系统中应用EJB 3.0的报告早已浮出水面。
本文是探讨EJB 3.0公共草案三系列中的第一篇。本文将向你介绍该草案中的一些专门概念并将同你一起用JBoss来实现这些具体的技术。另外,本文还涉及一些EJB 3.0和企业Bean组件的基本概念。
为此,你需要作如下准备:
·Java 2 SDK 1.5
·Maven 2.0
·JBoss应用程序服务器4.0.3
·JBoss AOP 1.3.4
一、EJB 3.0简介
企业级应用程序是这样一类应用程序-它们实现商业功能并包含大量的数据。这些应用程序一般不在孤立的环境中执行任务,取而代之的是,它们当中的每一段程序往往成为庞大的IT系统的一个小小的组成部分并且必须与人和另外的系统进行交互。简而言之,开发企业级应用程序是一件相当难的事情。在几乎所有的企业级应用程序中,为了在企业中成功地执行它们的功能,必须强调如性能,可伸缩性,并发性和安全性等一系列的问题。
作为对这些挑战的回应,为了更容易地开发分布式的面向对象的商业系统,在1998年3月,产生了EJB规格说明书。该规格说明书和实现它的应用程序服务器已经在很大程度上实现了这个目标。但是,在过去的几年中,EJB的不足以及随着更简化实现方式的出现,逐渐提出了很多问题-是否EJB能够为企业级应用程序的生产力开发提供最好的解决方案?
EJB经常被提及的不足包括如下:
·如果想利用提供的企业服务的组件就需要使用大量的EJB API。
·它是一种要么全有要么全无的提议。就算你想要使用一种EJB服务,你也必须使用所有伴随EJB的其它内容。
·EJB组件要求有相应的容器并且被证明是难于测试的。
·要求每个EJB实现若干内容(接口,类和描述符)。
·传统型EJB架构很少涉及面向对象并且引入了只有状态而没有行为的"假对象"。
关于EJB的一些流行选择有:
·面向方面编程(AOP)
·轻量级容器,如Spring,Pico Container和Hivemind
·对象关系映射(ORM)工具,如Hibernate,JDO和iBatis
·.NET服务组件
EJB 3.0规格说明书公共草案主要目的是使开发更为容易并使得平衡企业服务更为简单。这些改进在某种程度上得益于以上所列举内容的成功应用。上面工具的某些方面在EJB 3.0还留有它们的踪迹:
·一个POJO(普通Java对象)编程模型
·一个轻量级ORM持续性框架
·依赖性注入
·元数据注解
在EJB 3.0规格说明书中,其它一些重要组成包括:
·通过异常进行配置
·消除组件接口
·消除home接口
·检查异常使用的减少
本文假定你已经熟悉EJB 2.x并且会关注在3.0 规格说明书公共草案中所引入的新的变化。本文余下的部分将通过使用Maven和JBoss应用程序服务器来分析构建EJB 3.0应用程序的过程中的这些改进。
二、应用程序实例-一个在线音乐店
本文中所讨论的技术全部展现在所附的示例应用程序中-一家在线音乐店。这家店允许用户浏览和购买音乐,视频和音频书籍。图1显示出这个界面的一个屏幕快照;你可以下载本文最后有关的源代码。
本文相随的实例应用程序的设计和测试工具有:JBoss应用程序服务器4.0.3和JBoss AOP 1.3.4,并且使用Maven 2.0来构建这个应用程序。所附源代码为设置Jboss、使用Maven构建源文件和发布该应用程序均提供了指导。
三、无状态会话Beans
与EJB 3.0规格说明书中的其它一些企业bean组件一样,无状态会话beans是一些实现了一个商业接口的POJO。以我们的音乐店为例:该音乐店实现在用户浏览时对各种类型的音频和视频的查询功能。对这个音乐店来说,实现这一功能的一个简单的接口实现可以如下编写:
public interface IMusicStore{
public List
public Genre findGenreById(int id);
public Artist findArtistById(int id);
public Product findProductById(int id);
public void checkOut(IShoppingCart cart);
}
public class MusicStore implements IMusicStore{
public List
{ return MusicStoreDAO.getInstance().listGenres(); }
public Genre findGenreById(int id)
{ return MusicStoreDAO.getInstance().findGenreById(id); }
public Artist findArtistById(int id)
{ return MusicStoreDAO.getInstance().findArtistById(id); }
public Product findProductById(int id)
{ return MusicStoreDAO.getInstance().findProductById(id); }
public void checkOut(IShoppingCart cart)
{ ... }
}
@Stateless
public class MusicStore implements IMusicStore{ ...}
import com.devx.musicstore.IMusicStore;
public abstract class AbstractStoreAction extends Action{
@EJB
protected IMusicStore store;
...
}
public abstract class AbstractStoreAction extends Action{
@EJB(
name = "ejb/musicStore",
beanName = "store1",
BusinessInterface = com.devx.musicstore.IMusicStore.class
)
protected IMusicStore store;
...
}
四、远程接口
为了远程存取一个会话bean,你仅需要用如下的@Remote注解来对它进行注解即可:
@Stateless
@Remote
public class MusicStore implements IMusicStore
{ ...}
@Stateless
@Local( { IMusicStore.class } )
@Remote( { IMusicStoreRemote.class } )
public class MusicStore implements IMusicStore, IMusicStoreRemote
{ ...}
@Remote
public interface IMusicStoreRemote
{ ...}
@Stateful
public class ShoppingCart implements IShoppingCart
{ ...}
@MessageDriven
public class OrderProcessor implements MessageListener{
public void onMessage(Message message){
ObjectMessage objectMessage = (ObjectMessage) message;
try{
Order order = (Order) objectMessage.getObject();
System.out.println("Products Ordered:");
for (Product p : order.getProducts())
{ System.out.println(p.getTitle()); }
}
catch (JMSException e) { e.printStackTrace(); }
}
}
@MessageDriven(activateConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/orders")
})
public class OrderProcessor implements MessageListener
{ ...}