首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

整合 Java 內容倉庫 (JCR) 與 Spring 框架:實作指南

     編輯:Java 相關知識

在企業應用程式中,持久化資料是常態。傳統關聯式資料庫擅長處理結構化資料,但面對影像、文件等二進位大物件時往往力不從心。雖然檔案系統能提供較佳效能,卻缺乏查詢語言、關聯模型與交易支援。隨著系統擴展,開放第三方存取儲存資料的需求日益迫切,但自行實作往往耗時且複雜,內部儲存結構更易滲漏至 API 設計,影響資料檢索與遍歷方式。

什麼是 JSR-170 (JCR)?

Java 內容倉庫 API (JCR,JSR-170) 旨在以實作無關的方式解決上述問題。無論底層資源為資料庫、本地或虛擬檔案系統,API 皆保持一致。JCR 在資料儲存之上提供存取控制、版本控管、事件通知、全文檢索等內容服務。專家群包含 Day Software、Vignette、IBM、Oracle 等重量級廠商,使其極可能成為內容管理與文件儲存的事實標準。

經過兩年半努力,JSR-170 於 2005 年 6 月定案,javax.jcr 套件約含 50 個類別 (多為介面與例外)。2006 年釋出參考實作 Jackrabbit 1.0 版。

JCR 核心概念:樹狀結構

JCR 以「倉庫」為核心,採樹狀結構儲存資訊,由節點與屬性組成。節點對應目錄,屬性對應檔案;每個節點有一父節點、任意子節點與屬性;屬性值支援布林、日期、浮點數、長整數、字串與串流等型別。唯有屬性儲存實際資料,節點則構成路徑。

功能相容性層級

  • Level 1 (必須):唯讀存取、XML/SAX 輸出、XPath 查詢。
  • Level 2:寫入功能 (增刪節點/屬性、XML/SAX 匯入)。實作不強制支援 Level 2。
  • 選用功能:交易、版本控管、事件觀察、鎖定等進階特性,這正是 JCR 的亮點所在。

API 架構概覽

核心類別為 Session,代表客戶端與倉庫的連線,包含工作區名稱與憑證。Session 涵蓋 Level 1/2 方法,若底層不支援則拋出例外。javax.jcr.query、nodetype、version、observation、lock 等套件分別處理查詢、節點型別與選用功能。javax.jcr.util 提供 ItemVisitor 實作,應用訪問者模式。

主流 JCR 實作

  • Jackrabbit (Apache):參考實作,支援 Level 1/2 及選用功能,已孵化畢業可用於生產環境,授權 Apache 2.0。提供 JCA 連接器、WebDAV、虛擬檔案系統、JDBC 後端等擴充套件。
  • eXo JCR:eXo Platform 一部分,支援強制與部分選用功能,後端支援 MySQL/DB2/HSQL,雙授權 (GPL/商業)。
  • Jeceira:較新專案,實作 Level 1/2 部分需求,Magnolia CMS 採用,授權 Apache 2.0。

Spring Modules JCR 整合

Spring Modules JCR 模組簡化 JSR-170 開發,核心特性:

  • JcrTemplate:封裝 Session 管理、例外轉換 (檢查型轉非檢查型)、執行緒綁定 Session,支援交易環境。
  • RepositoryFactoryBean:配置、啟動/停止倉庫實例,預設支援 Jackrabbit、Jeceira,可擴充其他實作。
  • SessionFactory:統一 Repository、Credentials、Workspace,支援自動註冊監聽器與自訂命名空間。
  • 宣告式交易支援 (針對實作選用交易功能的倉庫)。
  • OpenSessionInView 攔截器/過濾器:每請求單一 Session,管理工作外部化。

實作範例:Jackrabbit + Spring 配置

倉庫與 SessionFactory 設定

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

生產環境常將倉庫註冊於 JNDI,可用 JndiObjectFactoryBean 或 Spring 2.0 <jndi:lookup> 取得。

SessionFactory 與 JcrTemplate

<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"/>
      <constructor-arg index="1">
        <bean factory-bean="password" factory-method="toCharArray"/>
      </constructor-arg>
    </bean>
  </property>
</bean>

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

JCR Callback 範例:匯入檔案

public Node importFile(final Node folderNode, final File file, final String mimeType, final String encoding) {
    return (Node) jcrTemplate.execute(new JcrCallback() {
        public Object doInJcr(Session session) throws RepositoryException, IOException {
            JcrConstants jcrConstants = new JcrConstants(session);
            Node fileNode = folderNode.addNode(file.getName(), jcrConstants.getNT_FILE());
            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;
        }
    });
}

程式碼包裝於 JcrCallback,JcrTemplate 自動處理 Session 開關、交易回滾與例外。硬編碼字串透過 JcrConstants 解析,增強健壯性。

交易支援

JCR 視交易為選用功能,Jackrabbit 透過每個 Session 暴露 javax.transaction.XAResource 實作。Spring Modules 提供 LocalTransactionManager:

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

搭配 TransactionProxyFactoryBean 進行宣告式交易劃分。若需 JTA,可使用 Jackrabbit 捐贈套件的 JCA 連接器與 Jencks 等可插拔容器。

TransactionAwareRepository

允許直接使用 JCR API 的程式碼透明地參與交易驅動 Session。配置 allowNonTxRepository 可支援非交易模式。

選用功能偵測機制

透過 SessionHolderProvider / SessionHolderProviderManager 實現可插拔支援。預設使用 JDK Service Provider 機制自動發現 (如 JackRabbitSessionHolderProvider),亦可改用 ListSessionHolderProviderManager 手動指定提供者清單,便於測試與客製化。

展望:JSR-283 與生態系發展

JSR-283 將聚焦聯邦化、遠端協定、擴充內容模型。生態系持續豐富:ORM 風格的物件映射框架、建構於 JCR 之 WebDAV 伺服器、Alfresco/BEA Portal/IBM Domino 等產品的 JCR 連接器。Spring Modules 路線圖包含 Acegi 安全整合、Spring 2.0 命名空間支援、更多 JCR 實作整合。Java 內容倉庫的未來一片光明。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved