Java 內(nèi)容管理系統(tǒng) JSR-170_第1頁(yè)
Java 內(nèi)容管理系統(tǒng) JSR-170_第2頁(yè)
Java 內(nèi)容管理系統(tǒng) JSR-170_第3頁(yè)
Java 內(nèi)容管理系統(tǒng) JSR-170_第4頁(yè)
Java 內(nèi)容管理系統(tǒng) JSR-170_第5頁(yè)
已閱讀5頁(yè),還剩11頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Java Content Repository API 簡(jiǎn)介學(xué)習(xí) JSR-170 如何使構(gòu)建 CMA 變得輕而易舉Titus Barik (), 高級(jí)程序員,分析師, SoloFX Enterprises, LLC簡(jiǎn)介: 隨著內(nèi)容管理應(yīng)用程序的日益普及,對(duì)于公共的、標(biāo)準(zhǔn)的內(nèi)容倉(cāng)庫(kù) API 的需求也變得漸漸明顯起來(lái)。Content Repository for Java Technology API(JSR-170)的目標(biāo)就是提供這樣一個(gè)接口。在這篇文章中,我將用開放源碼的 JSR-170 實(shí)現(xiàn) Apache Jackrabbit,設(shè)計(jì)一個(gè)簡(jiǎn)單的類似維京百科全書的后端

2、,研究這個(gè)前途遠(yuǎn)大的框架所提供的特性。標(biāo)記本文!發(fā)布日期: 2006 年 8 月 04 日 (最初發(fā)布 2005 年 8 月 23 日) 級(jí)別: 高級(jí) 訪問(wèn)情況 : 6929 次瀏覽 評(píng)論: 0 (查看 | 添加評(píng)論 - 登錄) 平均分 (12個(gè)評(píng)分)為本文評(píng)分如果曾經(jīng)試過(guò)開發(fā)內(nèi)容管理應(yīng)用程序,那么您應(yīng)當(dāng)非常清楚在實(shí)現(xiàn)內(nèi)容系統(tǒng)時(shí)所遇到的固有難題。這個(gè)領(lǐng)地有點(diǎn)支離破碎,許多供應(yīng)商都有自己的私有倉(cāng)庫(kù)引擎。這些困難惡化了這類系統(tǒng)的復(fù)雜性和可維護(hù)性、增強(qiáng)了廠商鎖定、增加了企業(yè)市場(chǎng)中對(duì)傳統(tǒng)系統(tǒng)長(zhǎng)期支持的需要。隨著企業(yè) weblog 和電子企業(yè)文檔管理的日益流行,對(duì)標(biāo)準(zhǔn)化內(nèi)容倉(cāng)庫(kù)接口的需求比以往任何時(shí)候都

3、更加顯著。Content Repository for Java Technology 規(guī)范是在 Java Community Process 中作為 JSR-170 開發(fā)的,它的目標(biāo)是滿足這些行業(yè)的需求。該規(guī)范在 javax.jcr 名稱空間中提供了統(tǒng)一的 API ,允許以廠商中立的方式訪問(wèn)任何符合規(guī)范的倉(cāng)庫(kù)實(shí)現(xiàn)。但是 API 標(biāo)準(zhǔn)化并不是 Java Content Repository(JCR)帶來(lái)的惟一特性。JSR-170 的一個(gè)主要優(yōu)勢(shì)就是沒有捆綁到任何特定的底層架構(gòu)上。例如,JSR-170 實(shí)現(xiàn)的后端數(shù)據(jù)存儲(chǔ)可以是文件系統(tǒng)、WebDAV 倉(cāng)庫(kù)、XML 支持的系統(tǒng)或者是 SQL 數(shù)據(jù)庫(kù)

4、。而且,JSR-170 的導(dǎo)出和導(dǎo)入功能允許集成人員在后端內(nèi)容和 JCR 實(shí)現(xiàn)之間無(wú)縫地切換。最后,JCR 提供了簡(jiǎn)單的接口,可以將該接口放在各種現(xiàn)有的內(nèi)容倉(cāng)庫(kù)之上,并同時(shí)標(biāo)準(zhǔn)化一些復(fù)雜的功能(例如版本管理、訪問(wèn)控制和搜索)。在討論 JCR 時(shí),有幾種方式可以采用。在這篇文章中,我從開發(fā)人員的角度來(lái)研究 JSR-170 規(guī)范所提供的特性,重點(diǎn)放在可用的 API 和接口上,這些接口允許程序員在設(shè)計(jì)內(nèi)容應(yīng)用程序時(shí)有效利用 JSR-170 倉(cāng)庫(kù)。作為一個(gè)假設(shè)的示例,我將為一個(gè)類似維京百科全書的、叫做 JCRWiki 的系統(tǒng)實(shí)現(xiàn)一個(gè)小小的后端,為二進(jìn)制內(nèi)容、版本管理、備份和搜索提供支持。我使用 Apa

