找回密码
 注册
搜索
热搜: 回贴

EJB 3.0+Beehive开发客户反馈系统

2009-12-22 00:38| 发布者: admin| 查看: 97| 评论: 0|原作者: 墨元

  设计目标

  客户反馈系统作为公司与客户交流的平台,几乎为所有的企业所运用,最近,公司让我负责客户反馈系统的开发。由于,公司与国外客户的业务需要,该系统必须实现中,英,日三国语言的切换(国际化要求)。在接到任务之后,我便决定尝试使用目前开源社区比较流行的Apache Beehive(蜂巢)和下一代EJB,EJB3.0等技术来实现这个系统。


  开发环境

  选择平台,开发工具

  为了支持EJB3.0和Beehive,我们选择JBoss4.0.3应用服务器作为运行平台,它也是目前唯一提供EJB3.0容器的应用服务器。

  下载和安装JBoss4.0.3服务器及EJB3.0容器http://www.jboss.com/downloads/index

  数据库选用 MySql5.0,由于我们没有针对特定数据库编码,因此数据库的移植也是非常方便的。
  下载MySql5.0 http://dev.mysql.com/downloads/mysql/5.0.html
  由于要开发EJB3.0和Beehive应用,选择Ecllipse这个IDE,

  下载Ecllipse SDK 3.1 http://eclipse.org/downloads/

  为了支持EJB3.0的开发,下载Jboss Ecllipse IDE这个Ecllipse插件
http://www.jboss.com/products/jbosside/downloads
  Pollinate是另一个Ecllipse插件,它也是目前唯一支持Beehive项目开发的IDE,虽然它远不及WebLogic 的 Workshop 如此强大,但在拥有一定BEA Workshop 开发经验的前提下,使用pollinate并不会有太大的问题。

  下载并安装Pollinate插件 http://www.eclipse.org/pollinate/
  Beehive简介

  在系统设计之前,选择一个优秀的系统框架是非常重要的。Beehive是Apahce的开放源代码项目。自2004年5月份,BEA系统公司宣布将WebLogic Platform中一系列居于核心地位的运行时框架(Runtime Framework)开放源代码并贡献给Apache项目后,这个Beehive的框架就一直成为开源社区关注的焦点之一。
  Beehive的目标是使J2EE开发更加简单,它是一个可扩展的Java应用程序框架,该框架具有针对Web服务,Web应用程序和资源访问的集成元数据驱动的编程模型。该框架利用了JDK1.5的最新创新,特别是JSR175元数据注解,可以减少开发人员的编码,从而提高开发效率。目前,Beehive项目包括Java控件,NetUI,Java Web服务元数据,能够帮助Java开发人员开发出基于组件和标准的JAVA应用。
  EJB3.0简介

  在客户反馈系统中,尝试使用最新的EJB3.0来实现持久层的开发。众所周知,由于EJB的复杂性使其在J2EE架构中的表现一直不是很好。EJB大概是J2EE架构中唯一一个没有兑现其能够简单开发并提高生产力的组件。而EJB3.0规范在这方面作出努力以减轻其开发的复杂性。EJB3.0取消或最小化了很多(以前这些是必须实现)回调方法的实现,并且降低了实体Bean及O/R映射模型的复杂性,从而大大减轻了开发人员进行底层开发的工作量。
  EJB3.0中两个重要的改进分别是:使用了Java5中的元数据注解功能和基于Hibernate的O/R映射模型, 在EJB3.0中,任何类型的企业级Bean只是一个加了适当注释的简单Java对象(POJO)。注释可以用于定义bean的业务接口、O/R映射信息、资源引用信息,效果与在EJB2.1中定义部署描述符和接口是一样的。在EJB3.0中部署描述符不再是必须的了;home接口也没有了,你也不必实现业务接口(容器可以为你完成这些事情)。
  EJB3.0的配置

  JBoss EJB3.0建立在Hibernate 3.0之上。配置数据源,实体bean需要创建hibernate.   Properties配置文件。在EJB3.0部署包下有一个默认的hibernate配置文件ejb3.deployer/META-INF/hibernate.properties。修改这个文件,使实体Bean使用MySql数据源,修改后的配置文件如下:

hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup
hibernate.connection.release_mode=after_statement
hibernate.transaction.flush_before_completion=false
hibernate.transaction.auto_close_session=false
hibernate.query.factory_class=org.hibernate.hql.ast.ASTQueryTranslatorFactory
  在SessionFactory创建后,自动输出schema创建语句到数据库,使用update可以创建和更新原来的schema,而不影响原来数据库中的数据

