ejb3spring:使用 Spring JSF EJB3 设计企业应用程序

  概述

  Java EE 5.0 核心框架是 EJB(Enterprise JavaBeans)3.0 和 JSF(JavaServerFaces)1.2 EJB 3.0 是个基于 POJO(Plain Old Java Objects) 服务端业务服务和数据库持久化组件模型 JSF 是个基于 MVC(Model-View-Controller) Web 应用框架大多数应用都将包含有业务逻辑 EJB3 组件和用于 Web 应用前端显示 JSF 组件从表面上看EJB3 和 JSF 互补但是他们是根据各自理念设计独立框架这 2者都无法独自解决所有计算问题例如EJB3 使用注解(annotation)来配置服务而 JSF 使用是 XML 文件 EJB3 和 JSF 组件在框架层面上是互不敏感最好结合使用但是 Java EE 5 规范标准并没有提供如何整合这两个组件模型标准思路方法要整合 EJB3 和 JSF开发者必须手动地将业务组件(EJB) 和 Web 组件(JSF) 联结起来以便能跨框架思路方法

  Spring 作为个轻量级容器常被认为是 EJB 替代品对于很多应用情况采用 Spring 作为容器并借助它对事务和 ORM 等支持种比采用 EJB 容器以实现同样功能个选择但也不是使用了 Spring 就不能使用 EJB 了实际上Spring 使得访问和实现 EJB 更加方便 Spring 分别提供了集成 JSF 和 EJB 思路方法本文将使用 Eclipse 开发个举例来演示这个过程

  举例介绍

  本文举例实现了对产品信息增删改查等基本操作只用到了个域模型:Product下面是它 UML 图:

  图 1. Product 类图

 

  搭建开发环境

  本文开发平台采用是 Windows Vista 操作系统因此以下环境设置都是针 WindowsVista 操作系统

  从 Java 站点 下载最新 JDK并安装至任意目录下本文采用是 jdk1.6.0_01

  从 Eclipse 站点 下载 Eclipse for Java EE Developers 3.4 或更新版本解压至任意目录本文采用是 eclipse3.4.1

  从 JBoss 站点 下载 Jboss Application Server 4.2 或更新版本解压至任意目录本文采用是 jboss-4.2.2.GA

  从 Spring 站点 下载 Spring Framework 2.5 或更新版本解压至任意目录本文采用是 spring-framework-2.5.4

  创建 EAR Application Project

  设置 JRE步在 JBoss 运行时需要依次打开 Windows > Preferences > Java > Installed JRES确保选中 JRE Locaton 为 JDK 安装目录本文 JDK 安装目录为 C:\soft\Java\jdk1.6.0_01

  图 2. 设置 JDK



  设置 Server Runtime Environments步配置应用运行环境依次打开 Windows > Preferences > Server > Runtime Environments点击 Add 按钮选择 JBoss > JBoss v4.2点击 Next JRE 选择第步中设置 JRE本文中为 jdk1.6.0_01Application Server Directory 选择 [Jboss 安装目录 ]/ server/default 点击完成按钮如下图:

  图 3. 配置运行环境



  新建名称为 simple EAR Application Project这个工程包括 3 个工程分别是 JPA Project、EJB Project、WEB Project以下步骤将分别介绍这 3个工程 Target Runtime 为 JBoss v4.2EAR version 为 5.0Configuration 为 Default Configuration for JBoss v4.2 如下图:

  图 4. 创建 EAR 工程项目



  点击 Next 选择 Generate Deployment Descriptor点击完成

  开发 JPA Project

  新建名称为 simpleJPA JPA 工程Configuration 为 Default Configuration for JBoss v4.2选中 Add project to anEAR如下图:

  图 5. 创建 JPA 项目



  点击 Next选择默认点击完成

  编辑 JPA persistence.xml 文件内容如下:

  清单 1. JPA persistence.xml 文件