5、che Jackrabbit(JSR-170 的開源實(shí)現(xiàn))開發(fā)這個(gè)應(yīng)用程序。倉(cāng)庫(kù)模型我先從對(duì)倉(cāng)庫(kù)模型的高級(jí)討論開始,以便讓您熟悉 JCR。倉(cāng)庫(kù)模型是簡(jiǎn)單的層次結(jié)構(gòu),看起來(lái)就像一個(gè)有 n 個(gè)分叉的樹。它由單一內(nèi)容倉(cāng)庫(kù)構(gòu)成,有一個(gè)或多個(gè)工作區(qū)。(這篇文章中的討論僅限制于單一工作區(qū)。)每個(gè)工作區(qū)都包含一個(gè)項(xiàng)目 樹;項(xiàng)目既可以是節(jié)點(diǎn)也可以是屬性。節(jié)點(diǎn)可以有零個(gè)或多個(gè)子節(jié)點(diǎn)以及零個(gè)或多個(gè)相關(guān)屬性,實(shí)際的內(nèi)容保存在子節(jié)點(diǎn)和屬性中。每個(gè)節(jié)點(diǎn)都有且只有一個(gè)主節(jié)點(diǎn)類型。主節(jié)點(diǎn)類型定義了節(jié)點(diǎn)的特征,例如允許節(jié)點(diǎn)擁有的屬性和子節(jié)點(diǎn)。除了主節(jié)點(diǎn)類型之外,節(jié)點(diǎn)還可以有一個(gè)或多個(gè)混合(mixin)類型?;旌项愋透裥揎椘?/p>

6、,向節(jié)點(diǎn)提供額外的特征。具體來(lái)說(shuō),JCR 實(shí)現(xiàn)可以提供三種預(yù)定義混合類型: mix:versionable:允許節(jié)點(diǎn)支持版本管理 mix:lockable:支持節(jié)點(diǎn)的鎖定功能 mix:referenceable:提供自動(dòng)創(chuàng)建的 jcr:uuid 屬性,給節(jié)點(diǎn)一個(gè)惟一可以引用的標(biāo)識(shí)符這個(gè)結(jié)構(gòu)如圖 1 所示。圓圈代表節(jié)點(diǎn),矩形代表屬性。請(qǐng)參見節(jié)點(diǎn) A、B 和 C,它們都衍生自一個(gè)根節(jié)點(diǎn)。節(jié)點(diǎn) A 有兩個(gè)屬性,即一個(gè)字符串 “John” 和一個(gè)整數(shù) 22。圖 1. 有多個(gè)工作區(qū)的倉(cāng)庫(kù)模型 預(yù)定義的節(jié)點(diǎn)類型每個(gè)倉(cāng)庫(kù)都必須支持主節(jié)點(diǎn)類型 nt:base。倉(cāng)庫(kù)還可以支持其他許多公共節(jié)點(diǎn)類型: nt:uns

7、tructured 是最靈活的節(jié)點(diǎn)類型。它允許使用任意數(shù)量的子節(jié)點(diǎn)或?qū)傩?,并且可以使用任意名稱。這個(gè)節(jié)點(diǎn)類型表示 JCRWiki 的條目。 nt:file 表示文件。它需要一個(gè)叫做 jcr:content 的單一子節(jié)點(diǎn)。這個(gè)節(jié)點(diǎn)類型表示 JCRWiki 條目中的圖片和其他二進(jìn)制內(nèi)容。 nt:folder 節(jié)點(diǎn)類型可以表示文件夾,就像常規(guī)的文件系統(tǒng)中的文件夾一樣。 nt:resource 通常表示文件的實(shí)際內(nèi)容。 nt:version 是支持版本管理的倉(cāng)庫(kù)所必需的節(jié)點(diǎn)類型。整個(gè)節(jié)點(diǎn)類型的結(jié)構(gòu)可以在 JSR-170 規(guī)范的 小節(jié)找到(請(qǐng)參閱 參考資料 獲得鏈接)。名稱空間倉(cāng)庫(kù)模型

