集成Java內容倉庫和Spring

JCR模塊

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

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

本文將使用參考實現(Jackrabbit),由于JCR模塊使用的是javax.jcr接口,因此改變實現根本就是一個配置的問題。讓我們一步一步地來看看在Jackrabbit之上如何使用Java內容倉庫,以及如何讓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在使用本地文件系統時特別有用;對于服務器環境,倉庫可能被注冊在JNDI中,此時可以使用JndiObjectFactoryBean幫助類(Spring分發包的一部分)檢索它:

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

SessionFactory的缺省實現是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的構造函數:它只接受字符數組,使用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

例子

既然倉庫已經配置了,接下來看看“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;
}
});
}

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

事務支持

使用JCR模塊的一個好處就是能將Spring事務基礎設施(包括聲明性和編程性)應用于Java內容倉庫。JSR 170將事務支持視為可選特性,并沒有強制一個標準的方式來暴露事務鉤子,因此每個實現可以選擇不同的方法。在本文撰寫時,只有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管理器,一個簡單而優雅的解決辦法是使用來自Jackrabbit捐獻包的jca連接器。為了使用jca,你并不需要一個應用服務器,因為你可以用一個可插入的JCA容器,如Jencks。JCA容器的配置已經超出本文的范圍,但是你可以參考JCR模塊例子中使用Jencks的例子。

TransactionAwareRepository

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

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

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

可選特性支持偵測

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

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

org.springmodules.jcr.jackrabbit.support.JackRabbitSessionHolderProvider

缺省,SessionHolderProviderManagerJcrSessionFactory內部使用,因此在工廠啟動時,任何客戶化實現可以被獲取,并與合適的倉庫一起使用。但是,通過設置JcrSessionFactory中的SessionHolderProviderManager,可以很容易的切換到一個不同的發現策略。一個可替代的發現服務是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內容倉庫的未來

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

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

本文轉自BlogJava 新浪blog的博客,原文鏈接:集成Java內容倉庫和Spring,如需轉載請自行聯系原博主。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/539886.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/539886.shtml
英文地址,請注明出處:http://en.pswp.cn/news/539886.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

jQuery Mobile彈出對話框后不刷新原頁面,保持原頁面內容不變

使用jQuery Mobile開發移動應用程序時&#xff0c;在一個頁面上彈出對話框&#xff0c;關閉對話框后&#xff0c;發現原來的頁面被刷新了。如果原頁面上有一些已經選擇或者填寫的數據&#xff0c;則這些數據就會丟失。這時候&#xff0c;就需要對對話框的返回按鈕做一些處理&am…

mpi4py linux例子,python-3.x – mpi4py中的共享內存

我使用MPI(mpi4py)腳本(在單個節點上),它與一個非常大的對象一起使用.為了讓所有進程都可以訪問該對象,我通過comm.bcast()分發它.這會將對象復制到所有進程并占用大量內存,尤其是在復制過程中.因此,我想分享像指針而不是對象本身.我發現memoryview中的一些功能對于增強進程內對…

c語言源程序最多可能由組成,一個C語言源程序由若干函數組成,其中至少應含有一個()。...

個C語言源由I am interested in the training course, which _____ at Hilton Hotel in Beijing from March 8 to 12, 2018.程序成“萬物莫不有對”體現了中國傳統哲學的矛盾觀。用戶在進行產品的三維設計時&#xff0c;干函可以采用以下( )的設計方法。數組少意識是人腦對客觀…

oracle的背景

oracle簡介 1977年 美國人 Larry 成立軟件開發實驗室 。 1980年 用c/c開發了世界第一個商用關系型數據庫&#xff08;RDBMS&#xff09;。 1983年 公司更名為Oracle Corporation&#xff08;甲骨文公司&#xff09;。 2009年4月21日&#xff0c;Oracle收購Sun公司。 30多…

Citrix Netscaler版本管理和選擇

Citrix Netscaler版本管理和選擇 來源 http://blog.51cto.com/caojin/1898164 隨著Citrix Netscaler的快速發展&#xff0c;有很多人在維護設備時經常搞不懂Netscaler軟件版本是如何查看和選擇&#xff0c;當前軟件是否需要升級&#xff0c;當前軟件是否穩定等。基于以上問題&a…

樹的基本操作代碼 c語言,二叉樹的基本操作(C語言、源代碼)

二叉樹的基本操作(源代碼)#include "stdio.h"#include "malloc.h"#define MAX 100typedef struct node{int date;struct node *lchild,*rchild;}bitnode,*bitree;bitree createbitree(bitree bt){int m;printf("m");scanf("%d",&m…

oracle實例與數據庫

一、名稱 Oracle數據庫服務器。單叫數據庫或服務器都不全面。 二、組成 oracle數據庫服務器由二部份組成&#xff1a;實例和數據庫 實例&#xff1a; 可理解為對象&#xff0c;看不見。數據庫&#xff1a; 理解為類&#xff0c;看得見的&#xff0c;E:\app\Administrator\…

