原创

Apache Jackrabbit简介及入门

1.什么是JCR

1.1 JCR 是什么

Java Content Repository API(JSR-170)试图建立一套标准的API去访问内容仓库。 内容仓库可以理解为一个用来存储文本和二进制数据(图片,word文档,PDF等等)的数据存储应用程序。 你不用关心你真正的数据到底存储在什么地方,是关系数据库?是文件系统?还是XML? 通过JSR-170,你开发代码只需要引用 javax.jcr.* 这些类和接口。它适用于任何兼容JSR-170规范的内容仓库。 JSR-170 API对不同的人员提供了不同的好处 对于开发者无需了解厂家的仓库特定的API,只要兼容JSR-170就可以通过JSR-170访问其仓库。 对于使用CMS的公司则无需花费资金用于在不同种类CMS的内容仓库之间进行转换。 对于CMS厂家,无需自己开发内容仓库,而专注于开发CMS应用。

1.2 JCR的内容仓库模型

JCR的内容仓库是一个树状结构 树上的元素(Item)分为两类:节点(node)和属性(property)。 1个节点:有且只有一个父亲,有任意数目的孩子(子节点)和任意数目的属性。 1个属性:有且只有一个父亲(节点),它没有子节点,由一个名字和一个或多个值组成。 属性值的类型可以是:布尔(Boolean)、日期(Date)、双精度(Double)、长整型(Long)、字符串(String)或流(Stream)。 属性可以被用来存储信息,节点则被用来创建树内部的“路径”(类似文件系统的结构,节点是目录,属性是实际的文件)

在这里插入图片描述

由于JCR的节点和属性具有很多相同的特性,因此它们都实现了Item接口中定义的通用方法,此外它们还添加了各自特有的功能方法。下图是JCR树状数据存储模型的UML结构图

在这里插入图片描述

除了 Node 和 Property 之外,API中还有几个重要的对象。Repository 代表整个内容仓库,Credentials 代表一个用户身份,Ticket 代表进入该内容仓库的门票。

2.什么是Jackrabbit

JackRabbit就是一种面向文档的数据库,它和MongoDB,CouchDB的功能十分接近,优势在于JackRabbit遵从JCR标准,日后可以迁移到其他同样兼容JCR的性能更好的商业解决方案上。 Jackrabbit(内容仓库)是一个高级的信息管理系统,该系统是传统的数据仓库的扩展,它提供了诸如版本控制、全文检索、访问控制、内容分类、内容事件监视等内容服务。Jackrabbit里面有一个DataStore类,该类有两个实现,DbDataStore和FileDataStore,可以保存元数据和二进制数据。

3.使用Jackrabbit

3.1 配置Jackrabbit环境

引入依赖
<dependencies> 
 <!-- The JCR API --> 
 <dependency> 
 <groupId>javax.jcr</groupId> 
 <artifactId>jcr</artifactId> 
 <version>2.0</version> 
 </dependency> 

 <!-- Jackrabbit content repository --> 
 <dependency> 
 <groupId>org.apache.jackrabbit</groupId> 
 <artifactId>jackrabbit-core</artifactId> 
 <version>2.12.1</version>
 </dependency> 

 <!-- Use Log4J for logging --> 
 <dependency> 
 <groupId>org.slf4j</groupId> 
 <artifactId>slf4j-log4j12</artifactId> 
 <version>1.5.11</version> 
 </dependency> 
</dependencies>
配置仓库repository.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<Repository>
 <FileSystem
 class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
 <param name="path" value="${rep.home}/repository"/>
 </FileSystem>
 <Security appName="Jackrabbit">
 <AccessManager
 class="org.apache.jackrabbit.core.security.
 SimpleAccessManager"/>
 </Security>
 <Workspaces
 rootPath="${rep.home}/workspaces"
 defaultWorkspace="default" />
 <Workspace name="${wsp.name}">
 <FileSystem
 class="org.apache.jackrabbit.core.fs.local.
 LocalFileSystem">
 <param name="path" value="${wsp.home}"/>
 </FileSystem>
 <PersistenceManager
 class="org.apache.jackrabbit.core.state.xml.
 XMLPersistenceManager" />
 <SearchIndex
 class="org.apache.jackrabbit.core.query.lucene.
 SearchIndex"> 
 <param name="path" value="${wsp.home}/index" />
 </SearchIndex>
 </Workspace>
 <Versioning rootPath="${rep.home}/versions">
 <FileSystem
 class="org.apache.jackrabbit.core.fs.local.
 LocalFileSystem">
 <param name="path" value="${rep.home}/versions"/>
 </FileSystem>
 <PersistenceManager
 class="org.apache.jackrabbit.core.state.xml.
 XMLPersistenceManager" />
 </Versioning>
