`
duyangsss
  • 浏览: 127475 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

[转载]Spring与JCR集成

 
阅读更多
原文档地址:http://www.infoq.com/cn/articles/spring-modules-jcr
Spring Modules的一部分,JCR模块的主要目标是:以一种类似Spring主分发包中ORM包的方式,简化使用JSR-170 API进行开发。特点如下:

JcrTemplate,允许执行JcrCallback和异常处理(将需检查的JCR异常转换成不需检查的Spring DAO异常)。这个模板实现了来自JCR Session的绝大部分方法,可以简单地作为替换物使用。此外该模板知道线程绑定的会话,这个会话可以跨几个方法使用,这在使用事务型仓库时非常有用。
RepositoryFactoryBean,它配置、启动和停止仓库实例。因为JSR-170并没有说明仓库配置的标准方式,需要注意实现在这个方面的不同。这个支持包含预定义的用于Jackrabbit和Jeceira的FactoryBean,以及一个可以很容易支持其它仓库的抽象基类。
SessionFactory,用来统一Repository,Credentials和Workspace接口,允许自动注册监听器和自定义名字空间。
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语句块(因为IO和Repository的需检查异常)和处理会话(和事务,如果有的话)清除工作中解放出来。值得提及的是硬编码字符串,如“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>

transactionRepository bean可以被用作一个普通的JCR仓库,不关心底层机制或线程绑定会话、事务性或非事务性(如果有事务,关闭会话时要提交事务)。

可选特性支持侦测

为了最大化代码重用,但仍然允许插入可选特性,如用于不同JCR实现的事务支持,JCR模块使用SessionHolder接口(前面已经提到),同时还有SessionHolderProvider和SessionHolderProviderManager接口。用户一般不用与它们打交道,因为它们是框架内部使用的;但是,它们代表了JCR模块主要的扩展点。

SessionHolder类被内部不同组件使用,主要被事务管理器用来操作会话,SessionHolderProvider和SessionHolderProviderManager处理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
缺省,SessionHolderProviderManager被JcrSessionFactory内部使用,因此在工厂启动时,任何客户化实现可以被获取,并与合适的仓库一起使用。但是,通过设置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>

注意,每个仓库一个提供者。如果列表包含多个工作于同一仓库的提供者,顺序将非常重要,因为先匹配的先使用。
备注:由于原文档所提供的下载地址无法访问https://springmodules.dev.java.net/(原因不清楚,可能是我公司所使用的网络有问题),所以从其它网站找到了相关的jar包,有需要的朋友可以直接下载哦。
补充:备注中所访问的地址确实无效了,项目还有一个GIT地址可以访问:https://github.com/astubbs/spring-modules
分享到:
评论

相关推荐

    将Spring与JBPM集成.txt

    本文旨在深入探讨如何实现Spring与JBPM的集成,以及这一过程所需的必要组件和配置步骤。 ### Spring与JBPM集成的重要性 Spring框架以其依赖注入(DI)和面向切面编程(AOP)的能力而闻名,为Java开发者提供了一个...

    SCIE与JCR使用指南

    ### SCIE与JCR使用指南 #### 一、SCIE与JCR简介 - **SCIE**(Science Citation Index Expanded)是科学引文索引扩展版,是全球最重要的科学文献索引之一,由美国汤森路透集团维护,提供科技领域内高质量的学术资源...

    JCR的2.0版规范

    - **类型与结构**: JCR定义了一系列预定义的节点类型和属性类型,如文件、图像等,这些类型定义了节点和属性的数据结构。 - **行为**: 包括节点的创建、删除、移动等操作,以及属性的设置、更新等。 ##### 2.2 连接...

    JCR2015分区与影响因子

    中科院2015年JCR分区与SCI影响因子

    spring定时任务关键jar包(齐全)

    5. **Quartz和Commons JCR支持**: Spring还提供了对Quartz(一个强大的开源作业调度库)和Apache Commons JCR(Java Content Repository API)的集成,如果你的项目需要更复杂的工作调度,可以使用这些库。...

    JCR用户培训手册

    #### 六、JCR版权与商标声明 - JCR及相关产品名称均为Thomson Scientific公司的注册商标。 - 用户在组织内部可复制使用培训指南,但必须保留版权信息。 通过以上内容的详细介绍,读者可以更全面地理解JCR的作用、...

    jcr_in_action.pdf

    ### JCR与Apache Jackrabbit JCR是一种标准接口,用于管理结构化和非结构化的数字内容,如文档、图像和其他媒体文件。它提供了对存储库(repository)的操作,包括存储、检索、搜索、版本控制、事务处理和观察等...

    JCR 170 文档

    2. **Java技术规范**:JCR API是根据Java技术规范设计的,确保其与Java环境的无缝集成。 3. **Swappability(可互换性)**:JCR允许不同的内容管理系统之间进行数据交换,无需修改应用程序代码。 4. **资源压缩...

    2022JCR最新发布-期刊影响力表-0628.xlsx

    JCR,即Journal Citation Reports(期刊引证报告),每年6月下旬由科睿唯安发布。 那么,到底什么是JCR,其中又包含哪些内容呢? 首先,是JCR的收录范围。 JCR创办之初,仅包含SCI期刊,后来陆续引入SSCI和AHCI...

    2011JCR分区表

    JCR分区表,助力科研,很有用的啊 ,Excel格式很有参考价值

    重磅!2022年JCR正式发布(附最新影响因子名单),前600

    2022年JCR正式发布(附最新影响因子名单) 重磅!2022年JCR正式发布(附最新影响因子名单,前600) 重磅!2022年JCR正式发布(附最新影响因子名单) 重磅!2022年JCR正式发布(附最新影响因子名单) 重磅!2022年JCR...

    2015年SCI影响因子与JCR分区

    2015年SCI期刊影响因子及JCR分区,包括 期刊名缩写、ISSN号、总被引次数、影响因子、5年期影响因子、即年指数、论文数量、半衰期、特征因子、论文影响分值等~

    2022年6月28日JCR官网公布2022年完整版影响因子

    2022年6月28日JCR官网公布2022年完整版影响因子!2022年6月28日JCR官网公布2022年完整版影响因子! 完整版,总计2W+本期刊。

    Ei、SCI、JCR数据库检索.pdf

    Ei、SCI、JCR数据库检索 本文将详细介绍Ei、SCI、JCR三个主要的数据库检索系统,分别介绍它们的发展历程、收录范围、数据库特点和使用方法。 一、Ei(Engineering Index) Ei,即 Engineering Index,创办于1884...

    JCR-2.0.jar

    JCR-2.0.JARJCR-2.0.JARJCR-2.0.JARJCR-2.0.JARJCR-2.0.JARJCR-2.0.JARJCR-2.0.JARJCR-2.0.JARJCR-2.0.JARJCR-2.0.JARJCR-2.0.JARJCR-2.0.JARJCR-2.0.JAR

    abdera-jcr-1.0.jar

    标签:abdera-jcr-1.0.jar,abdera,jcr,1.0,jar包下载,依赖包

    2022JCR最新发布 期刊影响因子 前600.xlsx

    JCR,即Journal Citation Reports(期刊引证报告),每年6月下旬由科睿唯安发布。 那么,到底什么是JCR,其中又包含哪些内容呢? 首先,是JCR的收录范围。 JCR创办之初,仅包含SCI期刊,后来陆续引入SSCI和AHCI...

    2020年最新JCR分区.xlsx

    2020年6月29日,科睿唯安发布的2019年期刊引证报告(Journal Citation Reports, JCR)。

    JCR.rar_jackrabbit_jcr

    Jackrabbit提供了一套API,使得开发者能够轻松地与JCR系统交互。例如,`Session`接口用于用户登录和工作空间管理,`Workspace`接口用于处理工作空间内的节点,`Node`接口代表一个内容节点,而`Property`接口则表示...

Global site tag (gtag.js) - Google Analytics