1.Dao代碼如何編寫?

Dao代碼如何編寫&#xff1f; 1、操作xml數據。數據保存在xml文件里。2、使用jdbc技術。2.1、原始的jdbc操作&#xff0c;connection&#xff0c;statement&#xff0c;resultset。2.2、自定義一個持久層的框架&#xff0c;封裝通用的dao操作方法。2.3、DbUtils組件&#xff0c…

WEB前端面試題匯總整理01

1.JS找字符串中出現最多的字符 例如&#xff1a;求字符串nininihaoa中出現次數最多字符 var str "nininihaoa"; var o {}; for (var i 0, length str.length; i < length; i) {var char str.charAt(i);if (o[char]) {o[char]; //次數加1} else {o[char] 1;…

c語言 文件游程統計,游程 碼表 如何形成

游程 碼表 如何形成求一個程序 將下表用huffman 樹存儲表示用傳統的霍夫曼建立的樹 好像不能形成此碼表。我感覺應該有一個特等的算法。我也試了好幾種方法&#xff0c;感覺都不行&#xff0c;希望大家給點建議。(碼表 要利于編碼和解碼)(部分碼表)白游程 碼子 黑游程 碼子(長…

用2468這四個數字c語言,C語言作業及參考答案.doc

C語言及實驗作業參考做法分支程序設計上機作業&#xff1a;標題4.3三角形判斷描述輸入三條邊的長&#xff0c;輸出這三條邊是否構成等邊三角形、等腰三角形、直角三角形、普通三角形&#xff0c;還是不能構成三角形輸入數據整數a,b,c的值輸出數據等邊三角形、等腰三角形、直角三…

C# WinForm開發系列 - GDI+【轉】

http://blog.csdn.net/blue_sky6/article/details/53811435?locationNum6&fps1 C# WinForm開發系列 - GDI Posted on 2009-07-19 15:23 peterzb 閱讀(48850) 評論(17) 編輯 收藏 UI&#xff08;User Interface&#xff09;編程在整個項目開發過程中是個頗為重要的環節&…

2.ORM思想

一、ORM思想介紹 orm是一種思想&#xff0c;是dao層代碼的一種編寫思想。其中&#xff1a;o代表Object&#xff0c;java對象&#xff1b;r代表Relation&#xff0c;關系型數據庫&#xff1b;m代表Map&#xff0c;java對象和關系型數據庫表的映射關系。該思想主張&#xff1a;1、…

android 字體顏色選擇,Android中顏色選擇器和改變字體顏色的實例教程

易采站長站為您分析Android中顏色選擇器和改變字體顏色的實例教程,其中改變字體顏色用到了ColorPicker顏色選擇器,需要的朋友可以參考下1.構建一張七彩圖:我們經常看到這種樣子的顏色選擇器吧..然后其實右邊的亮度選擇是:這樣我們的代碼就可以進行啦...// 創建七彩圖片private …

3.hello hibernate

一、Hibernate的開發步驟 1、引入jar文件2、配置3、apihibernate的映射文件的配置是不容易的&#xff0c;是重點學習的地方。二、Hello Hibernate 1、數據庫表準備 數據庫名 &#xff1a;test表&#xff1a;DROP TABLE IF EXISTS users; CREATE TABLE users (id int(11) NOT N…

無法連接oralce問題(不斷更新)

1、oracle自帶的sqlplus能連接&#xff0c;但第三方工具如plsqldev不能連接 解決方法&#xff1a;1、確認listener.ora&#xff0c;tnsnames.ora配置文件中的host地址一致。且&#xff1a;listener.ora只能配置主機名。winr&#xff0c;cmd&#xff0c;hostname 獲取主機名。2、…

新版vue-cli搭建多頁面應用

2019獨角獸企業重金招聘Python工程師標準>>> 折騰了好久&#xff0c;終于把坑踩完了&#xff0c;廢話不多說&#xff0c;上教程~ github地址&#xff1a;https://github.com/guolihuaGitHub/vue-cli-multipage 另外推薦一下我另一篇博客&#xff0c;我覺得這篇好用&…

android開發方法數,Android減少App方法數

作為Android開發者我們都知道Android應用方法數65535這樣一個限制&#xff0c;這是因為在Android系統中&#xff0c;方法的id使用short類型存儲在Dex文件中&#xff0c;而short類型的取值范圍是-32,768到32,767&#xff0c;因此導致Android應用方法數65535這樣一個最大限制&…

內表,外表

一、內表 Internal Table 內表與結構體基本類似&#xff0c;它同樣是程序運行中被臨時創建的一個存儲空間&#xff0c;它是一個可包含多條記錄的數據表。 二、外表 外表(external table)就像普通的表對像一樣&#xff0c;可以select等&#xff0c;只是它是只讀的&#xff0c;數…

國外分享插件

<script type"text/javascript" src"//s7.addthis.com/js/300/addthis_widget.js#pubidra-59effacb0a4e93a8"></script> addthis轉載于:https://www.cnblogs.com/ghfjj/p/8026946.html