<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
 xmlns="http://java.sun.com/xml/ns/persistence" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
 http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
 <persistence-unit name="simpleJPA">
  <!-- 使用JBoss默认数据源 -->
  <jta-data-source>java:/DefaultDS</jta-data-source>
  <properties>
   <!-- 使用Hibernatehbm2ddl工具在启动时生成表结构 -->
   <property name="hibernate.hbm2ddl.auto" value="update"/>
   <!-- 显示最终执行SQL -->
   <property name="hibernate.show_sql" value="true" />
   <!-- 格式化显示SQL -->
   <property name="hibernate.format_sql" value="true" />
  </properties>
 </persistence-unit>
</persistence>


  persistence-unit 节点可以有个或多个每个 persistence-unit 节点定义了持久化内容名称、使用数据源及持久化产品专有属性 name 属性定义了 persistence-unit 名称该属性是必需本例设置名称为“ simpleJPA ”

  在 JavaEE 环境中默认事务是 JTA而在 JavaSE 环境中则为 RESOURCE_LOCAL 使用 <jta-data-source> 指定数据源 JNDI 名称 Jboss 数据源 JNDI 名称在局部命名空间因此数据源名称前必须带有 java:/ 前缀数据源名称大小写敏感在本文中采用 JBoss 容器中默认数据源JNDI 为 java:/DefaultDS详情请查看:[Jboss 安装目录]/server/default/deployhsqldb-ds.xml

  <properties> 指定持久化产品专有属性各个应用服务器使用持久化产品都不如 Jboss 使用 Hibernateweblogic 使用 Kodo(实际上是基于 OpenJPA 封装)glassfish/sun application server/Oralce 使用 Toplink 对于 Hibernate 而言 hibernate.hbm2ddl.auto 属性指定实体 Bean 发布时是否同步数据库结构 如果 hibernate.hbm2ddl.auto 值设为 create-drop实体 Bean 发布及卸载时将自动创建及删除相应数据库表(注意:Jboss 服务器启动或关闭时也会引发实体 Bean 发布及卸载) TopLink 产品 toplink.ddl-generation 属性也起到同样作用有关 Hibernate 可用属性及默认值您可以在 [Jboss 安装目录]\server\default\deploy\ejb3.deployer\META-INF/persistence.properties 文件中找到在开发阶段Hibernate hibernate.show_sql 和 hibernate.format_sql 属性特别有用它们可以格式化显示 Hibernate 执行 SQL 语句

  新建名称为 org.zhouxing.simple.Product Entity , 根据举例介绍小节中 UML 类图添加 Entity Fields如下图:

  图 6. 新建 Entity



  id 为主键在 EJB3.0 中每个实体 Bean 必须具有个主键主键可以是基本类型也可以是个类主键既作为实体 Bean 在内存中标识符也作为数据表中标识符它在实体 Bean 中是不可缺少并且必须是唯

  表名为 product实体 Bean 成员属性分别映射到 product 表对应字段

  修改主键生成方式为自增给主键添加如下代码: @GeneratedValue(strategy = GenerationType.AUTO)

  @javax.persistence.GeneratedValue 注释指定主键值生成方式该注释和 @Id 注释结合使用在主键属性上只有在使用持久化驱动生成数据表 schema 时才需指定该注释如果您数据表已经存在那么该注释不需要指定 strategy 属性指定字段值生成策略 GenerationType.AUTO:由容器根据数据库类型选择种合适生成方式这种方式带有随机性区别 JPA 实现产品做法各有区别 (JBoss 将 JPA 实现为 Hibernate)对于本文而言Hibernate 知道 HSQL 支持 ID 自增长所以会选择 GenerationType.IDENTITY

  清单 2. 修改的后代码



package org.zhouxing.simple; 

import java.io.Serializable; 

import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.Table; 

