JBoss Seam:一個深度整合框架(一)

梧桐雨—168發表於2008-04-18
本文介紹了JBoss Seam的產生背景以及整合框架的概念,並且演示了在JBoss Seam中如何使用POJOs處理JSF事件以及實現雙向依賴注入。

本文是《JBoss Seam:一個深度整合框架》一文的第一部分,JBoss Seam中文站將陸續釋出該文的其他部分。

JBoss Seam的產生背景

軟體框架對於企業級Java開發者來說是非常有用的工具。它們被廣泛地用來組裝可重用的軟體元件和服務。

每個框架都提供了一系列的設計模式、APIs和元件模型——用於構建在框架之上的應用程式。許多受歡迎的Java EE框架的例項,既包括Hibernate、Spring和Struts這樣的開源專案,又包括基於Servlet/JSP、JSF、EJB、 JMS、Web Services等標準實現的產品。

一個典型的企業級Java應用程式,可以同時使用多個框架。所以,Java EE開發者們的主要競爭能力之一,就體現在使用這些框架的能力上。

然而,存在太多框架的缺點在於,每一種框架都提供了不同的程式設計模型(或元件模型)。而要在一個Web應用中使用不同的元件模型,開發人員一般需要寫很多”膠水”程式碼(例如資料傳輸物件、元件管理等)以及”膠水”配置檔案,這樣將會大大地降低開發效率。

在這種背景下,作為”整合框架”的Seam應運而生。Seam的目標就是減少這些”膠水”程式碼,整合現有的各種框架,為企業級應用提供一個一致的程式設計模型。

什麼是整合框架?

Java EE本身就可以被認為是一個整合框架。它定義了不同的框架,如Servlet/JSP、JSF、EJB、JMS、JTA,、JCA等,並使它們在企業級應用中攜手合作。

但是作為標準規範的Java EE由於自身的設計問題,導致發展非常緩慢。新的理念和前沿技術在成為Java EE標準之前,通常都已經作為開源專案出現了。

Spring框架是另一個被廣泛應用的整合框架。Spring對許多現有的框架提供了輕量級的封裝,開發人員可以通過配置XML檔案來管理應用程式 中的元件。但是開發人員仍需要自己混合和匹配多個不同的元件程式設計模型;另外,Spring “大量XML配置”的方式也因為包含太多的”XML程式碼”而變得繁瑣。

Seam是一個開源的”深度整合”框架,它試圖吸收Java EE和Spring世界中的精華為己所用。

Seam牢牢地紮根於Java EE標準:JSF和EJB3。

Seam的最初目標是為了解決JSF和EJB3中的一些設計缺陷。隨後,Seam的許多核心特性被採納為將來的官方Java EE標準,例如JSF 2.0和WebBeans。隨著越來越多的使用者開始採用Seam,它已經遠遠超過Java EE的範疇。

Seam走了一條與早期的Spring框架不同的路。Seam為被它整合的所有框架提供了一個統一的元件模型,開發人員可以使用統一的Seam元件,而不需要學習每個獨立框架的元件管理APIs。

對於開發人員來說,Seam API與被Seam整合的框架相比,有非常大的改進。Seam的註解(annotation)/API設計和Java EE5非常相似。

Seam整合的框架可能成為”幕後工作者”。在某些情況下,你在使用Seam的同時,卻要”奔波”在其它相互競爭的框架之中–與Java EE允許相同的API有多種實現是同樣的方式。

現在,所有關於整合方面的論述都顯示乏味和抽象。下面,我們將通過一些簡單的例子讓你深刻地體會到Seam是如何使開發變得輕鬆容易的。

運用EJB3 Beans或POJOs處理JSF事件

Seam最初引人注目的特性就是直接使用EJB3作為JSF的Backing Beans。

JSF和EJB3都是Java EE的關鍵技術,然而,Java EE卻沒有很好地整合這兩個框架。它們具有不同的元件模型:JSF使用基於POJOs的”Backing Beans”處理UI事件,並且需要進行大量的XML配置;EJB3使用註解型POJOs表示持久層和業務邏輯,只需要簡單的XML配置。

一般情況下,如果要在JSF頁面中進行資料庫操作,需要寫JSF Backing Beans去處理UI事件,然後呼叫EJB3會話Bean中的方法。