8、一個(gè)有用的卻經(jīng)常被忽視的特性就是它對(duì)名稱空間 的支持。名稱空間防止不同來(lái)源和不同應(yīng)用程序域之間的項(xiàng)目和節(jié)點(diǎn)類型的命名沖突。名稱空間被定義為帶有一個(gè)前綴,中間用一個(gè) : (冒號(hào))分隔。在這篇文章的教程中,已經(jīng)遇到了一些名稱空間:jcr用于 JCR 的內(nèi)部屬性,mix 用于混合類型,nt 用于節(jié)點(diǎn)類型。在 JCRWiki 中,所有的數(shù)據(jù)都將使用 wiki 名稱空間?;仨?yè)首安裝 JCR在編寫這篇文章的時(shí)候,Apache Jackrabbit(即 Apache 基金會(huì)的 JSR-170 的開源實(shí)現(xiàn))的發(fā)行版已經(jīng)到了版本 1.0。編譯好的字節(jié)碼 JAR 可以直接從 Jackrabbit Web 站點(diǎn)下載

9、(請(qǐng)參閱 參考資料)。雖然 Jackrabbit can 仍然可以用 SVN 從源代碼進(jìn)行編譯,但是 Jackrabbit 庫(kù)已經(jīng)非常穩(wěn)定,不再需要每夜構(gòu)建(nightly builds)技術(shù)。這一節(jié)將提供盡可能快地安裝 JCR 實(shí)現(xiàn)并運(yùn)行它的詳細(xì)說(shuō)明。需要的庫(kù)要使用和運(yùn)行這篇文章中的示例,請(qǐng)將下面這些庫(kù)放在類路徑中: jackrabbit-core:針對(duì) JSR-170 的 Jackrabbit 內(nèi)容倉(cāng)庫(kù)核心實(shí)現(xiàn)和來(lái)自 Apache 的公共實(shí)用代碼。 commons-collections:包含強(qiáng)大數(shù)據(jù)結(jié)構(gòu)的框架,該框架可以加快 Java 應(yīng)用程序的開發(fā)。 concurrent:這個(gè)庫(kù)提供通

10、常在 Java 并發(fā)編程中會(huì)遇到的工具類的標(biāo)準(zhǔn)化的、有效率的版本。 derby:一個(gè) Apache 數(shù)據(jù)庫(kù)子項(xiàng)目,它提供完全用 Java 語(yǔ)言實(shí)現(xiàn)的關(guān)系數(shù)據(jù)庫(kù)。 jcr:一組符合 JSR-170 規(guī)范的接口。 log4j:運(yùn)行時(shí)日志庫(kù)。 lucene:高性能的全功能文本搜索引擎庫(kù)。 slf4j (針對(duì) Java 的簡(jiǎn)單日志 Facade):目的是充當(dāng)不同日志 API 的簡(jiǎn)單 facade,允許用戶在部署時(shí)插入需要的實(shí)現(xiàn)。 xerces:高級(jí) XML 解析器,支持 SAX 版本 2、DOM 1 級(jí)和 SAX 版本 1 API。如果用 SVN 構(gòu)建 Jackrabbit,那么所有這些 JAR 文件

11、都會(huì)在 Jackrabbit 構(gòu)建過(guò)程中被下載,并位于 Maven 的緩存目錄中。在 Linux 下,這些 JAR 位于主目錄的 .maven 目錄下。如果使用二進(jìn)制構(gòu)建,那么只需要從它們各自的 Web 站點(diǎn)下載其二進(jìn)制版或?yàn)g覽 Jackrabbit Web 站點(diǎn)的 “First Hops with Jackrabbit” 即可,那里會(huì)提供到所有這些資源的直接鏈接。在 JSR-170 規(guī)范的下載中還有一個(gè) jcr-1.0.jar,在 Java 社區(qū)進(jìn)程的 Web 站點(diǎn)上也可以找到它?;仨?yè)首手工配置JSR-170 沒有確切地指定應(yīng)當(dāng)如何獲得初始的 Repository 對(duì)象;這被留作每個(gè)倉(cāng)庫(kù)廠商