</Repository>
初始化仓库
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.PROVIDER_URL, "localhost");
 
InitialContext ctx = new InitialContext(env);
 
RegistryHelper.registerRepository(ctx,
 "repo",
 configFile,
 repHomeDir,
 true);
 
Repository r = (Repository) ctx.lookup("repo");
登陆(需要以管理员的身份登陆,否则很多操作都没有权限,默认用户名和密码都是admin)
Session session = repository.login( 
 new SimpleCredentials("admin", "admin".toCharArray()));
注册工作区命名空间(非必须)
// 注册命名空间
 Workspace ws = session.getWorkspace();

3.2使用Jackrabbit

简单的CRUD操作
public static void main(String[] args) throws Exception { 
 Repository repository = JcrUtils.getRepository();
 Session session = repository.login( 
 new SimpleCredentials("admin", "admin".toCharArray()));
 try { 
 Node root = session.getRootNode(); 

 // 存储内容 
 Node hello = root.addNode("hello"); 
 Node world = hello.addNode("world"); 
 world.setProperty("message", "Hello, World!"); 
 session.save(); 

 // 检索内容
 Node node = root.getNode("hello/world"); 
 System.out.println(node.getPath()); 
 System.out.println(node.getProperty("message").getString()); 

 // 删除内容 
 root.getNode("hello").remove(); 
 session.save(); 
 } finally { 
 session.logout(); 
 } 
 }
将xml文件存入
public static void main(String[] args) throws Exception { 
 Repository repository = JcrUtils.getRepository();
 Session session = repository.login( 
 new SimpleCredentials("admin", "admin".toCharArray()));
 try { 
 Node root = session.getRootNode(); 

 // 导入XML文件,除非已经导入
 if (!root.hasNode("importxml")) { 
 System.out.print("Importing xml... "); 

 // 创建一个node在其下导入XML
 Node node = root.addNode("importxml", "nt:unstructured"); 

 // 将文件“ test.xml”导入到创建的节点下
 FileInputStream xml = new FileInputStream("test.xml");
 session.importXML( 
 node.getPath(), xml, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW); 
 xml.close();
 session.save(); 
 System.out.println("done."); 
 } 

 //输出存储库内容
 dump(root); 
 } finally { 
 session.logout(); 
 } 
 }
输入存储内容
private static void dump(Node node) throws RepositoryException { 
 // 首先输出节点路径
 System.out.println(node.getPath()); 
 // 跳过这个虚拟子树
 if (node.getName().equals("jcr:system")) { 
 return; 
 } 

 // 输出属性
 PropertyIterator properties = node.getProperties(); 
 while (properties.hasNext()) { 
 Property property = properties.nextProperty(); 
 if (property.getDefinition().isMultiple()) { 
 // 多值属性,打印所有值
 Value[] values = property.getValues(); 
 for (int i = 0; i < values.length; i++) { 
 System.out.println( 
 property.getPath() + " = " + values[i] .getString()); 
 } 
 } else { 
 // 单值属性
 System.out.println( 
 property.getPath() + " = " + property.getString()); 
 } 
 } 

 // 最后以递归方式输出所有子节点
 NodeIterator nodes = node.getNodes(); 
 while (nodes.hasNext()) { 
 dump(nodes.nextNode()); 
 } 
 }
参考文章
Jackrabbit的来源
Apache Jackrabbit学习
Apache Jackrabbit入门
Java Content Repository API 简介
Apache Jackrabbit官方文档
正文到此结束
Loading...