因此,如果開發人員需要在Backing Beans和EJB3 Beans之間傳遞複雜的資料,通常需要在這些框架中建立DTOs(資料傳輸物件)。這樣,整合JSF和EJB3框架將成為繁瑣的事情。

在Seam中,你可以直接使用EJB3 Beans作為JSF的Backing Beans。舉個例子,下面的JSF頁面引用一個名為”echo”的Seam元件。當使用者點選Echo按鈕時,頁面將會把輸入變成大寫形式,並顯示在頁面上。

My name is:

Hello #{echo.name}

action=”#{echo.toUpperCase}”/>

如果你還不是很熟悉JSF,下面將介紹一下頁面程式碼是如何工作的:

當伺服器生成頁面的時候,#{echo.name}被替換成echo物件中getName()方法的返回值。當你點選Echo按鈕時,伺服器首先呼叫setName()方法將輸入框的值填入#{echo.name},然後呼叫toUpperCase()方法。

#{…}格式的表示式語言( EL)是Seam程式設計模型中的關鍵元件,因為它不僅可以在網頁中使用,也可以在任何的文字環境中使用,比如XML配置檔案、流程/規則定義、測試指令碼等,我們將在後面介紹這些。

在單純的JSF中,echo元件將被作為JSF的Backing Beans。而在Seam中,我們可以直接使用EJB3 bean(或簡單的POJO)來實現該元件。你只需要通過@Name將元件註解成相應的名字。當存在Web請求時,Seam用”echo”名字建立一個 EchoBean例項,並將所有輸入資料傳遞給它,呼叫相應的方法;最後當響應返回時銷燬這個元件。在這個過程中,你不需要寫XML程式碼或有關物件生命周 期管理的程式碼。

@Stateful

@Name(”echo”)

public class EchoBean implements EchoInt {

private String name;

public String getName () { return name; }

public void setName (String name) { this.name = name; }

public void toUpperCase () { name = name.toUpperCase (); }

@Remove destroy () {}

}

當然,對於這個簡單的應用,EJB顯得有些太臃腫。EJB需要介面、方法和註解。最簡單的方法是寫一個POJO類,然後在這個類上面加上@Name註解就可以了。

@Name(”echo”)

public class EchoPojo {

private String name;

public String getName () { return name; }

public void setName (String name) { this.name = name; }

public void toUpperCase () { name = name.toUpperCase (); }

}

在Seam中,註解POJOs可以完全取代EJB3中的會話Beans,我們將在後面的內容中使用Seam POJOs。

雙向依賴注入

我們將通過一個多元件互動的例子,來領略一下Seam的元件管理能力。

頁面由與實體Bean相聯的輸入框、與POJO相聯的按鈕和由List物件構成的資料表格組成:

Your name:

action=”#{manager.sayHello}”/>

下面是Person實體Bean和管理類POJO:

@Entity

@Name(”person”)

public class Person implements Serializable {

private long id;

private String name;

@Id @GeneratedValue

public long getId() { return id;}

public void setId(long id) { this.id = id; }

public String getName() { return name; }

public void setName(String name) { this.name = name; }

}

@Name(”manager”)

public class Manager {

@In @Out

private Person person;

@Out

private List fans;

@In

private EntityManager em;

public String sayHello () {

em.persist (person);

person = new Person ();

fans = em.createQuery(”select p from Person p”)

.getResultList();

return null;

}

}

在管理類POJO中,當sayHello()方法執行時,person元件被注入(inject);當方法退出時,fans元件被注出(outject)。

同樣地,JPA實體管理類也可以被注入,提供對資料庫的支援。注入和注出(雙向依賴注入)可以在當前頁面請求範圍內同時發生。所以在sayHello()方法使用使用者輸入的#{person.name}值的同時,fans的值也將在結果頁面中顯示。

雙向依賴注入讓我們可以利用簡單的註解來管理元件間的複雜關係。

從整合的角度來看,這個例子過於簡單。Person實體Bean直接聯絡UI元素。實際上,實體Bean僅僅是一個Seam元件,你也可以用它來連線UI行為(例如點選按鈕)。

這樣,不同框架的元件之間的”獨裁統治”將被打破;更遠點說,如果在實體Bean中加入對業務邏輯的支援,就能夠建立包括資料和行為的富領域模型。

富領域模型在OOP中已經被實現,但是在Seam之前,還沒有被Web框架使用。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/13270562/viewspace-244007/,如需轉載,請註明出處,否則將追究法律責任。

相關文章