12、的實(shí)現(xiàn)細(xì)節(jié)。但是,在應(yīng)用程序中最好使用 JNDI 或其他容器環(huán)境中的配置機(jī)制,這樣可以保持 JSR-170 的實(shí)現(xiàn)相對(duì)獨(dú)立于對(duì) Jackrabbit 的直接依賴項(xiàng)。雖然這一策略在初始配置期間造成了額外的復(fù)雜性,但它提供了跨不同 JSR-170 實(shí)現(xiàn)的更好的移植性。要想獲得一個(gè)移植性雖然差但得到了簡(jiǎn)化的配置,可以使用自動(dòng)配置,詳細(xì)內(nèi)容在這篇文章后面部分介紹。在手工配置中,可以將 JNDI 與配置文件(叫做 repository.xml,以編程方式載入)結(jié)合使用來(lái)得到倉(cāng)庫(kù)。倉(cāng)庫(kù)配置第一步,也是最容易的一步,就是為 Jackrabbit 創(chuàng)建 repository.xml 文件。這個(gè)配置文件實(shí)現(xiàn)了許

13、多重要任務(wù)。這些任務(wù)包括:指定底層的后端存儲(chǔ)、訪問(wèn)控制機(jī)制、可用的工作區(qū)、版本管理系統(tǒng)和搜索子系統(tǒng)。清單 1 提供了一個(gè)示例:清單 1. 示例 repository.xml 配置文件 這個(gè)配置使用本地文件系統(tǒng)來(lái)保存?zhèn)}庫(kù)數(shù)據(jù),用 SimpleAccessManager 進(jìn)行訪問(wèn)控制。文件剩下的部分基本是自解釋的,將它們?cè)瓨訌?fù)制到自己的倉(cāng)庫(kù)目錄中即可。安全性配置使用 JASS 配置文件 jaas.config(存放在項(xiàng)目的根目錄中),可以提供初步的安全性。清單 2 提供了一個(gè)示例:清單 2. 示例 JAAS 配置Jackrabbit org.apache.jackrabbit.core.secur

14、ity.SimpleLoginModule required anonymousId=anonymous;倉(cāng)庫(kù)初始化代碼清單 3 描述的包可在初始化倉(cāng)庫(kù)時(shí)使用:清單 3. 手工配置的初始化 import 語(yǔ)句import org.apache.jackrabbit.core.jndi.RegistryHelper;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import javax.jcr.*;import javax.jcr.query.*

15、;import javax.jcr.version.*;import java.util.Hashtable;import java.util.Calendar;import java.io.*;import .www.MimeTable;要得到 Repository 對(duì)象,請(qǐng)將 configFile 變量設(shè)置成指向 repository.xml 文件,將 repHomeDir 變量設(shè)置成指向倉(cāng)庫(kù)所在的本地文件系統(tǒng)目錄。當(dāng)結(jié)合 RegistryHelper 使用 JNDI 時(shí),獲得倉(cāng)庫(kù)非常簡(jiǎn)單,如清單 4 所示:清單 4. 用 JNDI 獲得 repository 對(duì)象Strin

16、g configFile = repository.xml;String repHomeDir = repository;Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, org.apache.jackrabbit.core.jndi + .provider.DummyInitialContextFactory);env.put(Context.PROVIDER_URL, localhost);InitialContext ctx = new InitialContext(env);Registr

17、yHelper.registerRepository(ctx, repo, configFile, repHomeDir, true);Repository r = (Repository) ctx.lookup(repo);接下來(lái),用 SimpleCredentials 獲得 Session 對(duì)象。在這個(gè)實(shí)現(xiàn)中,SimpleCredentials 接受所有用戶名。替代的 JCR 實(shí)現(xiàn)可以提供更復(fù)雜的認(rèn)證機(jī)制,可以連接到 LDAP 服務(wù)器或外部數(shù)據(jù)庫(kù)來(lái)提供憑據(jù)信息。(身份驗(yàn)證和訪問(wèn)控制的完整功能超出了本文的范圍。要獲得有關(guān)的更多信息,請(qǐng)參閱 JSR-170 規(guī)范的 6.9 小節(jié)。)Sessio

