Java內(nèi)容管理系統(tǒng)JSR
《Java內(nèi)容管理系統(tǒng)JSR》由會員分享,可在線閱讀,更多相關(guān)《Java內(nèi)容管理系統(tǒng)JSR(16頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、Java Content Repository API 簡介 學習 JSR-170 如何使構(gòu)建 CMA 變得輕而易舉 Titus Barik (titus@), 高級程序員,分析師, SoloFX Enterprises, LLC 簡介: 隨著內(nèi)容管理應(yīng)用程序的日益普及,對于公共的、標準的內(nèi)容倉庫 API 的需求也變得漸漸明顯起來。Content Repository for Java ? Technology API(JSR-170)的目標就是提供這樣一個接口。在這篇文章中,我將用開放源碼的 JSR-170 實現(xiàn) Apache Jackrabbit,設(shè)計一個簡單的類似維京百科全書的后端
2、,研究這個前途遠大的框架所提供的特性。 標記本文! 發(fā)布日期: 2006 年 8 月 04 日 (最初發(fā)布 2005 年 8 月 23 日) 級別: 高級 訪問情況 : 6929 次瀏覽 評論: 0 (查看 | 添加評論 - 登錄) 平均分 (12個評分) 為本文評分 如果曾經(jīng)試過開發(fā)內(nèi)容管理應(yīng)用程序,那么您應(yīng)當非常清楚在實現(xiàn)內(nèi)容系統(tǒng)時所遇到的固有難題。這個領(lǐng)地有點支離破碎,許多供應(yīng)商都有自己的私有倉庫引擎。這些困難惡化了這類系統(tǒng)的復雜性和可維護性、增強了廠商鎖定、增加了企業(yè)市場中對傳統(tǒng)系統(tǒng)長期支持的需要。隨著企業(yè) weblog 和電子企業(yè)文檔管理的日益流行,對
3、標準化內(nèi)容倉庫接口的需求比以往任何時候都更加顯著。 Content Repository for Java Technology 規(guī)范是在 Java Community Process 中作為 JSR-170 開發(fā)的,它的目標是滿足這些行業(yè)的需求。該規(guī)范在 javax.jcr 名稱空間中提供了統(tǒng)一的 API ,允許以廠商中立的方式訪問任何符合規(guī)范的倉庫實現(xiàn)。 但是 API 標準化并不是 Java Content Repository(JCR)帶來的惟一特性。JSR-170 的一個主要優(yōu)勢就是沒有捆綁到任何特定的底層架構(gòu)上。例如,JSR-170 實現(xiàn)的后端數(shù)據(jù)存儲可以是文件系統(tǒng)、WebDAV
4、 倉庫、XML 支持的系統(tǒng)或者是 SQL 數(shù)據(jù)庫。而且,JSR-170 的導出和導入功能允許集成人員在后端內(nèi)容和 JCR 實現(xiàn)之間無縫地切換。最后,JCR 提供了簡單的接口,可以將該接口放在各種現(xiàn)有的內(nèi)容倉庫之上,并同時標準化一些復雜的功能(例如版本管理、訪問控制和搜索)。 在討論 JCR 時,有幾種方式可以采用。在這篇文章中,我從開發(fā)人員的角度來研究 JSR-170 規(guī)范所提供的特性,重點放在可用的 API 和接口上,這些接口允許程序員在設(shè)計內(nèi)容應(yīng)用程序時有效利用 JSR-170 倉庫。作為一個假設(shè)的示例,我將為一個類似維京百科全書的、叫做 JCRWiki 的系統(tǒng)實現(xiàn)一個小小的后端,為二進
5、制內(nèi)容、版本管理、備份和搜索提供支持。我使用 Apache Jackrabbit(JSR-170 的開源實現(xiàn))開發(fā)這個應(yīng)用程序。 倉庫模型 我先從對倉庫模型的高級討論開始,以便讓您熟悉 JCR。倉庫模型是簡單的層次結(jié)構(gòu),看起來就像一個有 n 個分叉的樹。它由單一內(nèi)容倉庫構(gòu)成,有一個或多個工作區(qū)。(這篇文章中的討論僅限制于單一工作區(qū)。)每個工作區(qū)都包含一個項目 樹;項目既可以是節(jié)點也可以是屬性。節(jié)點可以有零個或多個子節(jié)點以及零個或多個相關(guān)屬性,實際的內(nèi)容保存在子節(jié)點和屬性中。 每個節(jié)點都有且只有一個主節(jié)點類型。主節(jié)點類型定義了節(jié)點的特征,例如允許節(jié)點擁有的屬性和子節(jié)點。除了主節(jié)點類型之外,
6、節(jié)點還可以有一個或多個混合(mixin)類型?;旌项愋透裥揎椘鳎蚬?jié)點提供額外的特征。具體來說,JCR 實現(xiàn)可以提供三種預定義混合類型: mix:versionable:允許節(jié)點支持版本管理 mix:lockable:支持節(jié)點的鎖定功能 mix:referenceable:提供自動創(chuàng)建的 jcr:uuid 屬性,給節(jié)點一個惟一可以引用的標識符 這個結(jié)構(gòu)如圖 1 所示。圓圈代表節(jié)點,矩形代表屬性。請參見節(jié)點 A、B 和 C,它們都衍生自一個根節(jié)點。節(jié)點 A 有兩個屬性,即一個字符串 “John” 和一個整數(shù) 22。 圖 1. 有多個工作區(qū)的倉庫模型 預定義的節(jié)點類型
7、 每個倉庫都必須支持主節(jié)點類型 nt:base。倉庫還可以支持其他許多公共節(jié)點類型: nt:unstructured 是最靈活的節(jié)點類型。它允許使用任意數(shù)量的子節(jié)點或?qū)傩裕⑶铱梢允褂萌我饷Q。這個節(jié)點類型表示 JCRWiki 的條目。 nt:file 表示文件。它需要一個叫做 jcr:content 的單一子節(jié)點。這個節(jié)點類型表示 JCRWiki 條目中的圖片和其他二進制內(nèi)容。 nt:folder 節(jié)點類型可以表示文件夾,就像常規(guī)的文件系統(tǒng)中的文件夾一樣。 nt:resource 通常表示文件的實際內(nèi)容。 nt:version 是支持版本管理的倉庫所必需
8、的節(jié)點類型。 整個節(jié)點類型的結(jié)構(gòu)可以在 JSR-170 規(guī)范的 6.7.22.1 小節(jié)找到(請參閱 參考資料 獲得鏈接)。 名稱空間 倉庫模型一個有用的卻經(jīng)常被忽視的特性就是它對名稱空間 的支持。名稱空間防止不同來源和不同應(yīng)用程序域之間的項目和節(jié)點類型的命名沖突。名稱空間被定義為帶有一個前綴,中間用一個 : (冒號)分隔。在這篇文章的教程中,已經(jīng)遇到了一些名稱空間:jcr用于 JCR 的內(nèi)部屬性,mix 用于混合類型,nt 用于節(jié)點類型。在 JCRWiki 中,所有的數(shù)據(jù)都將使用 wiki 名稱空間。 回頁首 安裝 JCR 在編寫這篇文章的時候,Apache Jackrabbit(
9、即 Apache 基金會的 JSR-170 的開源實現(xiàn))的發(fā)行版已經(jīng)到了版本 1.0。編譯好的字節(jié)碼 JAR 可以直接從 Jackrabbit Web 站點下載(請參閱 參考資料)。雖然 Jackrabbit can 仍然可以用 SVN 從源代碼進行編譯,但是 Jackrabbit 庫已經(jīng)非常穩(wěn)定,不再需要每夜構(gòu)建(nightly builds)技術(shù)。這一節(jié)將提供盡可能快地安裝 JCR 實現(xiàn)并運行它的詳細說明。 需要的庫 要使用和運行這篇文章中的示例,請將下面這些庫放在類路徑中: jackrabbit-core:針對 JSR-170 的 Jackrabbit 內(nèi)容倉庫核心實現(xiàn)和來自 A
10、pache 的公共實用代碼。 commons-collections:包含強大數(shù)據(jù)結(jié)構(gòu)的框架,該框架可以加快 Java 應(yīng)用程序的開發(fā)。 concurrent:這個庫提供通常在 Java 并發(fā)編程中會遇到的工具類的標準化的、有效率的版本。 derby:一個 Apache 數(shù)據(jù)庫子項目,它提供完全用 Java 語言實現(xiàn)的關(guān)系數(shù)據(jù)庫。 jcr:一組符合 JSR-170 規(guī)范的接口。 log4j:運行時日志庫。 lucene:高性能的全功能文本搜索引擎庫。 slf4j (針對 Java 的簡單日志 Facade):目的是充當不同日志 API 的
11、簡單 facade,允許用戶在部署時插入需要的實現(xiàn)。 xerces:高級 XML 解析器,支持 SAX 版本 2、DOM 1 級和 SAX 版本 1 API。 如果用 SVN 構(gòu)建 Jackrabbit,那么所有這些 JAR 文件都會在 Jackrabbit 構(gòu)建過程中被下載,并位于 Maven 的緩存目錄中。在 Linux 下,這些 JAR 位于主目錄的 .maven 目錄下。如果使用二進制構(gòu)建,那么只需要從它們各自的 Web 站點下載其二進制版或瀏覽 Jackrabbit Web 站點的 “First Hops with Jackrabbit” 即可,那里會提供到所有這些資源的直
12、接鏈接。在 JSR-170 規(guī)范的下載中還有一個 jcr-1.0.jar,在 Java 社區(qū)進程的 Web 站點上也可以找到它。 回頁首 手工配置 JSR-170 沒有確切地指定應(yīng)當如何獲得初始的 Repository 對象;這被留作每個倉庫廠商的實現(xiàn)細節(jié)。但是,在應(yīng)用程序中最好使用 JNDI 或其他容器環(huán)境中的配置機制,這樣可以保持 JSR-170 的實現(xiàn)相對獨立于對 Jackrabbit 的直接依賴項。雖然這一策略在初始配置期間造成了額外的復雜性,但它提供了跨不同 JSR-170 實現(xiàn)的更好的移植性。要想獲得一個移植性雖然差但得到了簡化的配置,可以使用自動配置,詳細內(nèi)容在這篇文章后面
13、部分介紹。
在手工配置中,可以將 JNDI 與配置文件(叫做 repository.xml,以編程方式載入)結(jié)合使用來得到倉庫。
倉庫配置
第一步,也是最容易的一步,就是為 Jackrabbit 創(chuàng)建 repository.xml 文件。這個配置文件實現(xiàn)了許多重要任務(wù)。這些任務(wù)包括:指定底層的后端存儲、訪問控制機制、可用的工作區(qū)、版本管理系統(tǒng)和搜索子系統(tǒng)。清單 1 提供了一個示例:
清單 1. 示例 repository.xml 配置文件
14、tem
class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
19、ing>
20、"anonymous"; }; 倉庫初始化代碼 清單 3 描述的包可在初始化倉庫時使用: 清單 3. 手工配置的初始化 import 語句 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.*; import
21、 javax.jcr.version.*; import java.util.Hashtable; import java.util.Calendar; import java.io.*; import .www.MimeTable; 要得到 Repository 對象,請將 configFile 變量設(shè)置成指向 repository.xml 文件,將 repHomeDir 變量設(shè)置成指向倉庫所在的本地文件系統(tǒng)目錄。當結(jié)合 RegistryHelper 使用 JNDI 時,獲得倉庫非常簡單,如清單 4 所示: 清單 4. 用 JNDI 獲得 repository
22、 對象 String 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.PRO
23、VIDER_URL, "localhost"); InitialContext ctx = new InitialContext(env); RegistryHelper.registerRepository(ctx, "repo", configFile, repHomeDir, true); Repository r = (Repository) ctx.lookup("repo"); 接下來,用 SimpleCredentials 獲得 Session 對象。在這個實現(xiàn)中,Simp
24、leCredentials 接受所有用戶名。替代的 JCR 實現(xiàn)可以提供更復雜的認證機制,可以連接到 LDAP 服務(wù)器或外部數(shù)據(jù)庫來提供憑據(jù)信息。(身份驗證和訪問控制的完整功能超出了本文的范圍。要獲得有關(guān)的更多信息,請參閱 JSR-170 規(guī)范的 6.9 小節(jié)。) Session 對象為程序員提供了一個臨時的存儲層,它非常像傳統(tǒng)的對象關(guān)系映射工具中可以看到的層,而且還可以將它看作到特定工作區(qū)的連接。它允許客戶訪問綁定到這個會話的任何節(jié)點或?qū)傩?。通過會話,可以得到工作區(qū),再從工作區(qū)得到根節(jié)點。所有這些步驟都是在清單 5 的簡短代碼片段中完成的: 清單 5. 獲得工作區(qū)和根節(jié)點 Simp
25、leCredentials cred = new SimpleCredentials("userid", "".toCharArray()); Session session = r.login(cred, null); Workspace ws = session.getWorkspace(); Node rn = session.getRootNode(); 使用會話、工作區(qū)和根節(jié)點引用,現(xiàn)在可以通過不同的抽象層訪問倉庫的特性。最后,為了驗證倉庫已經(jīng)成功獲得初始化,可以用rn.getPrimaryNodeType().getName() 輸出根節(jié)點的
26、名稱。這應(yīng)當形成以下輸出: rep:root 因為正在使用 JAAS,所以請記得將 -Djava.security.auth.login.config==jaas.config. 以 Java JVM 參數(shù)的形式包含進來。 JCRWiki 名稱空間 在這個練習中,所有的 JCRWiki 內(nèi)容都放在 wiki 名稱空間下。為了讓倉庫識別這個名稱空間,必須在初始化時注冊名稱空間,如下所示: ws.getNamespaceRegistry()。registerNamespace ("wiki", " 恭喜!倉庫的手工配置現(xiàn)在完成了。 回頁首 自動配
27、置 Jackrabbit 實現(xiàn)還提供了一個 TransientRepository 類,這個類來自其核心 API,可以在啟動第一個會話時自動初始化內(nèi)容倉庫,并在最后一個會話關(guān)閉時停止使用倉庫。對于簡單的獨立應(yīng)用程序,使用 TransientRepository 可以極大地簡化倉庫的配置,但要以 JSR-170 的移植性作為代價。 TransientRepository 自動創(chuàng)建 repository.xml 和倉庫文件夾。它還在內(nèi)部提供了處理身份驗證和安全性的 SimpleAccessManager。 自動配置需要使用如圖 6 所示的初始化 import 語句。與手工配置相比,所有的 J
28、NDI 引用都被刪除了。在 RegistryHelper 的位置換上了 TransientRepository。 清單 6. 自動配置的 import 語句 import org.apache.jackrabbit.core.TransientRepository import javax.jcr.*; import javax.jcr.query.*; import javax.jcr.version.*; import java.util.Calendar; import java.io.*; import .www.MimeTable; 因為 T
29、ransientRepository 為您執(zhí)行了初始化,所以獲得倉庫非常簡單,如清單 7 所示: 清單 7. 用 TransientRepository 獲得倉庫、工作區(qū)和根節(jié)點 Repository r = new TransientRepository(); Session session = r.login(new SimpleCredentials("userid", "".toCharArray())); Workspace ws = session.getWorkspace(); Node rn = session.getRootNode(); 像手工
30、配置時一樣,所有的 JCRWiki 內(nèi)容都放在 wiki 名稱空間下: ws.getNamespaceRegistry()。registerNamespace ("wiki", " 恭喜!倉庫的自動配置現(xiàn)在完成了。 回頁首 JCRWiki 的設(shè)計策略 現(xiàn)在看一下 JCRWiki 倉庫的整體內(nèi)容層次結(jié)構(gòu)。在示例中,要創(chuàng)建兩個實體 “rose” 和 “Shakespeare”,它們都是 nt:unstructured類型的。根據(jù)設(shè)計合同,每個百科全書條目都要有三個屬性:條目的標題、條目的內(nèi)容以及多值分類屬性(如果條目有多個分類)或單值分類屬性(如果條目只有一個
31、分類)。多值屬性在編程上表現(xiàn)為一組數(shù)值。 圖 2 描繪了 JCRWiki 設(shè)計策略的圖示: 圖 2. JCRWiki 拓撲的高層圖示 回頁首 JCRWiki 功能 沒有內(nèi)容的倉庫沒什么用處。這一節(jié)將演示 JSR-170 提供的基本內(nèi)容操縱功能,并描述一些更高級的、可選的倉庫特性,例如版本管理和導入導出 XML 內(nèi)容。 添加內(nèi)容 從清單 8 開始,向倉庫添加內(nèi)容節(jié)點,讓它看起來像圖 2 中的 JCRWiki 拓撲: 清單 8. 將內(nèi)容添加到 JCR 倉庫中 Node encyclopedia = rn.addNode("wiki:encyclopedia");
32、 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"),
33、 new StringValue("plant"), new StringValue("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.setPropert
34、y("wiki:category", new StringValue("poet")); session.save(); 默認情況下,Jackrabbit 的節(jié)點被設(shè)置為 nt:unstructured。注意,“rose” 的分類屬性是多值的。上面代碼段的最后一行代碼將保存會話。添加和設(shè)置節(jié)點以及節(jié)點屬性只能修改臨時的會話存儲層。要將這些變化保持到倉庫中,則必須用 session.save() 保存會話??梢栽谀繕斯?jié)點上調(diào)用 Node.remove() 來刪除節(jié)點。 存取內(nèi)容 JSR-170 提供了兩種存取內(nèi)容的方法:遍歷 存取和直接 存取。遍歷存取包括用相對路徑在內(nèi)容樹中
35、進行遍歷,直接存取允許用絕對路徑直接跳到節(jié)點,如果節(jié)點是可以引用的,則用 UUID 直接跳到節(jié)點。因為兩種存取之間存在相似性,所以我在這篇文章只側(cè)重于遍歷存取。 從任何 Node 對象及其方法 Node.getNode()、Node.getProperty() 都可以進行遍歷存取。通過使用 JCRWiki 拓撲,可以用以下代碼從根節(jié)點獲得 encyclopedia 節(jié)點: Node encyclopedia = rn.getNode("wiki:encyclopedia"); 可以進一步通過遍歷得到屬性。例如,在根節(jié)點向下的 “rose” 百科全書節(jié)點條目中,假設(shè)以前知道 JCR
36、Wiki 拓撲,那么可以像這樣通過遍歷得到屬性: String roseTitle = rn.getProperty ("wiki:encyclopedia/wiki:entry[1]/wiki:title").getString() 請注意,您是通過 wiki:entry[1] 進行遍歷的。當有同名的多個同級節(jié)點時,可以用下標區(qū)分出想要的同級節(jié)點。在 JCR 中,對同級節(jié)點的索引是從 1 而不是 0 開始的。而且,索引的順序是在通過 Node.getNodes() 得到的迭代器中返回的節(jié)點的順序。 然后,可以通過獲取 NodeIterator(它返回特點節(jié)點的子節(jié)點)來
37、瀏覽所有 JCRWiki 條目,如清單 9 所示: 清單 9. 瀏覽內(nèi)容倉庫 Node encyclopedia = rn.getNode("wiki:encyclopedia"); NodeIterator entries = encyclopedia.getNodes("wiki:entry"); while (entries.hasNext()) { Node entry = entries.nextNode(); System.out.println(entry.getName()); System.out.println(entr
38、y.getProperty("wiki:title")。getString()); System.out.println(entry.getProperty("wiki:content")。getString()); System.out.println(entry.getPath()); Property category = entry.getProperty("wiki:category"); try { String c = category.getValue()。getString(); System.out
39、.println("Category: " + c); } catch (ValueFormatException e) { Value[] categories = category.getValues(); for (Value c : categories) { System.out.println("Category: " + c.getString()); } } } 因為分類屬性可以是多值的也可以是單值的,所以要用 try-catch 語句檢查它。如果對多值屬性調(diào)用
40、getValue(),就會拋出ValueFormatException。一般來說,直接存取和遍歷存取都需要知道內(nèi)部節(jié)點的結(jié)構(gòu)。所以讓我們來看一種更具表現(xiàn)力的存取節(jié)點的方式:使用搜索。 用 XPath 搜索內(nèi)容 正如已經(jīng)看到的,遍歷存取和直接存取都需要知道圖書的位置。獲得特定條目的更好方式是通過 JCR 的 XPath 搜索工具。因為從樹形結(jié)構(gòu)來看,工作區(qū)模型非常類似于 XML 文檔,所以 XPath 是查找節(jié)點的理想語法。XPath 查詢是通過 QueryManager 對象執(zhí)行的。查詢的過程與通過 JDBC 存取記錄類似,如清單 10 所示: 清單 10. 用 XPath 搜索內(nèi)容
41、 QueryManager qm = ws.getQueryManager(); Query q = qm.createQuery ("http://wiki:encyclopedia/wiki:entry[@wiki:title = rose]", Query.XPATH); QueryResult result = q.execute(); NodeIterator it = result.getNodes(); while (it.hasNext()) { Node n = it.nextN
42、ode(); System.out.println(n.getName()); System.out.println(n.getProperty("wiki:title").getString()); System.out.println(n.getProperty("wiki:content").getString()); } createQuery() 的第二個參數(shù)指定所使用的查詢語言。JRC 實現(xiàn)可以另外選擇為 SQL 語法支持 Query.SQL。也可以執(zhí)行更復雜的查詢。例如,可以查詢的內(nèi)容中包含單詞 rose
43、 的所有條目: Query q = qm.createQuery ("http://wiki:encyclopedia/" + "wiki:entry[jcr:contains(@wiki:content, rose)]", Query.XPATH); 用 XML 導入和導出內(nèi)容 JSR-170 為了確保跨 JCR 實現(xiàn)的移植性已經(jīng)做了許多工作。它促進移植性的方式之一就是使用標準的 XML 導入和導出特性。通過使用這些工具,符合規(guī)范的供應(yīng)商倉庫內(nèi)容可以很容易地轉(zhuǎn)移到另一個符合規(guī)范的供應(yīng)商倉庫。使用 XML 進行序列化的另一個優(yōu)勢是:可以用傳統(tǒng)的 XML 解析工具操縱
44、導出的倉庫。只要用清單 11 的三行代碼就可以執(zhí)行導出: 清單 11. 導出數(shù)據(jù) File outputFile = new File("systemview.xml"); FileOutputStream out = new FileOutputStream(outputFile); session.exportSystemView("/wiki:encyclopedia", out, false, false); 然后可以把生成的 XML 文件轉(zhuǎn)移給另一個新倉庫,如清單 12 所示: 清單 12. 轉(zhuǎn)移數(shù)據(jù) File inputFile = new File(
45、"systemview.xml"); FileInputStream in = new FileInputStream(inputFile); session.importXML ("/", in, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW); session.save(); 添加二進制內(nèi)容 直到現(xiàn)在,一直都是用 StringValue 表示屬性和節(jié)點。但是 JCR 還支持其他類型,包括布爾型和長整型。清單 13 演示了 JCR 中可使用的流類型,可在節(jié)點中保存二進制圖片。在這個清單中,可將文件 rose.gif
46、作為元數(shù)據(jù)添加到 nt:file 節(jié)點中。文件數(shù)據(jù)本身被保存為 nt:resource 子節(jié)點。 清單 13. 添加二進制內(nèi)容 File file = new File("rose.gif"); MimeTable mt = MimeTable.getDefaultTable(); String mimeType = mt.getContentTypeFor(file.getName()); if (mimeType == null) mimeType = "application/octet-stream"; Node fileNode = roseMode.addNod
47、e(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.getInstance(); lastM
48、odified.setTimeInMillis(file.lastModified()); resNode.setProperty("jcr:lastModified", lastModified); 在使用 MimeTable 類確定了內(nèi)容類型之后,用 FileInputStream 裝入文件。這個問題很簡單,只要給 nt:resource 節(jié)點類型添加命名正確的屬性即可,屬性包含實際的文件數(shù)據(jù)。 版本管理 JSR-170 支持許多可選特性,包括訪問控制、事務(wù)、鎖定和版本管理。這些特性本身都可以是個完整的主題,所以我必須簡要地總結(jié)一下,只介紹它們當中最流行的那一個:版本管理。
49、在最簡單的情況下,只需將 mix:versionable 混合類型添加到任何節(jié)點,就可以執(zhí)行版本管理。在節(jié)點上,可以用一組類似 CVS 操作的方法實現(xiàn)版本管理,如清單 14 所示: 清單 14. 版本管理方法 n.checkout(); n.setProperty("wiki:content", "Updated content for the entry."); n.save(); n.checkin(); JCR 中的其他操作包括:更新、合并和恢復以前版本。要瀏覽指定節(jié)點的整個版本歷史,可以通過清單 15 中的步驟進行: 清單 15. 瀏覽版本歷史 Vers
50、ionHistory vh = n.getVersionHistory(); 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.prin
51、tln("Version: " + v.getCreated()。getTime()); System.out.println(nv.getProperty("wiki:title").getString()); System.out.println(nv.getProperty("wiki:content").getString()); } } 使用 vi.skip(1) 最初看起來可能有點怪,但是如果看到了版本歷史的內(nèi)部保存機制,就應(yīng)該很清楚這種用法了,版本歷史的內(nèi)部保存機制如圖 3
52、所示: 圖 3. 節(jié)點版本歷史的結(jié)構(gòu)化模型 在節(jié)點的版本歷史中,每個版本都保存為版本歷史的一個子版本,而且包含指向后續(xù)版本的引用。在圖 3 中,版本 Vb 是版本 Va 的后續(xù),版本 Vc 和 Va 是 Vroot 的后續(xù),Vroot 是版本圖的開始。Vroot 是自動創(chuàng)建的子節(jié)點,是版本圖的起點,它不包含任何狀態(tài)信息。所以,當應(yīng)用程序在版本歷史中遍歷時,Vroot 被跳過。 回頁首 結(jié)束語 本文提供了對 JSR-170 規(guī)范所提供特性的廣泛介紹。在 2005 年 6 月 17 日通過的規(guī)范的最終發(fā)行版中,已有兩個商業(yè)實現(xiàn):Day Software 的 CRX 和 Obin
53、ary 的 Magnolia Power Pack。JSR-170 的引入也導致了企業(yè)開源門戶和內(nèi)容管理系統(tǒng)(如 Magnolia 和 eXo 平臺)的增多。最重要的是,JSR-170 擁有來自行業(yè)領(lǐng)導者(包括 SAP AG、Macromedia 和 IBM)的強大支持,從而在企業(yè)陣營建立起了它自己的應(yīng)用和重要性。就像對象關(guān)系映射框架改變了數(shù)據(jù)庫編程一樣,JCR API 也有可能極大地改變我們思考和開發(fā)內(nèi)容應(yīng)用程序的方式。 參考資料 學習 您可以參閱本文在 developerWorks 全球站點上的 英文原文 。 JSR-170 specification:在 Java C
54、ommunity Process 上瀏覽這個規(guī)范。API 規(guī)范包含近 300 頁有關(guān)使用 JCR 的信息以及構(gòu)建自己的 JSR-170 實現(xiàn)的內(nèi)部細節(jié)。 Magnolia content management:使用 JCR 訪問其內(nèi)容的一個免費的企業(yè)級類 CMS。 “項目管理: Maven 讓事情變得簡單”(Charles Chan,developerWorks,2003 年 4 月):用 Maven 加快速度。 “Subversion 簡介”(Elliotte Rusty Harold,developerWorks,2006 年 6 月):學習如何在 Eclip
55、se 中配置 Subversion 支持、簽出項目和同步倉庫,然后運行合并、補丁、差異和刪除之類的常見操作。 “Whats new in WebSphere Portal V5.1?”(Deborah Cottingham,developerWorks,2004 年 3 月):IBM WebSphere Portal 提供了 JSR 170 規(guī)范的初始實現(xiàn)。請在這個頁面上查找關(guān)于 JSR 和這個強大框架其他特性的更多信息。 “Parsing, indexing, and searching XML with Digester and Lucene”(Otis Gospodne
56、tic,developerWorks,2003 年 6 月):學習 Lucene 的搜索功能。 “XPath 入門”(Bertrand Portier,developerWorks,2004 年 5 月):如果不熟悉 XPath,您可能想看看這個 developerWorks 教程。 獲得產(chǎn)品和技術(shù) Apache Jackrabbit:Content Repository for Java Technology API 的開源實現(xiàn)。在 Apache 許可下發(fā)布。 The JSR-170 Tools online Web portal:Day Software 是
57、JSR-170 的規(guī)范領(lǐng)袖,它在這里演示了自己的 JCR 實現(xiàn))—— 商業(yè)內(nèi)容倉庫終極版(CRX)。CRX 提供了 I 級和 II 級功能,以及版本管理、鎖定、訪問控制和事件等高級特性??梢垣@得它的一個免費試用版。 Maven:這是 Apache Jackrabbit 實現(xiàn)使用的軟件項目構(gòu)建系統(tǒng)。 Subversion:這個流行的版本控制系統(tǒng)在 Apache 風格的許可下發(fā)布,提供了引人注目的對 CVS 的替代。 Xalan-Java:一個 XSLT 處理器,可以把 XML 文檔轉(zhuǎn)換成 HTML、文本或其他 XML 文檔類型。 討論 Jackrabbit Developer Mailing List:通過訂閱加入 Jackrabbit 項目。 關(guān)于作者 Titus Barik 是一名內(nèi)容應(yīng)用程序開發(fā)人員,他對開放源碼企業(yè)解決方案很感興趣。他已經(jīng)成功地在企業(yè)和非盈利環(huán)境中部署了 Magnolia 和其他 JSR-170 技術(shù)。 上有他的個人 weblog,非常歡迎您提供意見和建議。
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。