/** 
Entity implementation  for Entity: Product 
*/ 
@Entity 
@Table(name = "product") 
public  Product implements Serializable { 

  @Id 
  @GeneratedValue(strategy = GenerationType.AUTO) 
  private long id; 
  private String name; 
  private String description; 
  private Double price; 
  private Integer inventory; 

  public Product { 
    super; 
  } 
  ...tersgetters 思路方法省略
}


  @javax.persistence.Entity 注释指明这是个实体 Beanname 属性指定实体 bean 名称在本文中没有为该属性提供取值默认值为 bean 非限定类名 @javax.persistence.Table 注释指定了实体 Bean 所要映射name 属性指定映射表名称如果缺省 @Table 注释系统默认采用实体名称作为映射表名称在本文中采用表名为product

  至此 JPA Project 完成接下来是 EJB Project

  开发 EJB Project

  新建名称为 simpleEJB EJB 工程EJB Module version 为 3.0Configuration 为 Default Configuration for JBoss v4.2选中 Add project to anEAR如下图:

  图 7. 新建 EJB 工程



  点击 Next取消选择 Create an EJB Clicent JAR点击完成

  新建名称为 org.zhouxing.simple. ProductDAOBean Session Bean如下图:

  图 8. 新建 Session Bean



  选择生成 Local 和 Remote 接口

  同时实现 Remote 和 Local 接口是种比较好做法这样您既可以在远程访问 EJB也可以在本地访问 EJB 在本地接口中写出业务思路方法远程接口继承本地接口所有思路方法代码如下:

  清单 3. Remote 和 Local 接口



本地接口:
package org.zhouxing.simple; 
import java.util.List; 

/** 
本地接口
* 
@author 周行
*/ 
public erface ProductDAOLocal { 
  /** 
  查询所有 Product 
  @ 
  */ 
  public List<Product> findAll; 
  /** 
  添加 Product 
  @param product 
  */ 
  public void add(Product product); 
} 


远程接口:
package org.zhouxing.simple; 

/** 
远程接口
@author 周行
*/ 

public erface ProductDAORemote extends ProductDAOLocal{ 

} 



无状态会话 BEAN 
package org.zhouxing.simple; 

import java.util.List; 

import javax.ejb.Local; 
import javax.ejb.Remote; 
import javax.ejb.Stateless; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 
import javax.persistence.Query; 

/** 
无状态会话 BEAN 
* 
@author 周行
*/ 
@Stateless 
@Remote(ProductDAORemote.) 
@Local(ProductDAOLocal.) 
public  ProductDAOBean implements ProductDAORemote, 
  ProductDAOLocal { 
  /** 
  注入 EntityManager 
  */ 
  @PersistenceContext(unitName = "simpleJPA") 
  protected EntityManager em; 

  /** 
  Default constructor. 
  */ 
  public ProductDAOBean { 
  
  } 

  @Override 
  public void add(Product product) { 
    em.persist(product); 
  } 

  @SuppressWarnings("unchecked") 
  @Override 
  public List<Product> findAll { 
    Query query = em.createQuery("select o from Product o"); 
     query.getResultList; 
  } 

}


  @Stateless 注释指明这是个无状态会话 Bean@Remote 注释指定这个无状态 Bean remote 接口 Bean 类可以具有多个 remote 接口每个接口的间用逗号分隔如:@Remote ({ProductDAORemote.,ProductDAORemote2.,ProductDAORemote3.}) 如果您只有个接口您可以省略大括号对于本文而言可以写成这样:@Remote (ProductDAORemote.) @Local 注释指定这个无状态 Bean local 接口和 @Remote 注释@Local 注释也可以定义多个本地接口

  当 @Local 和 @Remote 注释都不存在时容器会将 Bean 实现接口默认为 Local 接口如果 EJB 和客户端部署在同个应用服务器采用 Local 接口访问 EJB 优于 Remote 接口通过 Remote 接口访问 EJB 需要在 TCP/IP 协议基础上转换和解释 Corba IIOP 协议消息 EJB 过程中存在对象序列化、协议解释、TCP/IP 通信等开销而通过 Local 接口访问 EJB 是在内存中和 Bean 彼此交互没有了分布式对象协议开销大大提高了性能

  @PersistenceContext 注释动态注入 EntityManager 对象在 EJB JNDI ENC 中注册个指向该资源引用 EntityManager 是由 EJB 容器自动管理和配置这包括 EntityManager

  建及清理工作所以我们不需要 close 思路方法释放资源 如果您试图这样做 反而会得到 IllegalStateException 例外借助 EntityManager我们可以创建、更新、删除及查询实体 bean EntityManager 负责将固定数量组类映射到数据库中这组类被称作持久化单元 (persistence unit) persistence unit 是在 persistence.xml 中定义根据持久化规范标准要求该部署描述文件是必须提供如果不提供这文件则持久化单元也将不存在因此应用也不能够获得和使用 EntityManager 本文持久化单元为simpleJPA

  至此 EJB Project 开发完毕接下来是 WEB Project

  开发 WEB Project

  WEB Project 是本文重点在这小节中我们将用 JSF 通过 Spring 来 EJB体验 Spring 便利

  新建名称为 simpleWEB Dynamic WEB ProjectDynamic WEB Project version 为 2.5Configuration 为 JavaServer Faces v1.1 Project选中 Add project to anEAR如下图:

  图 9. 新建 Web 项目



  点击 Next默认下JSF Libraries 选择 Server Supplied JSF Implementation修改 URL Mapping Patterns 为 *.jsf如下图:

  图 10. 配置项目对 JSF 支持



  所有以 *.jsf 结尾请求都有 JSF 处理

  配置 WEB Project

  拷贝 SPRING_HOME/dist/spring.jar 到 WebContent/WEB-INF/lib 目录在 WebContent/WEB-INF 下新建 spring 配置文件 applicationContext.xml

  个 Spring 为框架 Web 项目通常以 web.xml 为入口在 Web 应用启动时读入 context-param 中批量配置文件化配置文件里所定义 Bean通过ContextLoaderListener在 web 应用 servlet context 建立后立即执行建立 Spring ApplicationContext

  编辑 web.xml

  添加 ContextParam:

