Java-Android-jwebee
          Java-Android-jwebee
          對IT人來說,要成為一個優(yōu)秀的技術型管理者,除了需要具備扎實的技術基礎之外,還應該培養(yǎng)良好的人際關系能力、談判與溝通技能、客戶關系與咨詢技能、商業(yè)頭腦和財務技能以及創(chuàng)新意識,此外還要有巧妙的激勵技巧和化解沖突與解決突發(fā)問題的能力.

          作者 Costin Leau譯者 胡鍵 發(fā)布于 2008年2月12日 下午11時13分

          社區(qū)
          Java
          主題
          門戶/內(nèi)容管理系統(tǒng)

          保存各種信息對于應用程序來說非常平常,大多數(shù)時候它們是保存在關系數(shù)據(jù)庫中。數(shù)據(jù)庫處理規(guī)范數(shù)據(jù)類型十分在行,但是在處理如圖像、文檔等二進制數(shù)據(jù)時卻不是那么得心應手。盡管可以用文件系統(tǒng)作為替代——而且它們還提供了更好的性能。但它們既沒有提供用于搜索信息的查詢語言,也沒有提供表示關系或事務的概念。

          在很多情況下,允許第三方訪問這些存儲數(shù)據(jù)(隨著應用程序的不斷擴展,這成為一個典型的需求)是一個漫長而復雜的過程(它們不會在一夜之間完成)。內(nèi)部存儲結構很容易影響API架構,以及信息檢索與遍歷的方式。

          什么是JSR-170

          幸運的是,被稱為Java內(nèi)容倉庫(Java Content Repository,JCR)的JSR-170,試圖以獨立于具體實現(xiàn)的方式解決這些(以及其它)問題。即,不論底層資源(如,數(shù)據(jù)庫,本地或虛擬文件系統(tǒng))是什么,API都將相同。在數(shù)據(jù)存儲之上,JCR提供諸如訪問粒度控制、版本控制、內(nèi)容事件、全文檢索和過濾等內(nèi)容服務。由Day Software領導的JSR-170背后的專家組令人印象深刻,包括內(nèi)容管理系統(tǒng)(CMS)提供商Vignette、Hummingbird Ltd.、Stellent和通用Java驅動解決方案提供商,如BEA Systems、IBM和Oracle。該規(guī)范很可能成為內(nèi)容管理和文檔存儲方面事實上的標準。

          經(jīng)過幾乎2年半的努力,工作最終于2005年6月完成,在javax.jcr包中,API包含了大約50個類(主要是接口和異常)。2006年早些時候,發(fā)布了初始1.0版本的參考實現(xiàn)(JackRabbit)。

          JSR-170概覽

          Java內(nèi)容倉庫建立在倉庫(除了是“用于安全地保存貨物的地點”的通常含義之外)概念之上,它提供了幾個操作數(shù)據(jù)的特性。倉庫使用“樹結構”保存信息,如下圖,樹由節(jié)點和屬性組成。圓圈代表節(jié)點,方框代表屬性。1個節(jié)點有且只有1個父親,有任意數(shù)目的孩子(子節(jié)點)和任意數(shù)目的屬性。1個屬性有且只有一個父親(它是節(jié)點),它沒有子節(jié)點,由一個名字和一個或多個值組成。屬性值的類型可以是:布爾(Boolean)、日期(Date)、雙精(Double),長整(Long),字符串(String)或流(Stream)。只有屬性可以被用來存儲信息,節(jié)點則被用來創(chuàng)建樹內(nèi)部的“路徑”。在某種程度上,這棵樹類似文件系統(tǒng)的結構,節(jié)點是目錄,屬性是實際的文件。

          倉庫的功能被劃分為幾個“兼容性”級別,每個級別提供一組特定的特性:

          1. 級別 1

            對于所有實現(xiàn),級別1是必須的,它提供對倉庫的訪問,簡而言之:
            • 對節(jié)點和屬性的讀訪問。
            • 對屬性值的讀訪問。
            • 輸出到XML/SAX。
            • 支持XPATH語法的查詢服務。
          2. 級別 2

            級別2提供功能:
            • 增加和移除節(jié)點和屬性。
            • 對屬性值的寫操作。
            • 從XML/SAX輸入數(shù)據(jù)。

            值得注意的是,JCR的實現(xiàn)并不要求達到級別2或者更高層次。因此與只讀倉庫一起工作也是完全符合規(guī)范的。

          3. 可選級別

            “可選”級別包含一些高級特性,它并不是讀寫倉庫所必需的,但確是真正為JSR-170增色的部分。這個級別包括(除了其它之外):
            • 事務 —— 它使倉庫有可能與JMS或JDBC資源一起工作。
            • 版本標定 —— 允許倉庫記錄節(jié)點的不同狀態(tài),以備日后檢索。規(guī)范對于這個主題有相當?shù)钠辉撎匦允沟糜肑SR-170作為后端構建一個CVS的克隆成為可能。
            • 事件 —— 亦稱觀察,它允許倉庫內(nèi)發(fā)生的任何活動都會被通知給客戶端。
            •  —— 可以凍結部分樹的功能,它可以有效地返回一個只讀的子樹。

          API回顧

          使用JSR-170時,建議使用來自javax.jcr包的接口。這樣,更換JCR實現(xiàn)時會容易些,不會有任何代碼的變動。

          API的核心類是Session,它代表客戶端和倉庫之間的連接,使用連接活躍其上的workspace名和所提供的credentials進行定義。Session包含讀(級別1)和寫(級別2)方法;使用底層倉庫不支持的功能時將拋出異常。

          這個包還包含了那些組成倉庫的單元接口的定義:WorkspaceCredentialsNodePropertyItemNodeProperty的超類)和Valuejavax.jcr.query包負責處理查詢,javax.jcr.nodetype包負責定義節(jié)點類型。剩余的包負責可選級別的功能,如javax.jcr.versionjavax.jcr.observationjavax.jcr.lock。一個有趣的包是javax.jcr.util,它包含一個ItemVisitor的實現(xiàn),它源自GOF(四人幫,Gang of Four)撰寫的著名的設計模式中的訪問者模式(Visitor-pattern)接口。

          JSR-170實現(xiàn)

          GoogleSourceForge會列出好幾頁的JSR-170實現(xiàn),但是它們中的大多數(shù)都處于alpha階段,沒有發(fā)布任何版本。以下是一個可以自由下載的項目列表,它們已經(jīng)被作者使用過:

          • Jackrabbit
            它是JSR-170的參考實現(xiàn),Apache基金的一部分,提供級別1,2和可選功能。在撰寫本文時,它已經(jīng)經(jīng)過孵化階段并有一個官方公開的發(fā)布版本,該版本被認為足夠穩(wěn)定,可以被用在產(chǎn)品環(huán)境。此外,Jackrabbit也被用來作為Day Software(JSR-170的領導者)的商業(yè)產(chǎn)品的基礎。除了實現(xiàn)JSR-170中定義的所有特性,JackRabbit還加入了額外的功能(如SessionListenersCustomNode注冊),以及一個有趣的捐獻來的項目套件,它包括:JCA連接器、taglib、WebDAV接口、虛擬文件系統(tǒng)和JDBC后端。JackRabbit的許可證是Apache 2.0。
          • eXo JCR
            它是eXo platoform的一部分,包含規(guī)范要求的所有強制特性和幾個可選特性。最近一次的版本發(fā)布(1.0RC7)是2006年6月22日,基于規(guī)范的最終草案2。eXo JCR支持JDBC兼容數(shù)據(jù)庫,如MySQL、DB2或HSQL(它是缺省的)作為后端存儲,它是雙許可的(GPL和商用),最終版的發(fā)布日期尚未確定。
          • Jeceira
            與Jackrabbit和eXo JCR相比,它是相對較新的項目。它實現(xiàn)了級別1和2的一些需求,只在寫操作時,支持來自可選級別的觀察功能。不幸的是,這個項目處于未完成階段,在過去的9個月沒有新版本發(fā)布。然而它被Magnolia(一個流行的基于java的CMS,與作為JSR-170參考實現(xiàn)的Jackrabbit類似)使用。在最終版發(fā)布時,它計劃包含所有級別的功能,發(fā)布時間目前尚不確定。Jeceira的許可證是Apache 2.0,使用HSQL數(shù)據(jù)庫作為它的存儲引擎。

          JCR模塊

          Spring Modules的一部分,JCR模塊的主要目標是:以一種類似Spring主分發(fā)包中ORM包的方式,簡化使用JSR-170 API進行開發(fā)。特點如下:

          • JcrTemplate,允許執(zhí)行JcrCallback和異常處理(將需檢查的JCR異常轉換成不需檢查的Spring DAO異常)。這個模板實現(xiàn)了來自JCR Session的絕大部分方法,可以簡單地作為替換物使用。此外該模板知道線程綁定的會話,這個會話可以跨幾個方法使用,這在使用事務型倉庫時非常有用。
          • RepositoryFactoryBean,它配置、啟動和停止倉庫實例。因為JSR-170并沒有說明倉庫配置的標準方式,需要注意實現(xiàn)在這個方面的不同。這個支持包含預定義的用于Jackrabbit和Jeceira的FactoryBean,以及一個可以很容易支持其它倉庫的抽象基類。
          • SessionFactory,用來統(tǒng)一RepositoryCredentialsWorkspace接口,允許自動注冊監(jiān)聽器和自定義名字空間。
          • Spring聲明性事務為那些實現(xiàn)了(可選)事務特性的倉庫提供了支持。
          • OpenSessionInView攔截器和過濾器允許每個線程跨不同組件使用同一會話。與JcrTemplate一起,檢索、關閉和管理JCR會話的工作已經(jīng)外部化,對于調用者完全透明。

          本文將使用參考實現(xiàn)(Jackrabbit),由于JCR模塊使用的是javax.jcr接口,因此改變實現(xiàn)根本就是一個配置的問題。讓我們一步一步地來看看在Jackrabbit之上如何使用Java內(nèi)容倉庫,以及如何讓Spring模塊來幫助完成這一工作。

          配置倉庫和SessionFactory

          <bean id="repository" class="org.springmodules.jcr.jackrabbit.RepositoryFactoryBean">
          <!-- normal factory beans params -->
          <property name="configuration" value="classpath:jackrabbit-repo.xml"/>
          <property name="homeDir" ref="./tmp/repo"/>
          </bean>

          JCR支持提供RepositoryFactoryBean類配置Jackrabbit,它需要JackRabbit的配置文件和主目錄。注意,RepositoryFactoryBean在使用本地文件系統(tǒng)時特別有用;對于服務器環(huán)境,倉庫可能被注冊在JNDI中,此時可以使用JndiObjectFactoryBean幫助類(Spring分發(fā)包的一部分)檢索它:

          <bean id="repository" class="org.springframework.jndi.JndiObjectFactoryBean">
          <property name="jndiName" value="java:comp/env/jcr/myRepository"/>
          </bean>

          或使用Spring 2.0的模式名字空間:

          <jndi:lookup id="entityManagerFactory" jndi-name="jcr/myRepository"/>

          為了簡化與JCR的工作,模塊增加了SessionFactory接口:

          public interface SessionFactory {
          public Session getSession() throws RepositoryException;
          public SessionHolder getSessionHolder(Session session);
          }

          SessionFactory隱藏了實現(xiàn)內(nèi)部的認證細節(jié),因此一旦配置完成,使用同一證書的會話可以很容易的被檢索出來。為了利用實現(xiàn)的特性(沒有涵蓋在規(guī)范中的),這個接口允許檢索SessionHolder。它是一個JCR模塊特定類,主要被用于事務和會話管理(通過一種可用于每個JCR實現(xiàn)的缺省、通用實現(xiàn)),但是它不支持可選特性或自定義特性(如JackrabbitSessionHolder,它支持Jackrabbit的事務基礎結構)。JCR模塊提供一種簡易、透明的方式來發(fā)現(xiàn)SessionHolder實現(xiàn)(這些我將在以后詳細提到),使之很容易地插入對JSR-170其它兼容庫的支持。

          SessionFactory的缺省實現(xiàn)是JcrSessionFactory,它要求一個進行工作的倉庫和證書。

          <!-— SessionFactory -->
          <bean id="jcrSessionFactory" class="org.springmodules.jcr.JcrSessionFactory">
          <property name="repository" ref="repository"/>
          <property name="credentials">
          <bean class="javax.jcr.SimpleCredentials">
          <constructor-arg index="0" value="bogus"/>
          <!-- create the credentials using a bean factory -->
          <constructor-arg index="1">
          <bean factory-bean="password" factory-method="toCharArray"/>
          </constructor-arg>
          </bean>
          </property>
          </bean>

          <!-- create the password to return it as a char[] -->
          <bean id="password" class="java.lang.String">
          <constructor-arg index="0" value="pass"/>
          </bean>

          這個bean聲明非常簡單,唯一需要注意的地方是,密碼被提供給SimpleCredential的構造函數(shù):它只接受字符數(shù)組,使用Spring工廠聲明作為一種變通。

          JcrTemplate

          JcrTemplate是JCR模塊的核心類之一,它提供了與JCR會話一起工作的方便方法,將調用者從必須處理的打開和關閉會話、事務回滾(如果底層倉庫提供)、以及處理其它特性中的異常等工作中解放出來:

          <bean id="jcrTemplate" class="org.springmodules.jcr.JcrTemplate">
              <property name="sessionFactory" ref="jcrSessionFactory"/>
              <property name="allowCreate" value="true"/>
          </bean>

          模板定義非常簡單,類似來自Spring框架的其它模板類,如HibernateTemplate

          例子

          既然倉庫已經(jīng)配置了,接下來看看“Spring化”的例子之一,它來自Jackrabbit的wiki頁:

          public Node importFile(final Node folderNode, final File file, final String mimeType, 
          final String encoding) {

          return (Node) execute(new JcrCallback() {
                     
          /**
          * @see org.springmodules.jcr.JcrCallback#doInJcr(javax.jcr.Session)
          */
          public Object doInJcr(Session session) throws
          RepositoryException, IOException {
            
                 
          JcrConstants jcrConstants = new JcrConstants(session);
                 
          //create the file node - see section 6.7.22.6 of the spec
          Node fileNode = folderNode.addNode(file.getName(),
          jcrConstants.getNT_FILE());
           
          //create the mandatory child node - jcr:content
          Node resNode = fileNode.addNode(jcrConstants.getJCR_CONTENT(),
          jcrConstants.getNT_RESOURCE());
             
               resNode.setProperty(jcrConstants.getJCR_MIMETYPE(), mimeType);
              resNode.setProperty(jcrConstants.getJCR_ENCODING(), encoding);
          resNode.setProperty(jcrConstants.getJCR_DATA(), new FileInputStream(file));
          Calendar lastModified = Calendar.getInstance();
          lastModified.setTimeInMillis (file.lastModified ());
          resNode.setProperty(jcrConstants.getJCR_LASTMODIFIED(), lastModified);
                       
          session.save();
                       
          return resNode;
          }
          });
          }

          主要區(qū)別是:代碼被包裝在一個JCR模板中,它將我們從不得不使用的try/catch語句塊(因為IORepository的需檢查異常)和處理會話(和事務,如果有的話)清除工作中解放出來。值得提及的是硬編碼字符串,如“jcr:data”,是通過JcrConstants工具類解析出來的。它知道名字空間的前綴變化,并提供一種干凈的方式處理JCR常數(shù)。正如你看到的,我只是使例子更加健壯,但是對于實際業(yè)務代碼影響最小。

          事務支持

          使用JCR模塊的一個好處就是能將Spring事務基礎設施(包括聲明性和編程性)應用于Java內(nèi)容倉庫。JSR 170將事務支持視為可選特性,并沒有強制一個標準的方式來暴露事務鉤子,因此每個實現(xiàn)可以選擇不同的方法。在本文撰寫時,只有Jackrabbit支持事務(在它的大部分操作中),它通過為每個JcrSession暴露一個javax.transaction.XAResource做到這一點。JCR模塊提供LocalTransactionManager用于本地事務:

          <bean id="jcrTransactionManager" class="org.springmodules.jcr.jackrabbit.LocalTransactionManager">
          <property name="sessionFactory" ref="jcrSessionFactory"/>
          </bean>

          為了聲明事務劃分,我與上述事務管理器bean聲明一起使用標準Spring類:

          <!-- transaction proxy for Jcr services/facades -->
          <bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
          <property name="proxyTargetClass">
                  <value>true</value>
               </property>

               <property name="transactionManager" ref="jcrTransactionManager"/>
               <property name="transactionAttributes">
               <props>
                  <prop key="save*">PROPAGATION_REQUIRED</prop>
                 <prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
               </props>
               </property>
          </bean>
          <bean id="jcrService" parent="txProxyTemplate">
              <property name="target">
                  <bean class="org.springmodules.examples.jcr.JcrService">
                      <property name="template" ref="jcrTemplate"/>
                  </bean>
              </property>
          </bean>

          如果要求一個JTA管理器,一個簡單而優(yōu)雅的解決辦法是使用來自Jackrabbit捐獻包的jca連接器。為了使用jca,你并不需要一個應用服務器,因為你可以用一個可插入的JCA容器,如Jencks。JCA容器的配置已經(jīng)超出本文的范圍,但是你可以參考JCR模塊例子中使用Jencks的例子。

          TransactionAwareRepository

          對于要求普通JCR代碼的應用程序,JCR模塊允許用直接使用JCR API的代碼,透明地使用事務驅動會話。 此時,可以使用TransactionAwareRepository,它有一個參數(shù)是JcrSessionFactory。這樣,在使用Session.login()(它接收定義在JcrSessionFactory中的參數(shù))創(chuàng)建任何新會話時,如果發(fā)現(xiàn)有線程綁定的會話,就將返回它。注意:如果使用事務,JCR會話就是事務性的,否則你必須手動設置屬性allowNonTxRepository為true,配置如下,要不然將拋出一個異常:

          <bean id="transactionRepository" class="org.springmodules.jcr.TransactionAwareRepository">
               <property name="allowNonTxRepository" value="true"/>
               <property name="targetFactory" ref="jcrSessionFactory"/>
          </bean>

          transactionRepository bean可以被用作一個普通的JCR倉庫,不關心底層機制或線程綁定會話、事務性或非事務性(如果有事務,關閉會話時要提交事務)。

          可選特性支持偵測

          為了最大化代碼重用,但仍然允許插入可選特性,如用于不同JCR實現(xiàn)的事務支持,JCR模塊使用SessionHolder接口(前面已經(jīng)提到),同時還有SessionHolderProviderSessionHolderProviderManager接口。用戶一般不用與它們打交道,因為它們是框架內(nèi)部使用的;但是,它們代表了JCR模塊主要的擴展點。

          SessionHolder類被內(nèi)部不同組件使用,主要被事務管理器用來操作會話,SessionHolderProviderSessionHolderProviderManager處理sessionHolder創(chuàng)建的方式以及提供者是如何被個別使用的。缺省將使用ServiceSessionHolderProviderManager,它利用JDK 1.3 Service Provider的自動發(fā)現(xiàn)特性。管理器將在類路徑中搜索META-INF/services/org.springmodules.jcr.SessionHolderProvider條目,它包含了SessionHolderProvider實現(xiàn)的完整限定名。Jackrabbit支持就是這樣配置的,JCR模塊的分發(fā)包中包含一個META-INF/services/org.springmodules.jcr.SessionHolderProvider(譯注:原文有誤,沒有給出后面的文件名)文件,它只有一行:

          org.springmodules.jcr.jackrabbit.support.JackRabbitSessionHolderProvider

          缺省,SessionHolderProviderManagerJcrSessionFactory內(nèi)部使用,因此在工廠啟動時,任何客戶化實現(xiàn)可以被獲取,并與合適的倉庫一起使用。但是,通過設置JcrSessionFactory中的SessionHolderProviderManager,可以很容易的切換到一個不同的發(fā)現(xiàn)策略。一個可替代的發(fā)現(xiàn)服務是ListSessionHolderProviderManager,它接收一組提供者列表,可以方便地使用自定義提供(如測試)。

          <bean id="listProviderManager" class="org.springmodules.jcr.support.ListSessionHolderProviderManager">
               <property name="providers">
                   <list>
                      <bean class="org.mycompany.jcr.CustomHolderProvider"/>
                      <bean class="org.springmodules.jcr.jackrabbit.support.JackRabbitSessionHolderProvider"/>
                      <bean class="org.springmodules.jcr.support.GenericHolderProvider"/>
                   </list>
               </property
          </bean>

          <bean id="jcrSessionFactory" class="org.springmodules.jcr.JcrSessionFactory">
                  ...
              <property name="sessionHolderProviderManager" ref="listProviderManager"/>
          </bean>

          注意,每個倉庫一個提供者。如果列表包含多個工作于同一倉庫的提供者,順序將非常重要,因為先匹配的先使用。

          Java內(nèi)容倉庫的未來

          盡管JSR-170已經(jīng)于2005年5月完成,Java內(nèi)容倉庫的工作并沒有終止。JSR-283,官方的后繼者,將聚焦于功能增強,如聯(lián)邦,remoting,客戶端/服務器協(xié)議映射和擴展內(nèi)容模型的能力。同時還存在著一些JSR之外的想法和項目:綁定/映射框架,它可以將java類轉換為一個JCR樹,反之亦然(類似ORM,后端用Java內(nèi)容倉庫替代數(shù)據(jù)庫),建構于JCR之上的WebDAV服務器(參見Jackrabbit的捐獻包),以及其他。已經(jīng)出現(xiàn)了用于不同產(chǎn)品的JSR-170連接器,如Alfresco、BEA Portal Server和IBM Domino。

          至于JCR模塊,路線圖包括用于幾個實現(xiàn)的Acegi安全集成,支持Spring 2.0名字空間模式(它將減少XML的配置)和與其它JCR實現(xiàn)集成。很顯然,JCR的看起來一片光明。

          查看英文原文:Integrating Java Content Repository and Spring

          加入書簽
          digg+,
          reddit+,
          del.icio.us+,
          dzone+
          標簽
          Java內(nèi)容倉庫,
          Spring


          jwebee

          我的個人網(wǎng)站
          posted on 2008-02-19 18:12 周行 閱讀(814) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           
          Java-Android-jwebee
          主站蜘蛛池模板: 许昌市| 隆回县| 三台县| 东兰县| 哈尔滨市| 凤冈县| 云南省| 汉源县| 潍坊市| 林口县| 元江| 兴海县| 淮阳县| 安达市| 延安市| 玉林市| 顺平县| 平昌县| 饶阳县| 泸水县| 巴彦淖尔市| 芜湖县| 织金县| 时尚| 五河县| 达州市| 司法| 都安| 门头沟区| 鄱阳县| 濮阳县| 抚州市| 邛崃市| 通山县| 自贡市| 含山县| 左云县| 宜宾县| 宣恩县| 兴安盟| 工布江达县|