無為

          無為則可為,無為則至深!

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

          第一部分: 介紹Web Bean

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

          歷史回顧

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

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

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

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

          第一個決定只認識到不是每一個組件都需要EJB服務(例如聲明式事務,授權(quán)等)的事實。然而,Web bean將不復制此項功能,所以當需要這些服務時,Web bean需要寫成會話bean。第二個決定允許組件在應用服務器外面集成或單元測試,允許代碼級重用,例如一個批處理過程。

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

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

          Web bean 組件

          精確地說一個Web bean是什么?

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

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

          • 實力的生命周期
          • 此實例對于客戶端的可見作用域

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

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

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

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

          讓我們看一看這些條目對于組建開發(fā)者來說意味著什么。

          組件類型

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

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

          @Component
          public class Credentials { ... }

          組件前場景類型批注識別此類作為一個Web bean到Web bean容器中。

          API 類型,綁定批注和依賴注入

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

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

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

          @In @CreditCard PaymentProcessor paymentProcessor;

          以下組件將被注入:

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

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

          組件作用域

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

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

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

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

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

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

          到那時我們能很容易在JSF頁使用此組件:

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

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

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

          1. 通過一個XML部署描述文件web-beans.xml
          2. 通過寫一個解析方法

          我們在將來的文章中介紹web-beans.xml文件。

          一個解析方法是一在當前上下文中沒有實例存在時由容器調(diào)用它來獲得一個組件實例的方法。例如:

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

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

          登錄

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

          @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>

          實際工作由一個維護關于當前進入的用戶信息和向其他組件暴露用戶實體的會話作用域組件去做:

          @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;
          }
          }

          當然,@LoggedIn是一個綁定批注:

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

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

          @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ù)關注我啊!

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

          ——————來自牛哄哄的Hibernate之父 Gavin King

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

          posted on 2007-09-23 08:56 草兒 閱讀(1593) 評論(0)  編輯  收藏 所屬分類: JAVA WEB應用
          主站蜘蛛池模板: 菏泽市| 湖口县| 田阳县| 九龙坡区| 特克斯县| 芦溪县| 旌德县| 剑川县| 南丹县| 丽江市| 贺兰县| 抚松县| 静海县| 剑川县| 临桂县| 六安市| 天气| 太保市| 绥阳县| 镇坪县| 许昌县| 西丰县| 马公市| 高密市| 景谷| 灵丘县| 北海市| 泰和县| 综艺| 农安县| 上林县| 盘锦市| 六盘水市| 淳安县| 长沙市| 扎囊县| 永宁县| 同德县| 天镇县| 阿合奇县| 林周县|