18、n 對(duì)象為程序員提供了一個(gè)臨時(shí)的存儲(chǔ)層,它非常像傳統(tǒng)的對(duì)象關(guān)系映射工具中可以看到的層,而且還可以將它看作到特定工作區(qū)的連接。它允許客戶訪問(wèn)綁定到這個(gè)會(huì)話的任何節(jié)點(diǎn)或?qū)傩?。通過(guò)會(huì)話,可以得到工作區(qū),再?gòu)墓ぷ鲄^(qū)得到根節(jié)點(diǎn)。所有這些步驟都是在清單 5 的簡(jiǎn)短代碼片段中完成的:清單 5. 獲得工作區(qū)和根節(jié)點(diǎn)SimpleCredentials cred = new SimpleCredentials(userid, .toCharArray();Session session = r.login(cred, null);Workspace ws = session.getWorkspace();Node

19、 rn = session.getRootNode();使用會(huì)話、工作區(qū)和根節(jié)點(diǎn)引用,現(xiàn)在可以通過(guò)不同的抽象層訪問(wèn)倉(cāng)庫(kù)的特性。最后,為了驗(yàn)證倉(cāng)庫(kù)已經(jīng)成功獲得初始化,可以用rn.getPrimaryNodeType().getName() 輸出根節(jié)點(diǎn)的名稱。這應(yīng)當(dāng)形成以下輸出:rep:root因?yàn)檎谑褂?JAAS,所以請(qǐng)記得將 -Djava.security.auth.login.config=jaas.config. 以 Java JVM 參數(shù)的形式包含進(jìn)來(lái)。JCRWiki 名稱空間在這個(gè)練習(xí)中,所有的 JCRWiki 內(nèi)容都放在 wiki 名稱空間下。為了讓倉(cāng)庫(kù)識(shí)別這個(gè)名稱空間,必須在初始

20、化時(shí)注冊(cè)名稱空間,如下所示:ws.getNamespaceRegistry()。registerNamespace (wiki, /wiki/1.0);恭喜!倉(cāng)庫(kù)的手工配置現(xiàn)在完成了?;仨?yè)首自動(dòng)配置Jackrabbit 實(shí)現(xiàn)還提供了一個(gè) TransientRepository 類,這個(gè)類來(lái)自其核心 API,可以在啟動(dòng)第一個(gè)會(huì)話時(shí)自動(dòng)初始化內(nèi)容倉(cāng)庫(kù),并在最后一個(gè)會(huì)話關(guān)閉時(shí)停止使用倉(cāng)庫(kù)。對(duì)于簡(jiǎn)單的獨(dú)立應(yīng)用程序,使用 TransientRepository 可以極大地簡(jiǎn)化倉(cāng)庫(kù)的配置,但要以 JSR-170 的移植性作為代價(jià)。TransientRepository

21、 自動(dòng)創(chuàng)建 repository.xml 和倉(cāng)庫(kù)文件夾。它還在內(nèi)部提供了處理身份驗(yàn)證和安全性的 SimpleAccessManager。自動(dòng)配置需要使用如圖 6 所示的初始化 import 語(yǔ)句。與手工配置相比,所有的 JNDI 引用都被刪除了。在 RegistryHelper 的位置換上了 TransientRepository。清單 6. 自動(dòng)配置的 import 語(yǔ)句import org.apache.jackrabbit.core.TransientRepositoryimport javax.jcr.*;import javax.jcr.query.*;import javax.jc

22、r.version.*;import java.util.Calendar;import java.io.*;import .www.MimeTable;因?yàn)?TransientRepository 為您執(zhí)行了初始化,所以獲得倉(cāng)庫(kù)非常簡(jiǎn)單,如清單 7 所示:清單 7. 用 TransientRepository 獲得倉(cāng)庫(kù)、工作區(qū)和根節(jié)點(diǎn) Repository r = new TransientRepository();Session session = r.login(new SimpleCredentials(userid, .toCharArray();Workspace w

23、s = session.getWorkspace();Node rn = session.getRootNode();像手工配置時(shí)一樣,所有的 JCRWiki 內(nèi)容都放在 wiki 名稱空間下:ws.getNamespaceRegistry()。registerNamespace (wiki, /wiki/1.0);恭喜!倉(cāng)庫(kù)的自動(dòng)配置現(xiàn)在完成了?;仨?yè)首JCRWiki 的設(shè)計(jì)策略現(xiàn)在看一下 JCRWiki 倉(cāng)庫(kù)的整體內(nèi)容層次結(jié)構(gòu)。在示例中,要?jiǎng)?chuàng)建兩個(gè)實(shí)體 “rose” 和 “Shakespeare”,它們都是 nt:unstructured類型的。根據(jù)設(shè)計(jì)