<context-param> 
  <param-name>contextConfigLocation</param-name> 
  <param-value>/WEB-INF/applicationContext.xml</param-value> 
</context-param> 
 


  添加 Spring listener:

<listener> 
  <listener-> 
  org.springframework.web.context.ContextLoaderListener 
  </listener-> 
</listener>


  编辑 applicationContext.xml内容如下:

  清单 4. applicationContext.xml



 <?xml version="1.0" encoding="UTF-8"?> 
 <beans xmlns="http://www.springframework.org/schema/beans" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:jee="http://www.springframework.org/schema/jee"   
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
 http://www.springframework.org/schema/jee 
 http://www.springframework.org/schema/jee/spring-jee-2.5.xsd"> 

 <jee:jndi-lookup id="productDAO" jndi-name="simple/ProductDAOBean/remote"  
 proxy-erface="org.zhouxing.simple.ProductDAORemote" /> 
 </beans> 
 


  Spring 通过 jndi-lookup 来访问 EJB以后就可以在本地 EJB 组件远程 EJB 或者 POJO 这些变体的间透明地切换实现方式而不需要改变客户端代码

  新建名称为 org.zhouxing.simple.ProductBean 个类作为 JSF managed Bean JSF 使用 JavaBean 来达到逻辑和视图分离在 JSF 中 Bean 其角色是属于 Backing Bean又称的为 Glue Bean其作用是在真正业务逻辑 Bean 及 UI 组件的间搭起桥梁在 Backing Bean 中会呼叫业务逻辑 Bean 处理使用者请求或者是将业务处理结果放置其中等待 UI 组件取出当中值并显示结果给使用者

  主要有两个思路方法实现业务功能代码如下:

  清单 5. 业务功能代码



package org.zhouxing.simple; 

import java.util.List;

/** 
JSF Managed Bean 实现 Product 查询添加
@author 周行
*
*/ 
public  ProductBean { 
  private ProductDAORemote productDAO; 
  private Product product; 

  public ProductBean { 
    product =  Product; 
  } 

  public void ProductDAO(ProductDAORemote productDAO) {
    this.productDAO = productDAO; 
  }

  public String add { 
    productDAO.add(product); 
     ""; 
  }

  public List<Product> getProducts { 
     productDAO.findAll; 
  }

  public Product getProduct { 
     product; 
  } 
}
 


  属性 productDAO 通过 JSF 配置文件用 Spring 注入属性 product 为简单起见作为表单 Form

Tags:  weblogicejb3 jsf整合spring jsfspring ejb3spring

延伸阅读

最新评论

发表评论