無(wú)為

          無(wú)為則可為,無(wú)為則至深!

            BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
            190 Posts :: 291 Stories :: 258 Comments :: 0 Trackbacks

          第一部分: 介紹Web Bean

               我們現(xiàn)在真的臨近發(fā)布一個(gè)Web bean的社區(qū)預(yù)覽草案。該草案的目的是收集關(guān)于我們定義的組件模型,依賴管理模型和擴(kuò)展上下文模型的反饋,希望讓人們對(duì)Web
          Bean感興趣。我們也需要在其他的EE6 相關(guān)專(zhuān)家組的前面開(kāi)展我們的工作,以至于它們可以考慮如何同我們已定義的一些機(jī)制盡可能的重用和集成。然而,該規(guī)范本質(zhì)就
          是用高級(jí)技術(shù)性語(yǔ)言寫(xiě)的,因此在此blog是第一個(gè)以系列文章的友好形式介紹Web bean(也就是說(shuō)我的翻譯是國(guó)人第一份,哈哈。)當(dāng)社區(qū)預(yù)覽草案發(fā)布以后,請(qǐng)花時(shí)
          間下載和審查它。但是請(qǐng)先讀此系列文章。

          歷史回顧

               首先介紹一下背景。Web bean 是由 JBoss 創(chuàng)造的,幫助填平Java EE5的裂隙。EE 5平臺(tái)對(duì)用成熟的技術(shù)包括EJB3,JTA,JCA和JPA來(lái)訪問(wèn)事務(wù)資源提供了極大
          支持。當(dāng)然,此平臺(tái)也以支持廣泛的Web表現(xiàn)技術(shù)例如Java Servlets,JSP和JSF作為特征。然而,Web層和事務(wù)層彼此獨(dú)立發(fā)展,已經(jīng)失去了發(fā)展一個(gè)為訪問(wèn)企業(yè)事務(wù)
          資源的Web應(yīng)用共享的組件模型的機(jī)會(huì)。今天,Web Bean正在以JBoss,Sun,Oracle和Google作為代表,以及一些獨(dú)立成員支持下發(fā)展。組件模型受到Google Guice
          Seam的極大影響。

          Java EE的一個(gè)統(tǒng)一組件模型

          Web bean是一個(gè)同兩層技術(shù)相兼容的組件模型。Web bean同JSF和EJB3集成,允許一個(gè)EJB3會(huì)話bean作為一個(gè)JSF可管理的活動(dòng),因此同這兩個(gè)組件模型兼容。另外,Web bean提供一個(gè)會(huì)話模型和持久化上下文管理,因此解決了影響JSF和JPA的狀態(tài)管理問(wèn)題和優(yōu)化事務(wù)管理問(wèn)題。總而言之,Web bean 使建立通過(guò)JPA訪問(wèn)數(shù)據(jù)庫(kù)的Java EE Web應(yīng)用程序更容易開(kāi)發(fā)。當(dāng)web bean為JSF和EJB3的集成提供一個(gè)輕快實(shí)現(xiàn)時(shí),組件模型變得更通用。特別是,它支持沒(méi)有JSF或沒(méi)有EJB3的情況下的使用。較早提出的一個(gè)問(wèn)題是某種程度上Web bean被限制在EE和EJB3環(huán)境下。專(zhuān)家組無(wú)異議的決定是:

          1. 一個(gè)Web bean不必是一個(gè)EJB;
          2. Web bean應(yīng)該可以在容器外執(zhí)行。

          第一個(gè)決定只認(rèn)識(shí)到不是每一個(gè)組件都需要EJB服務(wù)(例如聲明式事務(wù),授權(quán)等)的事實(shí)。然而,Web bean將不復(fù)制此項(xiàng)功能,所以當(dāng)需要這些服務(wù)時(shí),Web bean需要寫(xiě)成會(huì)話bean。第二個(gè)決定允許組件在應(yīng)用服務(wù)器外面集成或單元測(cè)試,允許代碼級(jí)重用,例如一個(gè)批處理過(guò)程。

          一些會(huì)員,尤其Bob Lee,認(rèn)為我們已做的工作只是在EE平臺(tái)外面有用,并且特別是組件模型應(yīng)考慮Java SE中的使用。然而,作為規(guī)范領(lǐng)導(dǎo)和根據(jù)我們JSR提議的語(yǔ)言,我做出決定清晰的指定目標(biāo)環(huán)境是Java EE,限制我們的爭(zhēng)論在EE開(kāi)發(fā)者需要什么。

          如果將來(lái),有來(lái)自社區(qū)和JCP的壓力開(kāi)放Web bean的一部分(例如高級(jí)Guice樣式依賴注入引擎)的話,我們能夠在那時(shí)跟從在EJB3專(zhuān)家組有JPA建立的先例,定義EE平臺(tái)以外的行為。

          Web bean 組件

          精確地說(shuō)一個(gè)Web bean是什么?

          一個(gè)Web bean是一個(gè)包含業(yè)務(wù)邏輯的應(yīng)用組件。一個(gè)Web bean可以從Java 代碼中被調(diào)用,或者通過(guò)統(tǒng)一了的EL調(diào)用。一個(gè)Web bean 可以訪問(wèn)事務(wù)資源。兩個(gè)Web bean的依賴由Web bean容器自動(dòng)管理。大多數(shù)Web Bean是有狀態(tài)和上下文的。一個(gè)Web bean的生命周期總是由容器管理。讓我們稍微回顧一下。它對(duì)于上下文意味著什么呢?因?yàn)閃eb bean是有狀態(tài)的,所以它同我有哪一個(gè)bean實(shí)例有關(guān)。同一個(gè)無(wú)狀態(tài)組件模型(無(wú)狀態(tài)會(huì)話bean)或者單例組件模型(例如serlets)不一樣,一個(gè)組件的不同客戶端看到組件的不同狀態(tài)。客戶端可見(jiàn)狀態(tài)依賴于客戶端有哪一個(gè)組件實(shí)例的引用。

          然而,象一個(gè)無(wú)狀態(tài)會(huì)話bean或單例模型一樣,象JSF,但是與有狀態(tài)會(huì)話bean不一樣,客戶端不通過(guò)顯式創(chuàng)建和破壞它來(lái)控制實(shí)例的生命周期。作為代替,一個(gè)上下文定義:

          • 實(shí)力的生命周期
          • 此實(shí)例對(duì)于客戶端的可見(jiàn)作用域

          所以在相同作用域執(zhí)行的客戶端(例如其它Web bean)將看到同一實(shí)例。但是,在不同作用域的客戶端將看到不同實(shí)例。上下文模型一個(gè)很大的優(yōu)勢(shì)是它允許象創(chuàng)建服務(wù)一樣創(chuàng)建有狀態(tài)組件。客戶端不需要它使用的管理的組件生命周期關(guān)注它自己,也不需要知道生命周期是什么。組件通過(guò)傳送消息交互,組件實(shí)現(xiàn)定義了它們自己狀態(tài)的生命周期。之所以此組件是松散耦合的,是因?yàn)椋?

          • 它們通過(guò)定義良好的公共API交互
          • 它們的生命周期完全被解耦

          我們能夠用實(shí)現(xiàn)相同API和有一個(gè)不影響其它組件實(shí)現(xiàn)的不同生命周期的另一個(gè)不同組件替代組件。實(shí)際上,Web bean為在足夠人工攔截的重寫(xiě)組件實(shí)現(xiàn)定義了一個(gè)部署時(shí)的高級(jí)功能,這將在我們將來(lái)安裝時(shí)看到。更正規(guī)的是,根據(jù)該規(guī)范:

          一個(gè)Web bean組件包括:
          • 組件類(lèi)型
          • 或這是一個(gè)bean實(shí)現(xiàn)類(lèi)或者是解析方法
          • 一系列的API類(lèi)型
          • 一系列(可能為空)的綁定批注類(lèi)型
          • 作用域
          • 組件名

          讓我們看一看這些條目對(duì)于組建開(kāi)發(fā)者來(lái)說(shuō)意味著什么。

          組件類(lèi)型

          我們現(xiàn)在關(guān)于組件類(lèi)型所需要知道的是一個(gè)Web bean開(kāi)發(fā)者可能定義一些享元作為批注,例如允許全部組件集合在特定系統(tǒng)部署中有條件的安裝的@Mock, @Staging 或者 @AustralianTaxLaw。我們?cè)诤笠还?jié)中的更多討論這個(gè)獨(dú)一無(wú)二的強(qiáng)大功能。

          一個(gè)非常簡(jiǎn)單的Web bean可能僅使用內(nèi)置的組件類(lèi)型@Component:

          @Component
          public class Credentials { ... }

          組件前場(chǎng)景類(lèi)型批注識(shí)別此類(lèi)作為一個(gè)Web bean到Web bean容器中。

          API 類(lèi)型,綁定批注和依賴注入

          Web bean通常通過(guò)依賴注入獲得對(duì)于其它Web bean的引用。任何注入型參數(shù)指定一個(gè)組件必須滿足的契約。契約為:

          • 一個(gè)API
          • 一個(gè) (可能為空)綁定批注集合

          一個(gè)API是用戶定義類(lèi)或者接口。(如果組件是一個(gè)EJB會(huì)話bean,那么此API類(lèi)型是@Local接口。)一個(gè)綁定批注是一個(gè)本身用@BindingType注解的用戶定義批注。容器搜索滿足契約(實(shí)現(xiàn)此API和支持綁定批注)的組件,注入那個(gè)組件。例如,如果這個(gè)是注入點(diǎn):

          @In @CreditCard PaymentProcessor paymentProcessor;

          以下組件將被注入:

          @CreditCard @Component
          public class CreditCardPaymentProcessor
          implements PaymentProcessor { ... }

          Web bean定一個(gè)高級(jí)但是直接解析算法,它幫助容器決定如果超過(guò)一個(gè)組件滿足一個(gè)指定契約的話將做什么。我們將在以后文章中詳細(xì)介紹。

          組件作用域

          作用域定義組件實(shí)例的生命周期和可見(jiàn)性。Web bean上下文模型是可擴(kuò)展的,The scope defines the lifecycle and visibility of instances of the component. The Web Beans context model is extensible, 包含模糊作用域。然而,對(duì)于規(guī)范來(lái)說(shuō)某個(gè)重要的作用域是內(nèi)置的,有Web bean容器來(lái)提供。例如,任何Web 應(yīng)用程序都可訪問(wèn)一個(gè)會(huì)話作用域:

          @SessionScoped @Component
          public class ShoppingCart { ... }

          我們將在以后文章中詳細(xì)介紹作用域。

          組件名和統(tǒng)一表達(dá)式語(yǔ)言(EL)

          所有Web bean可以通過(guò)名字在統(tǒng)一EL表達(dá)式中使用。自定制一個(gè)Web bean名字是很容易的:

          @SessionScoped @Component @Named("cart")
          public class ShoppingCart { ... }

          到那時(shí)我們能很容易在JSF頁(yè)使用此組件:

          <h:dataTable value="#{cart.lineItems}" var="item">
          ....
          </h:dataTable>

          解析方法和web-beans.xml文件

          大多數(shù)Web bean通過(guò)寫(xiě)一個(gè)實(shí)現(xiàn)類(lèi)和注解它來(lái)定義。然而,有另外兩種定義一個(gè)Web bean的方式:

          1. 通過(guò)一個(gè)XML部署描述文件web-beans.xml
          2. 通過(guò)寫(xiě)一個(gè)解析方法

          我們?cè)趯?lái)的文章中介紹web-beans.xml文件。

          一個(gè)解析方法是一在當(dāng)前上下文中沒(méi)有實(shí)例存在時(shí)由容器調(diào)用它來(lái)獲得一個(gè)組件實(shí)例的方法。例如:

          @SessionScoped @Component
          public class Login {
          User user;
          ...
          public void login() {
          user = ...;
          }
          @Resolves @LoggedIn User getCurrentUser() {
          return user;
          }
          }

          一個(gè)解析方法是第一個(gè)類(lèi)Web bean組件。再一次的告訴大家,后面章節(jié)繼續(xù)介紹它。

          登錄

          讓我們通過(guò)梳理以下前面的例子來(lái)描述一下這些觀點(diǎn)。我們將實(shí)現(xiàn)用戶登錄/注出。首先我們將定義一個(gè)組件包含用戶名和密碼,這些將在登錄過(guò)程中用到:

          @Component
          public class Credentials {
          private String username;
          private String password;
          public String getUsername() { return username; }
          public void setUsername(String username) { this.username = username; }
          public String getPassword() { return password; }
          public void setPassword(String password) { this.password = password; }
          }

          此組件綁定到登錄在以下JSF表格的提示符下:

          <f:form>
          <h:panelGrid columns="2" rendered="#{!login.isLoggedIn}">
          <h:outputLabel for="username">Username:</h:outputLabel>
          <h:inputText id="username" value="#{credentials.username}"/>
          <h:outputLabel for="password">Password:</h:outputLabel>
          <h:inputText id="password" value="#{credentials.password}"/>
          </h:panelGrid>
          <h:commandButton action="#{login.login}" rendered="#{!login.isLoggedIn}"/>
          <h:commandButton acion="#{login.logout}" rendered="#{login.isLoggedIn}"/>
          </f:form>

          實(shí)際工作由一個(gè)維護(hù)關(guān)于當(dāng)前進(jìn)入的用戶信息和向其他組件暴露用戶實(shí)體的會(huì)話作用域組件去做:

          @SessionScoped @Component
          public class Login {
          @In Credentials credentials;
          @In @UserDatabase EntityManager userDatabase;
          private User user;
          public void login() {
          List<User> results = userDatabase.createQuery(
          "select u from User u where u.username=:username and u.password=:password")
          .setParameter("username", credentials.getUserName())
          .setParameter("password", credentials.getPassword())
          .getResultList();
          if ( !results.isEmpty() ) {
          user = results.get(0);
          }
          }
          public void logout() {
          user = null;
          }
          public boolean isLoggedIn() {
          return user!=null;
          }
          @Resolves @LoggedIn User getCurrentUser() {
          return user;
          }
          }

          當(dāng)然,@LoggedIn是一個(gè)綁定批注:

          @Retention(RUNTIME)
          @Target({TYPE, METHOD, FIELD})
          @BindingType
          public @interface LoggedIn {}

          現(xiàn)在,任何其它的組件能夠很容易注入當(dāng)前用戶:

          @Component
          public class DocumentEditor {
          @In @Current Document document;
          @In @LoggedIn User currentUser;
          @In @DocumentDatabase EntityManager docDatabase;
          public void save() {
          document.setCreatedBy(currentUser);
          docDatabase.persist(document);
          }
          }

          大家繼續(xù)關(guān)注我啊!

          希望這篇文章為您理解Web bean組件模型提供幫助。有更多的東西需要討論,我希望您將有時(shí)間看一看此系列文章的剩余部分。 

          ——————來(lái)自牛哄哄的Hibernate之父 Gavin King

          凡是有該標(biāo)志的文章,都是該blog博主Caoer(草兒)原創(chuàng),凡是索引、收藏
          、轉(zhuǎn)載請(qǐng)注明來(lái)處和原文作者。非常感謝。

          posted on 2007-09-23 08:56 草兒 閱讀(1594) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): JAVA WEB應(yīng)用
          主站蜘蛛池模板: 文安县| 江西省| 锦州市| 葫芦岛市| 商河县| 阿鲁科尔沁旗| 钦州市| 灵丘县| 邛崃市| 余江县| 芷江| 舟曲县| 贵州省| 曲水县| 祁门县| 渝中区| 乐都县| 甘南县| 宝丰县| 乌恰县| 盈江县| 米林县| 三穗县| 托里县| 秦皇岛市| 南投县| 江孜县| 泾川县| 剑阁县| 谷城县| 乌兰浩特市| 诸城市| 茂名市| 芜湖县| 正阳县| 普陀区| 沙湾县| 佛教| 太白县| 洛南县| 若羌县|