24、合同,每個(gè)百科全書條目都要有三個(gè)屬性:條目的標(biāo)題、條目的內(nèi)容以及多值分類屬性(如果條目有多個(gè)分類)或單值分類屬性(如果條目只有一個(gè)分類)。多值屬性在編程上表現(xiàn)為一組數(shù)值。圖 2 描繪了 JCRWiki 設(shè)計(jì)策略的圖示:圖 2. JCRWiki 拓?fù)涞母邔訄D示 回頁(yè)首JCRWiki 功能沒有內(nèi)容的倉(cāng)庫(kù)沒什么用處。這一節(jié)將演示 JSR-170 提供的基本內(nèi)容操縱功能,并描述一些更高級(jí)的、可選的倉(cāng)庫(kù)特性,例如版本管理和導(dǎo)入導(dǎo)出 XML 內(nèi)容。添加內(nèi)容從清單 8 開始,向倉(cāng)庫(kù)添加內(nèi)容節(jié)點(diǎn),讓它看起來(lái)像圖 2 中的 JCRWiki 拓?fù)洌呵鍐?8. 將內(nèi)容添加到 JCR 倉(cāng)庫(kù)中Node encyclop

25、edia = rn.addNode(wiki:encyclopedia);Node p = encyclopedia.addNode(wiki:entry);p.setProperty(wiki:title, new StringValue(rose);p.setProperty(wiki:content, new StringValue(A rose is a flowering shrub.);p.setProperty(wiki:category, new Value new StringValue(flower), new StringValue(plant), new StringV

26、alue(rose);Node n = encyclopedia.addNode(wiki:entry);n.setProperty(wiki:title, new StringValue(Shakespeare);n.setProperty(wiki:content, new StringValue(A famous poet who likes roses.);n.setProperty(wiki:category, new StringValue(poet);session.save();默認(rèn)情況下,Jackrabbit 的節(jié)點(diǎn)被設(shè)置為 nt:unstructured。注意,“rose”

27、 的分類屬性是多值的。上面代碼段的最后一行代碼將保存會(huì)話。添加和設(shè)置節(jié)點(diǎn)以及節(jié)點(diǎn)屬性只能修改臨時(shí)的會(huì)話存儲(chǔ)層。要將這些變化保持到倉(cāng)庫(kù)中,則必須用 session.save() 保存會(huì)話。可以在目標(biāo)節(jié)點(diǎn)上調(diào)用 Node.remove() 來(lái)刪除節(jié)點(diǎn)。存取內(nèi)容JSR-170 提供了兩種存取內(nèi)容的方法:遍歷 存取和直接 存取。遍歷存取包括用相對(duì)路徑在內(nèi)容樹中進(jìn)行遍歷,直接存取允許用絕對(duì)路徑直接跳到節(jié)點(diǎn),如果節(jié)點(diǎn)是可以引用的,則用 UUID 直接跳到節(jié)點(diǎn)。因?yàn)閮煞N存取之間存在相似性,所以我在這篇文章只側(cè)重于遍歷存取。從任何 Node 對(duì)象及其方法 Node.getNode()、Node.getProp

28、erty() 都可以進(jìn)行遍歷存取。通過(guò)使用 JCRWiki 拓?fù)洌梢杂靡韵麓a從根節(jié)點(diǎn)獲得 encyclopedia 節(jié)點(diǎn):Node encyclopedia = rn.getNode(wiki:encyclopedia);可以進(jìn)一步通過(guò)遍歷得到屬性。例如,在根節(jié)點(diǎn)向下的 “rose” 百科全書節(jié)點(diǎn)條目中,假設(shè)以前知道 JCRWiki 拓?fù)?,那么可以像這樣通過(guò)遍歷得到屬性:String roseTitle = rn.getProperty (wiki:encyclopedia/wiki:entry1/wiki:title).getString()請(qǐng)注意,您是通過(guò) wiki:entry1 進(jìn)行

29、遍歷的。當(dāng)有同名的多個(gè)同級(jí)節(jié)點(diǎn)時(shí),可以用下標(biāo)區(qū)分出想要的同級(jí)節(jié)點(diǎn)。在 JCR 中,對(duì)同級(jí)節(jié)點(diǎn)的索引是從 1 而不是 0 開始的。而且,索引的順序是在通過(guò) Node.getNodes() 得到的迭代器中返回的節(jié)點(diǎn)的順序。然后,可以通過(guò)獲取 NodeIterator(它返回特點(diǎn)節(jié)點(diǎn)的子節(jié)點(diǎn))來(lái)瀏覽所有 JCRWiki 條目,如清單 9 所示:清單 9. 瀏覽內(nèi)容倉(cāng)庫(kù)Node encyclopedia = rn.getNode(wiki:encyclopedia);NodeIterator entries = encyclopedia.getNodes(wiki:entry);while (entr

30、ies.hasNext() Node entry = entries.nextNode(); System.out.println(entry.getName(); System.out.println(entry.getProperty(wiki:title)。getString(); System.out.println(entry.getProperty(wiki:content)。getString(); System.out.println(entry.getPath(); Property category = entry.getProperty(wiki:category); t

31、ry String c = category.getValue()。getString(); System.out.println(Category: + c); catch (ValueFormatException e) Value categories = category.getValues(); for (Value c : categories) System.out.println(Category: + c.getString(); 因?yàn)榉诸悓傩钥梢允嵌嘀档囊部梢允菃沃档?,所以要?try-catch 語(yǔ)句檢查它。如果對(duì)多值屬性調(diào)用 getValue(),就會(huì)拋出ValueFo

32、rmatException。一般來(lái)說(shuō),直接存取和遍歷存取都需要知道內(nèi)部節(jié)點(diǎn)的結(jié)構(gòu)。所以讓我們來(lái)看一種更具表現(xiàn)力的存取節(jié)點(diǎn)的方式:使用搜索。用 XPath 搜索內(nèi)容正如已經(jīng)看到的,遍歷存取和直接存取都需要知道圖書的位置。獲得特定條目的更好方式是通過(guò) JCR 的 XPath 搜索工具。因?yàn)閺臉湫谓Y(jié)構(gòu)來(lái)看,工作區(qū)模型非常類似于 XML 文檔,所以 XPath 是查找節(jié)點(diǎn)的理想語(yǔ)法。XPath 查詢是通過(guò) QueryManager 對(duì)象執(zhí)行的。查詢的過(guò)程與通過(guò) JDBC 存取記錄類似,如清單 10 所示:清單 10. 用 XPath 搜索內(nèi)容QueryManager qm = ws.getQueryM

33、anager();Query q = qm.createQuery(/wiki:encyclopedia/wiki:entrywiki:title = rose, Query.XPATH);QueryResult result = q.execute();NodeIterator it = result.getNodes();while (it.hasNext() Node n = it.nextNode(); System.out.println(n.getName(); System.out.println(n.getProperty(wiki:title).getString(); Sy

34、stem.out.println(n.getProperty(wiki:content).getString();createQuery() 的第二個(gè)參數(shù)指定所使用的查詢語(yǔ)言。JRC 實(shí)現(xiàn)可以另外選擇為 SQL 語(yǔ)法支持 Query.SQL。也可以執(zhí)行更復(fù)雜的查詢。例如,可以查詢的內(nèi)容中包含單詞 rose 的所有條目:Query q = qm.createQuery (/wiki:encyclopedia/ + wiki:entryjcr:contains(wiki:content, rose), Query.XPATH);用 XML 導(dǎo)入和導(dǎo)出內(nèi)容JSR-170 為了確???JCR 實(shí)現(xiàn)的移

35、植性已經(jīng)做了許多工作。它促進(jìn)移植性的方式之一就是使用標(biāo)準(zhǔn)的 XML 導(dǎo)入和導(dǎo)出特性。通過(guò)使用這些工具,符合規(guī)范的供應(yīng)商倉(cāng)庫(kù)內(nèi)容可以很容易地轉(zhuǎn)移到另一個(gè)符合規(guī)范的供應(yīng)商倉(cāng)庫(kù)。使用 XML 進(jìn)行序列化的另一個(gè)優(yōu)勢(shì)是:可以用傳統(tǒng)的 XML 解析工具操縱導(dǎo)出的倉(cāng)庫(kù)。只要用清單 11 的三行代碼就可以執(zhí)行導(dǎo)出:清單 11. 導(dǎo)出數(shù)據(jù)File outputFile = new File(systemview.xml);FileOutputStream out = new FileOutputStream(outputFile);session.exportSystemView(/wiki:encyclop

36、edia, out, false, false);然后可以把生成的 XML 文件轉(zhuǎn)移給另一個(gè)新倉(cāng)庫(kù),如清單 12 所示:清單 12. 轉(zhuǎn)移數(shù)據(jù)File inputFile = new File(systemview.xml);FileInputStream in = new FileInputStream(inputFile);session.importXML (/, in, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);session.save();添加二進(jìn)制內(nèi)容直到現(xiàn)在,一直都是用 StringValue 表示屬性和節(jié)點(diǎn)。但是 JCR 還支持其他類

37、型,包括布爾型和長(zhǎng)整型。清單 13 演示了 JCR 中可使用的流類型,可在節(jié)點(diǎn)中保存二進(jìn)制圖片。在這個(gè)清單中,可將文件 rose.gif 作為元數(shù)據(jù)添加到 nt:file 節(jié)點(diǎn)中。文件數(shù)據(jù)本身被保存為 nt:resource 子節(jié)點(diǎn)。清單 13. 添加二進(jìn)制內(nèi)容File file = new File(rose.gif);MimeTable mt = MimeTable.getDefaultTable();String mimeType = mt.getContentTypeFor(file.getName();if (mimeType = null) mimeType = applicati

38、on/octet-stream;Node fileNode = roseMode.addNode(file.getName(), nt:file);Node resNode = fileNode.addNode(jcr:content, nt:resource);resNode.setProperty(jcr:mimeType, mimeType);resNode.setProperty(jcr:encoding, );resNode.setProperty(jcr:data, new FileInputStream(file);Calendar lastModified = Calendar

39、.getInstance();lastModified.setTimeInMillis(file.lastModified();resNode.setProperty(jcr:lastModified, lastModified);在使用 MimeTable 類確定了內(nèi)容類型之后,用 FileInputStream 裝入文件。這個(gè)問(wèn)題很簡(jiǎn)單,只要給 nt:resource 節(jié)點(diǎn)類型添加命名正確的屬性即可,屬性包含實(shí)際的文件數(shù)據(jù)。版本管理JSR-170 支持許多可選特性,包括訪問(wèn)控制、事務(wù)、鎖定和版本管理。這些特性本身都可以是個(gè)完整的主題,所以我必須簡(jiǎn)要地總結(jié)一下,只介紹它們當(dāng)中最流行的那一個(gè):

40、版本管理。在最簡(jiǎn)單的情況下,只需將 mix:versionable 混合類型添加到任何節(jié)點(diǎn),就可以執(zhí)行版本管理。在節(jié)點(diǎn)上,可以用一組類似 CVS 操作的方法實(shí)現(xiàn)版本管理,如清單 14 所示:清單 14. 版本管理方法n.checkout();n.setProperty(wiki:content, Updated content for the entry.);n.save();n.checkin();JCR 中的其他操作包括:更新、合并和恢復(fù)以前版本。要瀏覽指定節(jié)點(diǎn)的整個(gè)版本歷史,可以通過(guò)清單 15 中的步驟進(jìn)行:清單 15. 瀏覽版本歷史VersionHistory vh = n.getVe

41、rsionHistory();VersionIterator vi = vh.getAllVersions();vi.skip(1);while (vi.hasNext() Version v = vi.nextVersion(); NodeIterator ni = v.getNodes(); while (ni.hasNext() Node nv = ni.nextNode(); System.out.println(Version: + v.getCreated()。getTime(); System.out.println(nv.getProperty(wiki:title).getS

42、tring(); System.out.println(nv.getProperty(wiki:content).getString(); 使用 vi.skip(1) 最初看起來(lái)可能有點(diǎn)怪,但是如果看到了版本歷史的內(nèi)部保存機(jī)制,就應(yīng)該很清楚這種用法了,版本歷史的內(nèi)部保存機(jī)制如圖 3 所示:圖 3. 節(jié)點(diǎn)版本歷史的結(jié)構(gòu)化模型 在節(jié)點(diǎn)的版本歷史中,每個(gè)版本都保存為版本歷史的一個(gè)子版本,而且包含指向后續(xù)版本的引用。在圖 3 中,版本 Vb 是版本 Va 的后續(xù),版本 Vc 和 Va 是 Vroot 的后續(xù),Vroot 是版本圖的開始。Vroot 是自動(dòng)創(chuàng)建的子節(jié)點(diǎn),是版本圖的起點(diǎn),它不包含任何狀態(tài)信息。所以,當(dāng)應(yīng)用程序在版本歷史中遍歷時(shí),Vroot 被跳過(guò)。回頁(yè)首結(jié)束語(yǔ)本文提供了對(duì) JSR-170 規(guī)范所提供特性的廣泛介紹。在 2005 年 6 月 17 日通過(guò)的規(guī)范的最終發(fā)行版中,已有兩個(gè)商業(yè)實(shí)現(xiàn):Day Software 的 CRX 和 Obinary 的 Magnolia Power Pack。JSR-170 的引入也導(dǎo)致了企業(yè)開源門戶和內(nèi)容管理系統(tǒng)(如 Magnolia 和 eXo 平臺(tái))的增多。最重要的是,JSR-170 擁有來(lái)自行業(yè)領(lǐng)導(dǎo)者(包括 SAP AG、Macromedia 和 IBM)的強(qiáng)大支持,從而在企業(yè)陣營(yíng)建立起了它自己的應(yīng)用和重要性。就像對(duì)象關(guān)系映射框

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論