hibernate.hbm2ddl.auto=update
#hibernate.hbm2ddl.auto=create
hibernate.show_sql =true
hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider
# Clustered cache with TreeCache
#hibernate.cache.provider_class=org.jboss.ejb3.entity.TreeCacheProviderHook
#hibernate.treecache.mbean.object_name=jboss.cache:service=EJB3EntityTreeCache
  修改蓝色字体部分使其默认数据源改为MySqlDS(JBOSS的数据源配置参考JBOSS相关文档)。

hibernate.connection.datasource=java:/MySqlDS
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.jndi.java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
hibernate.jndi.java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
  持久层设计

  创建Ejb3.0项目

  首先使用Jboss IDE,创建一个EJB3.0项目,选择new->project->EJB3.0 project,

  选择Next按钮,在project name中输入项目名称:feedback,点击next,

  接着选择JBoss4.0.3 Server作为项目默认的服务器。单击完成按钮,这样就生成了一个EJB3.0的项目,其根目录下的jndi.property文件指明了JBoss服务器名称服务的一些配置。
  数据持久层

  使用EJB3.0的实体Bean来实现系统的数据持久层.EJB3.0的实体bean也是一个加了注释的简单Java对象(POJO)。一旦它被EntityManager访问它就成为了一个持久化对象,并且成为了持久化上下文(context)的一部分。一个持久化上下文与一个事务上下文是松耦合的;严格的讲,它隐含的与一个事务会话共存。 在EJB3.0中开发实体Bean非常简单,可以像开发一般的java bean一样编程,只需做少量的注释来定义实体关系,O/R映射等,而在EJB2.1中这些都要通过开发人员自己的设计模式或者其它技术来完成的(比如,自增长主键策略)。如下定义了一个Item实体bean表示客户发起的一个主题:
//声明该类为一个实体Bean对象,表示客户发起的一个主题

public class Item implements Serializable{
private static final long serialVersionUID = -3318132295818643572L;
private int itemId;
private Collection feedBacks;
private User user;
……
//此处定义了实体Bean的一对一关系
(optional = false)
(name = "userId", unique = false, nullable = false)
public User getUser() {
return user;
}
//声明实体Bean的主键及增长策略
(generate=GeneratorType.AUTO)
(name="itemId")
public int getItemId() {
return itemId;
}
//声明主题实体与反馈实体之间的的一对多关系,并且制定级联及获取方式等
(cascade=CascadeType.ALL,fetch=FetchType.LAZY,mappedBy="item")
(name="itemId")
public Collection getFeedBacks() {
return feedBacks;
}
public void setFeedBacks(Collection feedBacks) {
this.feedBacks = feedBacks;
}
……
}

  上例中,蓝色部分便是JDK1.5的元数据注解功能,如 便指名该类是一个EJB3.0 实体Bean,这样在编译后便产生了EJB3.0 的实体Bean,在部署时,Jboss的EJB3.0容器能够识别EJB3.0的实体Bean,并将其映射到对应的数据库表中。具体请参考EJB3.0相关技术文档。
  业务逻辑层

  在客户反馈系统中使用无状态会话Bean来实现系统的业务逻辑层,在EJB3.0规范中,写一个无状态回话bean(SLSB)只需要一个简单的Java文件并在类层加上注释就可以了。这个bean可以扩展javax.ejb.SessionBean接口,但这些不是必须的。一个SLSB不再需要home接口,没有哪类EJB再需要它了。Bean类可以实现业务接口也可以不实现它。如果没有实现任何业务接口,业务接口会由任意public的方法产生。如果只有几个业务方法会被暴露在业务接口中,这些方法可以使用注释。缺省情况下所有产生的接口都是local(本地)接口,你也可以使用注释来声明这个接口为remote(远程)接口。
  使用JBoss IDE创建会话Bean十分方便,选择new->others->EJB3.0->Session Bean,打开会话Bean创建向导,如图所示

  Session Bean Type中选择Stateless,表明要创建一个无状态会bean。在Bean Name中输入要创建的Session Bean的名称,这里我们创建一个处理客户反馈的无状态会话Bean:FeedBacks。点击finish按钮后,分别产生了会话Bean的接口文件和实现文件:FeedBacks,无状态会话Bean的业务接口:

public interface FeedBacks{
public FeedBack addFeedBack(int itemId,String title,String content,int userId,Collection feedBackFiles);
public void deleteFeedBack(int feedBackId);
……
}

  在会话Bean的业务接口中,添加会话Bean的接口。其中声明该Bean实现会话Bean的Remote接口

  无状态会话Bean的实现:

