zoukankan      html  css  js  c++  java
  • 了解 Java EE 5

    重要增强功能意味着更快、更容易、更简单地开发企业应用程序

    developerWorks
    文档选项

    未显示需要 JavaScript 的文档选项

    将打印机的版面设置成横向打印模式

    打印本页

    将此页作为电子邮件发送

    将此页作为电子邮件发送



    级别: 中级

    Roland Barcia (barcia@us.ibm.com), IT 咨询专家, IBM WebSphere 软件服务部

    2007 年 11 月 01 日

    概要介绍新的 Java™ EE 5 规范、它的许多重要增强功能以及它对 WebSphere® 应用程序的意义。

    引言

    纵 观 Java Platform, Enterprise Edition (Java EE) 规范的历史可以看出,每次重大修订都是由一个重要主题推动的。例如,第一次发布 J2EE™ 1.2 时,伴随的重要主题是首次将单独的规范绑定在一起,后来,在 J2EE 1.4 中,关注的重要主题则是 Web 服务。图 1 显示了 Java EE 的摘要历史,列出了每个版本的重要功能以及促成每次修订的一些重要外部影响。


    图 1. Java EE 的历史
    图 1. Java EE 的历史

    与一些新技术的大多数早期版本一样,Java EE 规范的以前版本中存在一些“难点”,其中包括:

    • 业务逻辑编程的复杂性。
    • 持久性编程模型的复杂性和性能。
    • 表示层/逻辑混合。
    • Web 服务的类型、复杂性、文档模型、扩展和性能。
    • 多成员团队开发。
    • 漫长的编辑-编译-调试周期。

    这时,毫无疑问,Java EE 5 规范的主题就是简化,这一目标已通过改善以下领域的开发体验得到实现:

    • 简化业务逻辑开发。
    • 简化测试和依赖关系管理。
    • 简化 O/R 持久性。
    • 增强 Web 服务编程模型。

    Java EE 5 中的许多升级都受到商业和开放源代码领域创新技术的影响,例如 Hibernate、Spring、Service Data Object (SDO) 以及其他技术。另外,还预期对规范的级别进行升级,做一些小幅度的改进。

    为 您使用 Java EE 5 做准备,本文重点介绍新规范的一些主要功能,如 EJB 3.0、Java Persistance Architecture (JPA)、Web 服务、JAX-WS 及其他一些内容,然后简单地介绍我们对 Java EE 6 的一些可能的预期。





    回页首


    EJB 3.0

    对于 Java EE 5 中的所有技术增强而言,Enterprise JavaBean™ (EJB) 3.0 是最为显著的,已对它的外观进行了很大的更改,明显简化了开发。EJB 3.0 规范已拆分为三个子规范:

    • EJB 3.0 简化 API:定义用于编码 EJB 组件(特别是会话 Bean 和消息驱动的 Bean)的新简化的 API。

    • 核心契约和要求:定义 Bean 和 EJB 容器之间的 EJB 契约。

    • Java 持久性体系结构 API:为持久性定义新实体 Bean 模型。

    下一部分描述 EJB 3.0 和 JPA API 的更新。

    EJB 3.0 简化

    POJO (传统 Java 对象)是最近经常提到的一个术语,它是指编写为简单 Java 类的代码。由于 EJB 2.x 程序要求您扩展特定的类、提供多个接口并编写部署描述符,因此它们被视为“重载”的 Java 对象,而不再是简单的对象;而且,还需要 J2EE 容器来运行和测试它们。EJB 3.0 的更改包括:

    • EJB 组件不再要求主接口。另外,不再需要 EJB 组件提供不同的接口或扩展任何特定于 EJB 的类。

    • J2SE 5.0 标注现在是实现 EJB 3.0 组件的一个主要辅助方法。通过指定特殊的标注,开发人员可以创建 EJB 组件的 POJO 类,并将其作为 XML 的备选方案。

    • EJB 3.0 引入了业务接口概念,而非单独的远程和本地接口。下面给出了它的一个示例:

      清单 1

                                  
      public interface Stock
      {
      public double getQuote(String symbol);
      }

      您的 Bean 类可以实现以下接口:

      清单 2
                                  
      @Stateless public class StockBean implements Stock
      public double getQuote(String symbol)
      {
      return 100.33;
      }
      }

      在上面的示例中,@Stateless 标注意味着此类现在是一个无状态的会话 Bean,并且使用业务接口来调用它。还可以在不实现特定接口的情况下对无状态会话 Bean 进行编码,而且可以通过容器生成一个:

      清单 3
                                  
      @Stateless public class StockBean
      public double getQuote(String symbol)
      {
      return 100.33;
      }
      }

      缺省情况下,除非特别标注,否则,所有公共方法都包括在业务接口中。例如,如果使用 @BusinessMethod 至少指定一个方法,则只有使用 @BusinessMethod 指定的方法才包括在业务接口中:

      清单 4
                                  
      @Stateless public class StockBean
      @BusinessMethod public double getQuote(String symbol)
      {
      return 100.33;
      }
      }

      现在已经创建了一个接口,那么如何指定一个方法是远程的还是本地的?当然,可以使用一个标注:

      清单 5
                                  
      @Stateless public class StockBean
      @Remote public double getQuote(String symbol)
      {
      return 100.33;
      }
      }

      您可以标注业务接口或者 Bean 类本身。当选择生成业务接口时,在 Bean 类上启用标注非常有用。

    EJB 3.0 规范的更新包括以下内容:

    1. 容器服务
    2. 回调
    3. 拦截器
    4. 依赖项注入
    1. 容器服务

      EJB 组件由于隐式支持事务管理和安全性,因此非常受欢迎。EJB 3.0 规范使用标注(和 XML)来应用容器服务。下面给出了一个示例,介绍如何在无状态会话 Bean 上指定事务属性。

      清单 6

                                  
      @Stateless public class StockBean
      {

      @TransactionAttribute(TransactionAttributeType.REQUIRESNEW)
      public double getQuote(String symbol)
      {
      return 100.33;
      }
      }

      此标注意味着,该方法将在新事务中运行。请参见规范,了解不同标注的具体语法和语义,但相同事务和安全功能都有标注。还可以使用 XML 部署描述符应用容器服务,而XML 部署描述符可以在部署时覆盖启用灵活性的标注。
    2. 回调

      回 调是什么情况?在 EJB 3.0 之前,必须在 Bean 类上实现回调方法,如 ejbCreate();Bean 类必须实现所有方法,无论是否使用它们。在大多数情况下,这些方法实现是空的。现在还通过标注并使用回调方法或回调侦听器类处理回调。下面是一个示例,说 明如何编写代码来使用回调方法响应回调:

      清单 7

                                  
      @Stateless public class StockBean implements Stock
      public double getQuote(String symbol)
      {
      return 100.33;
      }

      @PostConstruct initializeCache()
      {
      }
      }

      以上代码可让您在创建 Bean 实例之后实现代码。如果希望使用回调侦听器,则可以创建回调侦听器类:

      清单 8
                                  
      public class MyCallbackListener
      {
      @PrePassivate public clearCache(Object obj)
      {
      Stock stock = (Stock) obj;
      //perform logic
      }
      }

      不属于 Bean 类的回调类必须获取 java.lang.Object 参数。容器然后传递 Bean 实例。Bean 类通过使用特殊回调标注在 Bean 类级别添加回调侦听器类:

      清单 9
                                  
      @CallbackListener MyCallbackListener
      @Stateless public class StockBean implements Stock
      public double getQuote(String symbol)
      {
      return 100.33;
      }
      }

      回调方法比较好,因为在代码中包括回调方法是有条件的,这与实现接口不同。
    3. 拦截器

      EJB 规范另一增强功能是使用拦截器。EJB 组件以前缺少的功能是无法对预处理/后处理和横切关注点(与 Servlet 筛选器对 Servlet 的作用类似)等内容执行面向方面的开发 (AOP)。现在可以开发一个拦截器类并将其应用到 Bean。下面是一个审核 StockBean 类调用的拦截器类的示例:

      清单 10

                                  
      public class StockRequestAudit {
      @AroundInvoke
      public Object auditStockOperation(InvocationContext inv) throws
      Exception {
      try {
      Object result = inv.proceed();
      Auditor.audit(inv.getMethod().getName(), inv.getParameters[0]);
      return result;
      } catch (Exception ex) {
      Auditor.auditFailure(ex);
      throw ex;
      }
      }
      }

      上 面的拦截器拦截对目标 EJB 方法的调用,然后调用 InvocationContext 上的 proceed() 方法。这可让该调用方法流经实际被调用的 EJB 方法。在返回目标 EJB 方法之后,它使用 InvocationTarget 中的元数据来获取被调用的目标 EJB 组件的方法名和参数。然后可以将拦截器应用到 Bean 类:

      清单 11
                                  
      @Stateless @Interceptors({StockRequestAudit})
      public class StockBean implements Stock
      public double getQuote(String symbol)
      {
      return 100.33;
      }
      }

      另 外,还可以开发一个在 Bean 类内部实现的拦截器方法,而且可以指定多个拦截器,在指定多个拦截器时,它们的调用顺序由其在 Bean 类中定义的顺序指定。还可以使用 XML 在 Bean 以外应用拦截器,这在 AOP 中为首选方法,因为您希望向 Bean 透明地应用横切关注点。
    4. 依赖项注入

      依 赖于数据源之类的 EJB 代码依赖项和 EJB 客户端调用 EJB 组件的方式难以进行 EJB 开发测试。为解决此问题,EJB 3.0 规范引入了依赖项注入机制。EJB 没有使用 JNDI 查找,而是通过注入代码定义一个资源引用。下面是 EJB Bean 的一个示例,此 EJB Bean 需要调用另一个 EJB 组件并使用数据源执行 JDBC 工作:

      清单 12

                                  
      @Stateless public class StockBean implements Stock
      {
      @EJB(name="MarketBean", businessInterface="Market")
      Market market;

      @Resource(name="StockDB, resourceType="javax.sql.DataSource")
      DataSource stockDS

      public double getQuote(String symbol)
      {
      Connection con = stockDS.getConnection();
      //DO JDBC work

      return market.getCurrentPrice(symbol);
      }
      }

      依赖项注入可以通过多种方式进行,例如通过 setter 方法或类变量。有关详细信息,请参见规范

    Java 持久性体系结构 (JPA)

    EJB 持久性的规范已发生了显著变化。该规范称为容器管理的持久性 (CMP),它没有定义映射层,而是由容器映射;因此它由供应商实现映射。受多个商业和开源产品和技术(如 Hibernate、Java Data Objects (JDO) 和 TopLink)的影响,EJB 3.0 引入了新的持久性样式,即基于 POJO 的持久性:

    • 在成功模式上建模。
    • 简化 JDBC 访问模式。
    • 可以与 Web 服务集成。
    • 不受容器的阻碍;可以在 Java EE 或 Java SE 环境中使用 JPA。
    • 标准化 O/R 映射元数据。
    • 支持自顶向下、中间相遇和自底向上的开发。
    • 支持断接和连接的对象状态,省去了对单独的数据传输对象的需要。图 2 显示了一个示例。

    图 2. 支持对象状态
    图 2. 支持对象状态

    JPA API 的更新包括以下内容:

    1. 类型:实体和表
    2. 实例:Java 对象
    3. 属性:Java 属性和列标注
    4. 依赖对象:嵌入式 Java 对象
    5. 派生属性:瞬态标注
    6. 键属性:标注的字段和键类
    7. 关系:标注和联合列
    8. 约束:标注和数据库
    9. 继承:标注——单个表、联合表和按类表
    1. 类型:实体和表

      JPA 的类型是实体(不再称为实体 Bean),这些实体可以映射到表。映射的主要机制是通过标注实体类。下面是客户 Java 对象和 CUSTOMER 表之间的一个映射示例:

      清单 13

                                  
      @Entity
      @Table(name="CUSTOMER")
      public class Customer implements Serializable {
      ...

      类被标注为一个实体并使用客户标注。部署描述符可用作备用或覆盖机制。
    2. 实例:Java 对象

      应 用程序在运行时与 Java 对象交互。通过使用称为实体管理器的特殊对象,应用程序可以查询或保持对象。使用 EJB 容器中的依赖项注入将实体管理器注入到应用程序(在 Java SE 环境中也可以通过 EntityManagerFactory 查找)。下面是一个示例:

      清单 14

                                  
      @PersistenceContext (unitName="db2")
      private EntityManager em;

      应用程序可以检索对象或者将它们传递到实体管理器。下面是使用实体管理器通过主键查找对象的应用程序示例:

      清单 15
                                  
      Customer customer = (Customer)em.find(Customer.class,customerId);

      下面是另一个示例,说明创建 Java 对象,并通过将其传递到实体管理器而保存到数据库:

      清单 16
                                  
      CustomerOrder newOrder = new CustomerOrder();
      newOrder.setStatus("OPEN");
      newOrder.setTotal(new Integer(0));
      newOrder.setCustomerId(customerId);
      em.persist(newOrder);

    3. 属性:Java 属性和列标注

      属性是类中的 Java 属性。Java 属性可以通过 @column 标注映射到数据库列。共有两种属性映射形式:字段或属性(缺省):

      清单 17

                                  
      @Entity(access=FIELD)
      @Table(name="PRODUCT")
      public class Product implements Serializable {

      @Id
      @Column(name="SKU")
      Integer sku;

      @Column(name="DESC")
      String description;

      @Column(name="PRICE")
      Integer cost;

    4. 依赖对象:嵌入式 Java 对象

      JPA 支持依赖对象。可以创建一个特殊的可嵌入对象,可以通过使用 @Embeddable 标注类对其进行定义:

      清单 18

                                  
      @Embeddable
      public class CustomerAddress {
      private int streetAddress;
      private String city;
      private String state;
      private String country;
      ...
      }

      然后可以将该对象定义为实体类上的一个字段:

      清单 19
                                  
      @Entity
      @Table(name="CUSTOMER")
      public class Customer {
      private String name;
      private CustomerAddress ca;

      @Embedded
      @AttributeOverrides({
      @AttributeOverride(name="streetAddress", column=@Column("
      STRT_ADD")),
      @AttributeOverride(name="city", column=@Column("CITY"))
      ... //more
      })
      public CustomerAddress getCustomerAddress()
      {

      ...
      }

      使用特殊的属性覆盖,可以将可嵌入类的字段映射到实体中。备用方法是直接将列映射到可嵌入类。
    5. 派生属性:瞬态标注

      缺省情况下,所有字段在 JPA 中都是持久性的;但是,您可以将一个字段标注为瞬态的,然后可以使用逻辑派生任何字段。下面是执行派生字段的查询:

      清单 20

                                  
      @Transient
      public Integer getTotal() {

      Query totalLineItems = em.createNamedQuery("getOrderTotal");
      totalLineItems.setParameter("orderId",orderId);
      Integer result = (Integer)totalLineItems.getSingleResult();
      return result;
      }

    6. 键属性:标注的字段和键类

      JPA 支持多种主键以及各种键的生成。在下面的简单示例中,您可以使用 @Id 标注将实体上的字段标注为主键:

      清单 21

                                  
      @Entity
      @Table(name="CUSTOMER")
      public class Customer implements Serializable {

      private Integer id;
      private String name;
      private CustomerOrder currentOrder;


      @Id
      @Column(name="CUST_ID")
      public Integer getId() {
      return id;
      }
      public void setId(Integer id) {
      this.id = id;
      }
      ...

      还可以为具有组合键的实体创建一个主键类:

      清单 22
                                  
      public class LineItemId implements Serializable {

      private Integer orderId;
      private Integer productId;
      public LineItemId() {
      super();
      // TODO Auto-generated constructor stub
      }
      @Column(name="ORDER_ID")
      public Integer getOrderId() {
      return orderId;
      }
      public void setOrderId(Integer orderId) {
      this.orderId = orderId;
      }

      @Column(name="PRODUCT_ID")
      public Integer getProductId() {
      return productId;
      }
      public void setProductId(Integer productId) {
      this.productId = productId;
      }
      public boolean equals(Object arg0) {
      if (arg0 == this) return true;
      if (!(arg0 instanceof LineItemId)) return false;
      LineItemId other = (LineItemId)arg0;
      if(other.getOrderId().equals(orderId) &&
      other.getProductId().equals(productId))
      {
      return true;
      }
      return false;

      }
      public int hashCode() {
      return orderId + productId.hashCode();
      }

      }

      然后可以使用 @IdClass 标注在实体上定义组合键:

      清单 23
                                  
      @Entity
      @Table(name="LINEITEM")
      @IdClass(LineItemId.class)
      public class LineItem implements Serializable {

      您的实体类必须在类上具有匹配字段,或者它可以作为可嵌入键嵌入该键:

      清单 24
                                  
      @Entity
      @Table(name="LINEITEM")
      @IdClass(LineItemId.class)
      public class LineItem implements Serializable {
      private LineItemId lineItemId;

      @EmbeddedId
      public LineItemId getLineItemId()
      {
      return lineItemId;
      }

      ...

      另一个主要增强是支持生成主键。通过使用 @Id 标注的生成属性,可以选择一个不同的策略。例如,您可以选择向 DB2 标识列委派主键生成,如下所示:

      清单 25
                                  
      @Id(generate=GeneratorType.IDENTITY)
      @Column(name="ORDER_ID")
      public Integer getOrderId() {
      return orderId;
      }
      public void setOrderId(Integer orderId) {
      this.orderId = orderId;
      }

      其他受支持机制包括序列和表生成。
    7. 关系:标注和联合列

      JPA 对实体之间的关系提供强大的支持。JPA 支持一对一、一对多、多对一和多对多关系。在 JPA 中,关系不是双向的,这与 EJB 2.x 中相同。相反,对象将其他实体声明为成员,并添加标注来定义关系。可以使用特殊属性将关系转换为双向的。下面是具有两个不同关系的 CustomerOrder 类的示例:

      清单 26

                                  
      @Entity
      @Table(name="CUSTOMER")
      public class Customer implements Serializable {


      private Integer id;
      private String name;
      private CustomerOrder currentOrder;


      @Id
      @Column(name="CUST_ID")
      public Integer getId() {
      return id;
      }
      public void setId(Integer id) {
      this.id = id;
      }

      @Column(name="NAME")
      public String getName() {
      return name;
      }
      public void setName(String name) {
      this.name = name;
      }

      @OneToOne(cascade=CascadeType.ALL , fetch=FetchType.EAGER )
      @JoinColumn(name="OPEN_ORDER_ID",referencedColumnName="ORDER_ID")
      public CustomerOrder getCurrentOrder() {
      return currentOrder;
      }
      public void setCurrentOrder(CustomerOrder currentOrder) {
      this.currentOrder = currentOrder;
      }

      }

      在 此关系中,通过在 Customer 类中标注 CustomerOrder 属性,将 Customer 与 CustomerOrder 定义为一对一关系。还定义了 JoinColumn 信息。名称属性在 Customer 类映射到的表上定义外键,参考列定义 Table CustomerOrder 映射到的主键。对关系的任何约束都定义为 @OneToOne 标注的属性。CustomerOrder 类如下所示。CustomerOrder 定义了一个 Customer 属性;不过 CustomerOrder 对象有一个返回到 Customer 的一对多关系。这是因为 Customer 只能有一个当前顺序;实际上,一个客户可以有多个顺序,因此 CustomerOrder 显示了这一点。不过,此处的 mappedBy 属性用于定义由 Customer 类将 CustomerOrder 映射到关系的另一侧。此类如下所示:

      清单 27
                                  
      public class CustomerOrder implements Serializable {
      private Integer orderId;
      private String status;
      private Integer total;
      private Integer customerId;
      private Collection<LineItem> lineItems;
      private Customer customer;

      @Column(name="CUSTOMER_ID")
      public Integer getCustomerId() {
      return customerId;
      }
      public void setCustomerId(Integer customerId) {
      this.customerId = customerId;
      }

      @Id(generate=GeneratorType.IDENTITY)
      @Column(name="ORDER_ID")
      public Integer getOrderId() {
      return orderId;
      }
      public void setOrderId(Integer orderId) {
      this.orderId = orderId;
      }
      @Column(name="STATUS")
      public String getStatus() {
      return status;
      }
      public void setStatus(String status) {
      this.status = status;
      }
      @Column(name="TOTAL")
      public Integer getTotal() {
      return total;
      }
      public void setTotal(Integer total) {
      this.total = total;
      }

      @ManyToOne(fetch=FetchType.EAGER,optional=false)
      @JoinColumn(name="CUSTOMER_ID",
      referencedColumnName="CUST_ID",insertable=false,updatable=false,
      nullable=false,unique=true)
      public Customer getCustomer() {
      return customer;
      }
      public void setCustomer(Customer customer) {
      this.customer = customer;
      }
      @OneToMany(mappedBy="customerOrder", cascade=CascadeType.ALL ,
      fetch=FetchType.EAGER)
      public Collection<LineItem> getLineItems() {
      return lineItems;
      }
      public void setLineItems(Collection<LineItem> lineItems) {
      this.lineItems = lineItems;

      }

      }

      CustomerOrder 中的另一关系包含 LineItem 对象的集合。这是一个一对多关系。注意,JRE 5 定义泛型的使用,指定集合的类型。此处还使用了特殊的 mappedBy 属性,使关系的另一侧映射成为双向关系。

      清单 28
                                  
      @Entity
      @Table(name="LINEITEM")
      @IdClass(LineItemId.class)
      public class LineItem implements Serializable {

      private Product product;
      private Integer orderId;
      private Integer productId;
      private Integer quantity;
      private Integer total;
      private CustomerOrder customerOrder;

      @Column(name="QUANTITY")
      public Integer getQuantity() {
      return quantity;
      }
      public void setQuantity(Integer quantity) {
      this.quantity = quantity;
      }

      @Column(name="AMOUNT")
      public Integer getTotal() {
      return total;
      }
      public void setTotal(Integer total) {
      this.total = total;
      }

      @ManyToOne(fetch=FetchType.EAGER,optional=false)
      @JoinColumn(name="PRODUCT_ID",
      referencedColumnName="SKU",insertable=false,updatable=false,
      nullable=false,unique=true)
      public Product getProduct() {
      return product;
      }
      public void setProduct(Product product) {
      this.product = product;
      }

      @Column(name="ORDER_ID")
      public Integer getOrderId() {
      return orderId;
      }
      public void setOrderId(Integer orderId) {
      this.orderId = orderId;
      }

      @Column(name="PRODUCT_ID")
      public Integer getProductId() {
      return productId;
      }
      public void setProductId(Integer productId) {
      this.productId = productId;
      }
      @ManyToOne(fetch=FetchType.EAGER,optional=false)
      @JoinColumn(name="ORDER_ID",
      referencedColumnName="ORDER_ID",insertable=false,updatable=false,
      nullable=false,unique=true)
      public CustomerOrder getCustomerOrder() {
      return customerOrder;
      }
      public void setCustomerOrder(CustomerOrder customerOrder) {
      this.customerOrder = customerOrder;
      }

      }

      LineItem 类有一个 CustomerOrder 属性。这里定义了一个多对一关系,如上面所示。类似地,LineItem 类与产品对象也具有多对一关系。

      另一映射类型是,表可能有一对一关系,但对象模型只有一个对象。换句话说,您希望在跨多个表映射单一对象(在某种程度上与依赖对象相反)。可以通过添加一个或多个辅助表做到这一点。下面是跨 Customer 和 Order 表映射客户对象的一个示例。

      清单 29

                                  
      @Entity
      @Table(name="CUSTOMER")
      @SecondaryTable(name="ORDER ",
      pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID"))
      public class Customer { ... }

    8. 约束:标注和数据库

      JPA 除支持各种数据库约束外,还可以使用它定义对各种关系的约束:

      清单 30

                                  
      @OneToMany(mappedBy="customerOrder", cascade=CascadeType.ALL ,
      fetch=FetchType.EAGER)
      public Collection<LineItem> getLineItems() {
      return lineItems;
      }
      public void setLineItems(Collection<LineItem> lineItems) {
      this.lineItems = lineItems;
      }

      在本例中显示了级联影响。例如,如果删除了客户,也将删除客户的顺序。下面是一个具有更多约束的示例:

      清单 31
                                  
      @ManyToOne(fetch=FetchType.EAGER,optional=false)
      @JoinColumn(name="CUSTOMER_ID", referencedColumnName="CUST_ID",
      insertable=false,updatable=false, nullable=false,unique=true)

      public Customer getCustomer() {
      return customer;
      }
      public void setCustomer(Customer customer) {
      this.customer = customer;
      }

      在上例中,跨外键(也是主键的一部分)定义了多对一关系。在本例中,不允许任何人更新或插入同样标记为唯一和不得为空的列。此关系也指定为不可选。JPA 还可让您在特定实体上定义唯一约束,如下所示:

      清单 32
                                  
      @Entity
      @Table(
      name="EMPLOYEE",
      uniqueConstraints=
      {@UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"})}
      )

    9. 继承:标注——单个表、联合表和按类表

      JPA 规范定义了对映射继承的三种类型的支持;其中只有一种在当前规范中是强制的:

      • 单个表:对象树映射到一个表。
      • 联合表:(可选)将子类映射到与父类映射到的表具有外键关系的表。
      • 按类表:(可选)每个具体的子类映射到一个表,并且包含超类属性的列。

      下面是一个使用单表策略映射超类和子类的示例:

      清单 33

                                  
      @Entity
      @Table(name="CUST")
      @Inheritance(strategy=SINGLE_TABLE,
      discriminatorType=STRING,

      discriminatorValue="CUST")
      public class Customer { ... }


      @Entity
      @Inheritance(discriminatorValue="VCUST")
      public class ValuedCustomer extends Customer { ... }

      下面是一个使用联合表策略的示例:

      清单 34
                                  
      @Entity
      @Table(name="CUST")
      @Inheritance(strategy=JOINED,
      discriminatorType=STRING,
      discriminatorValue="CUST")
      public class Customer { ... }

      @Entity
      @Table(name="VCUST")
      @Inheritance(discriminatorValue="VCUST")
      @PrimaryKeyJoinColumn(name="CUST_ID")
      public class ValuedCustomer extends Customer { ... }

    请参阅参考资料,以了解 JPA 中提供的更多其他功能。





    回页首


    JAX-WS

    Java EE 5 还为 Web 服务引入了一个新的编程模型:JAX-WS。在了解不同之处之前,您需要知道从 JAX-RPC 到 JAX-WS 哪些内容没有发生变化:

    • JAX-WS 仍然支持 SOAP 1.1 over HTTP 1.1,因此互操作性将不会受到影响。仍然可以在网上传递相同的消息。
    • JAX-WS 仍然支持 WSDL 1.1,因此您所学到的有关该规范的知识仍然有用。新的 WSDL 2.0 规范已经接近完成,但在 JAX-WS 2.0 相关工作结束时其工作仍在进行中。

    系列文章 Web 服务提示与技巧:JAX-RPC 与 JAX-WS 的比较包含关于 JAX-WS 的详细信息,下面大致列出了从 JAX-RPC 1.1 到 JAX-WS 2.0 都发生了哪些更改:

    • SOAP 1.2:JAX-RPC 和 JAX-WS 都支持 SOAP 1.1。JAX-WS 还支持 SOAP 1.2。
    • XML/HTTP:WSDL 1.1 规范在 HTTP 绑定中定义,这意味着利用此规范可以在不使用 SOAP 的情况下通过 HTTP 发送 XML 消息。JAX-RPC 忽略了 HTTP 绑定。而 JAX-WS 添加了对其的支持。
    • WS-I Basic Profile:JAX-RPC 支持 WS-I Basic Profile (BP) V1.0。JAX-WS 支持 BP 1.1。(WS-I 即 Web 服务互操作性组织。)
    • 新的 Java 功能:JAX-RPC 映射到 Java 1.4。JAX-WS 映射到 Java 5.0。JAX-WS 依赖于 Java 5.0 中的很多新功能。(Java EE 5 是 J2EE 1.4 的后续版本,添加了对 JAX-WS 的支持,但仍然支持 JAX-RPC,这可能会对 Web 服务新手造成混淆。)
    • 数据映射模型:JAX-RPC 具有自己的映射模型,此模型大约涵盖了所有模式类型中的 90%。那些没有包括的模式被映射到 javax.xml.soap.SOAPElement(JAX-WS 数据映射模型是 JAXB,该模型映射所有 XML 模式)。
    • 接口映射模型:JAX-WS 的基本接口映射模型与 JAX-RPC 的区别并不大,不过 JAX-WS 模型使用新的 Java 5.0 功能,并引入了异步功能。
    • 动态编程模型:JAX-WS 的动态客户端模式与 JAX-RPC 模式差别很大。根据业界的需要进行了许多更改,其中包括面向消息的功能和动态异步功能。JAX-WS 还添加了动态服务器模型,而 JAX-RPC 则没有此模型。
    • 消息传输优化机制 (MTOM):JAX-WS 通过 JAXB 添加了对新附件规范 MTOM 的支持,因此应该能够实现附件互操作性。
    • 处理程序模型:从 JAX-RPC 到 JAX-WS 的过程中,处理程序模型发生了很大的变化。JAX-RPC 处理程序依赖于 SAAJ 1.2,而 JAX-WS 处理程序则依赖于新的 SAAJ 1.3 规范。

    JAX-WS 还可以与 EJB 3.0 一起使用来简化编程模型。例如,下面的代码显示了将 EJB 3.0 POJO 转换为 Web 服务的简单方法:


    清单 35
                    
    @WebService public interface StockQuote {
    public float getQuote(String sym);
    }

    @Stateless public class QuoteBean implements StockQuote {
    public float getQuote(String sym) { ... }
    }

    还添加了其他标注以便支持 Web 服务中更高级的功能。JAX-B 提供了 POJO(清单 36)和 XML 模式(清单 37)之间的标准映射,下面给出了它的一个示例:


    清单 36
                    
    @XmlType
    public class Trade {
    @XmlElement(name="tickerSymbol")
    public String symbol;
    @XmlAttribute
    int getQuantity() {...}
    void setQuantity() {...}
    }


    清单 37
                    
    <xs:complexType name="trade">
    <xs:sequence>
    <xs:element
    name="tickerSymbol"
    type="xs:string"/>
    </xs:sequence>
    <xs:attribute name="quantity"
    type="xs:int"/>
    </xs:complexType>





    回页首


    JavaServer Faces

    JavaServer™ Faces (JSF) 到目前为止已有数年的历史,并且受大多数 Java EE 应用服务器支持,例如 IBM® WebSphere Application Server。在 Java EE 5 中,JSF 现在是 Java EE 5 规范的一部分。JSF 为 Java EE 应用程序提供了许多好处:

    • 丰富、可扩展的 UI 组件。
    • 事件驱动。
    • 托管组件状态。
    • 呈现器/客户端独立性。
    • 验证程序。
    • 类型转换。
    • 外部化导航。
    • JavaServer Pages 和 Faces 通用表达语言。




    回页首


    展望 Java EE 6

    最近对 JSR 316 (Java EE 6) 提出了一些议案,尽管对其规范定义为时尚早,但该议案突出了以下几个重要主题:

    • 可扩展性:通过添加更多扩展点和更多服务提供程序接口,可以将其他技术简洁高效地插入平台实现,从而实现了可增长性。

    • 概要:概 要将根据 JCP 过程的定义参考 Java EE 平台,并且可能包括 Java EE 平台技术的子集或/和不属于基本 Java EE 平台的其他 JCP 技术。专家组还将定义 Java EE Web 概要的第一个版本,这是一个用于 Web 应用程序开发的 Java EE 平台的子集。

    • 技术修剪:Java EE 平台中的一些技术不再具有它们刚引入平台时的相关性。需要有一种方法,能够认真有序地将这些技术从平台中“修剪”掉,并让仍使用这些技术的开发人员受到的 影响降到最小,同时使平台能够更健壮地成长。正如该过程定义的那样,专家组将考虑在将来的 Java EE 平台规范中应将某些技术标记为可被移除。这些可能被移除的技术包括:

      • EJB CMP,被 Java Persistence 有效地代替。
      • JAX-RPC,被 JAX-WS 有效地代替。
    • SOA 支持:Java EE 平台已经广泛应用于 SOA 应用程序。随着越来越多的企业认识到 SOA 体系结构的好处,对该平台的功能和互操作性的需要也相应提高。Java EE 6 需要考虑增加对 Web 服务的支持。尽管基本 Web 服务支持现在是 Java SE 6 平台的一部分,但此规范将需要这些技术的更新版本,以便提供更多的 Web 服务支持。服务组件体系结构 (SCA) 定义一些可以在 SOA 环境中由组合应用程序使用的工具。专家组在考虑将所有 SCA 定义的工具都包含在 Java EE 6 平台中是否合适。

    • 其他增加内容:专家组提议在 Java EE 6 中包括下列新的 JSR:

      • 用于容器的 JSR-196 Java 身份验证 SPI。
      • 用于应用服务器的 JSR-236 计时器。
      • 用于应用服务器的 JSR-237 工作管理器。
      • JSR-299 Web Bean。
      • JSR-311 JAX-RS:用于 RESTful Web 服务的 Java API。

    预计在以下领域进行进一步更新:

    • Enterprise JavaBeans。
    • Java Persistence API。
    • Servlet。
    • JavaServer Faces。
    • JAX-WS。
    • Java EE Connector API。

    具体要包括哪些技术将由专家组根据合作伙伴和客户要求确定。其中一些规范还要考虑快速发展的 Web 2.0 空间。





    回页首


    结束语

    Java EE 5 是一个功能强大而重要的发行版,是用于企业开发的最完善的版本。显然,已经采取了一些重要步骤解决了围绕以前 Java 开发的一些问题。EJB 3.0 和 JPA 是功能强大而又易用的技术,而且 JAX-WS 中的增强功能使得 Web 服务的开发比以往更加容易。





    回页首


    致谢

    作者感谢 Jim Knutson 和 Russell Butek 对本文所做的贡献。



    参考资料

    学习

    获得产品和技术


    关于作者

    Roland Barcia 的照片

    Roland Barcia 是位于纽约/新泽西州 Metro 区 IBM WebSphere 软件服务部 的 IT 咨询专家。他是 IBM WebSphere: Deployment and Advanced Configuration 的合著者。有关 Roland 的详细信息,请访问他的网站

     
  • 相关阅读:
    SQL server 事务介绍,创建与使用
    DOM操作系列-01
    JS键盘事件
    Js获取当前日期时间及其它操作
    js中!!的作用
    js == 与 === 的区别[转]
    学习总结--Dom
    css历史
    javascript中 visibility和display的区别
    “==”和Equals区别
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6470835.html
Copyright © 2011-2022 走看看