public class FeedBacksBean implements FeedBacks {
public FeedBack addFeedBack(int itemId,String title,String content,int userId,Collection feedBackFiles)
{
//此处添加实现代码
……
}
……
}
  在实现中完成。
  在实现中完成所有的业务逻辑编码。其中声明该Bean是一个无状态会话Bean。
  WEB层设计   创建Beehive项目   首先创建一个Beehive项目,选择new->project->Beehive project,打开Beehive Project创建向导,如图所示:   在name中输入,应用的名称:feedbackApp。下一步中可以选择以定义的应用模板。完成上述步骤后,便生成了一个beehive project,新生成的项目已经添加了所有需要的Beehive资源。接着就可以开发页面流和Java控件了。   利用Java Control在Beehive中使用 Ejb3.0  Beehive提供了EJB Control用于获取EJB实例,但不支持EJB3.0,因此在客户反馈系统中考虑使用Java Control技术编写一个由EJB3.0实例的JNDI名称来获取EJB实例的控件。   Java控件(Control)架构是一个基于JavaBeans的轻量级组件架构,它公开了用于访问各种J2EE资源类型简单而一致的客户机模型。该框架提供了大量的函数,其中包括:基于JSR-175元数据和外部配置数据的配置,自动资源管理,上下文服务和用于创建新控件类型的可扩展设计模型。   开发Java控件,首先将EJB 3.0项目引入当前beehive项目中,可以在project->property->build path中设置。接着编写一个名为EjbFinder的Java Control来实现Ejb3.0实列的获取。   Java Control的开发分为两个步骤,首先要定义Java Control的接口如下所示: // 指明该接口是控件EjbFinder的接口部分

public interface EjbFinder {
public Object getEjb(String ejbName);
}

  然后定义Java Control的实现部分,
// 指明该类是控件EjbFinder的实现部分

public class EjbFinderImpl implements EjbFinder, java.io.Serializable {
//实现业务接口中的方法
public Object getEjb(String ejbName) {
try{
Context context = new InitialContext();
//根据JNDI名称获取ejb3.0实例,并返回该实例
return(context.lookup(ejbName));
}catch(NamingException e){
e.printStackTrace();
return null;
}
}
}
  Java 控件是一种可以在平台应用程序中的任何位置使用的可重用组件。上面的java control 用于由ejb实例的JNDI名称,在整个Context中查找,并返回该ejb实例。接着我们便可以在Beehive Web 应用中的PageFlow(页面流)中使用这个Java控件来获取ejb3.0实例了:  在需要使用ejb3.0实例的PageFlow页面流控制文件中添加如下代码,声明使用该控件 .apache.beehive.controls.api.bean.Control()protected EjbFinder _ejbFinderControl;  接着我们便可以使用这个EjbFinder控件来获取所需的ejb3.0实例了 feedbacksBean= (FeedBacks) _ejbFinderControl.getEjb(FeedBacks.class.getName());  由于Pollinate中尚不提供控件的视图,为了说明Java Control与Pageflow(页面流)之间的关系,可以参照上面这张Bea Workshop中java control的参考视图,图中的主体是一个pageflow(页面流),而右侧users就是在该页面流中使用的一个名为users的java控件。   开发NetUI页面流   NetUI Page Flow(页面流)是一个基于Apache Sruts的Web应用程序框架,具有易于使用,基于JSR-175元数据的单文件编程模型。该页面流构建在模型/视图/控制器元素的核心Struts分离的基础之上,比如自动状态管理和与控件,XMLBeans和JavaServerFaces的一流集成。   页面流使用一种专门设计的批注和方法控制 Web 应用程序行为的 Java 类,称为“控制器 (controller)”类。在包含控制器类的目录中,也包含了页面流中使用的 Java Server Page (JSP)。一个 JSP 要成为页面流的一部分,它必须位于页面流目录中。JSP 文件使用的特殊标记有助于绑定到数据和业务逻辑操作。控制器文件中的操作方法所实现的代码可以导致站点导航、数据传递或通过控件调用后端业务逻辑。而且控制器类中的业务逻辑与 JSP 文件中定义的表示代码相互独立,使得整个Web应用的开发和维护更加清晰高效。   在Pollinate中创建页面流,选择new->other->Page Flow Wizard如图所示  单击next,在弹出框中输入页面流的名称。这里我们创建一个处理客户反馈主题的页面流topics,点击完成之后,便生成了一个基础的页面流,打开页面流所在的文件夹,双击页面流的控制文件Controller.java,点击flow页打开页面流设计视图,如下所示  它由一个begin Action和一个index.jsp页面组成。左侧是设计组件,包括Action,Page,添加所需的页面和Action到页面流中。   在页面流控制文件中添加动作处理代码: //页面流的控制文件,声明流转的目标
.Controller(multipartHandler = Jpf.MultipartHandler.memory, forwards = {
.Forward(name = "showTopics", path = "topicList.jsp"),
.Forward(name = "addTopicAccessories", path = "accessories.jsp"),
.Forward(name = "showLinkmen", path = "linkmanList.jsp"),
.Forward(name = "detailTopic", path = "detailTopic.jsp"),
.Forward(name = "newTopic", path = "newTopic.jsp") })
public class Controller extends PageFlowController {
//在页面流中声明使用的控件
.apache.beehive.controls.api.bean.Control()
protected EjbFinder _ejbFinderControl;
.apache.beehive.controls.api.bean.Control()
protected FileControl _fileControl;

……

//每个Action都对应一次页面流转的动作,以下action对应一个添加反馈主题的动作
.Action()
public Forward addTopic() {
this.topicForm = null;
this.topicForm = new TopicForm();
topicForm.setFileList(new ArrayList());
this.loadLinkman();
return new Forward("newTopic");
}
……
  在页面文件中可以使用netui标记,实现绑定数据,资源声明,模板使用等功能,这样在页面文件中可以最大限度的减少java编码,使得页面更容易维护和管理。以下是一个显示主题列表的页面 topicList.jsp:<netui-template:template templatePage="../web/template/template.jsp">
<netui-template:section name="leftCol" >
<jsp:include page="newTopicNav.jsp" />
</netui-template:section>
<netui-template:section name="centerCol" >
<ejar-ui:window width="70%" title="">
<netui:form action="/newTopic">
<% file="../web/template/errors.jspf"%>
<table>
<tr>
<td>
<netui:span value=""></netui:span>
</td>
<td>
<netui:select dataSource="pageFlow.topicForm.receiverName" optionsDataSource=""></netui:select>
</td>
</tr>
<tr>
<td>
<netui:span value=""></netui:span>
</td>
<td>
<netui:textBox dataSource="pageFlow.topicForm.title"></netui:textBox>
</td>
</tr>
<tr>
<td>
<netui:span value=""></netui:span>

</td>
<td>
<netui:textBox dataSource="pageFlow.topicForm.deadline"></netui:textBox>
<netui:span value=""></netui:span>
</td>

</tr>
<tr>
<td>
<netui:span value=""></netui:span>
</td>
<td>
<netui-data:repeater dataSource="pageFlow.topicForm.fileList">
<netui-data:repeaterItem>
<netui:image src="http://www.xiugoo.com/../resources/images/i.p.attach.gif"></netui:image>
<netui:span value=" "/>

</netui-data:repeaterItem>
</netui-data:repeater>
</td>
</tr>
<tr>
<td>
<netui:span value=""></netui:span>
</td>
<td>

<netui:textArea dataSource="pageFlow.topicForm.content" cols="50" rows="10"></netui:textArea>
</td>
</tr>
<tr>
<td colspan="2" height="40">
<netui:button value="" type="submit" action="/saveTopicForm"></netui:button>

<netui:button type="submit" value=""></netui:button>
</td>
</tr>
</table>
</netui:form>
<br>

</ejar-ui:window>
</netui-template:section>
</netui-template:template>
  最终的页面流文件在Pollinate中对应的设计视图如下所示:  在对整个工程进行Build之后,页面流控制文件被编译为一个class文件和一个对应的配置文件WEB-INF.pageflow-struts-generated jpf-struts-config-[页面流名称].xml,该配置文件定义了一系列控制文件中注释所对应的配置,如下为其中一部分: <struts-config>
<form-beans>
<form-beanname="uploadFileForm" type="org.form.UploadFileForm"
className="org.apache.beehive.netui.pageflow.config.PageFlowActionFormBean">
<set-property property="actualType" value="org.form.UploadFileForm"/>
</form-bean>
</form-beans>
<global-exceptions/>
<global-forwards>
<forward name="showTopics" path="/topicList.jsp"/>
<forward name="addFeedBackAccessories" path="/feedBackAccessories.jsp"/>
</global-forwards>
<action-mappings>
<actionpath="/addAccessories" name="uploadFileForm"
type="org.apache.beehive.netui.pageflow.internal.FlowControllerAction" input="addTopicAccessories"   parameter="topics.Controller" scope="request" validate="true">
<forward name="newTopic" path="/newTopic.jsp"/>
<!--forward "addTopicAccessories" (validationErrorForward)-->
<forward name="addTopicAccessories" path="/accessories.jsp"/>
</action>
……
<message-resources key="_defaultValidationMessages"
parameter="org.apache.beehive.netui.pageflow.validation.defaultMessages" null="true"/>
</struts-config>
  由于篇幅所限,无法详细阐述pollinate的使用,读者可以参考

最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )

GMT+8, 2024-9-30 09:18 , Processed in 0.107316 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

返回顶部