0


开源DMS文档管理系统 Nuxeo Vs Alfresco对比及 API 使用概述

1. 文档管理系统是什么

文档管理系统(DMS:Document Management System)是一种软件系统,用于组织、存储、检索和管理电子文档和文件。这些文件可以是各种格式的电子文档,如文本文档、电子表格、图像、音频或视频文件等。

DMS的主要功能通常包括:

  • 文档存储和组织:DMS允许用户将文档上传到系统中,并按照特定的分类或标签进行组织和存储,使用户能够轻松找到所需的文件。
  • 版本控制:DMS通常具有版本控制功能,允许用户跟踪文档的不同版本,并查看文档的修改历史。这对于团队协作和审查流程非常有用。
  • 访问控制:DMS允许管理员设置不同用户或用户组的访问权限,以确保只有授权的人员可以查看、编辑或删除特定文档。
  • 搜索和检索:DMS通常具有强大的搜索功能,允许用户根据关键字、日期、作者等条件快速检索所需的文档。
  • 工作流管理:一些DMS还提供工作流功能,允许用户定义和管理文档处理过程,包括审批、审核和分发。
  • 安全性和备份:DMS通常提供安全性功能,如数据加密、安全审计和备份,以确保文档的安全性和完整性。

总的来说,文档管理系统帮助组织更有效地管理和利用其电子文档和文件,提高工作效率,减少错误,并促进团队协作和知识共享。大家熟知的飞书文档、钉钉文档、企业微信文档、华为云文档等都属于DMS的范畴。

即使是不了解DMS的同学,通过上面的介绍也可以感觉到DMS相对比较复杂和庞大,因此完全0-1去建设一个DMS的话,相关的工作量还是比较大的(需要先搞定分布式存储、分布式文件系统、工作流等基础能力后才能将他们整合成为一个DMS),因此选择开源DMS成为了一个捷径,目前知名的基于Java的开源DMS有:

  • Alfresco :Alfresco是一种成熟的企业级DMS平台,提供了丰富的功能,包括文档管理、工作流、版本控制等。Alfresco Community Edition是其开源版本,可以免费使用。
  • Nuxeo :Nuxeo是一个灵活的企业级内容管理平台,提供了强大的文档管理和协作功能。Nuxeo Platform是其开源版本,基于Java开发。
  • Liferay Portal:Liferay Portal是一个用于构建企业门户和社交协作平台的开源解决方案。它提供了文档管理、协作、工作流等功能,并且是基于Java的。
  • OpenKM:OpenKM是一个功能强大的开源文档管理系统,提供了文档存储、检索、版本控制等功能,基于Java语言开发。

2. Nuxeo Vs Alfresco 选型对比

建议:Nuxeo 和 Alfresco 在功能方面都提供了类似的核心文档管理和协作功能,并且都是社区版开源免费以及都提供了较好的REST
API,但是从部署上来说Nuxeo更加迎合传统App建设现状,同时Nuxeo在Github上热度及更新频度远高于Alfresco,并且Nuxeo对于二开定制化更好(SDK支持类型广,二开遵循一切接插件的思想等),而 Alfresco 则强调开箱即用,如果优先考虑二开建议选择Nuxeo。

2.1 开源协议对比

两者都是社区版开源免费(使用Apache 2.0 许可证,允许用户自由使用、修改和分发),企业版收费。

2.2 产品功能对比

Nuxeo 和 Alfresco 在功能方面都提供了类似的文档管理和协作功能。

2.3 Github项目热度对比 (Nuxeo热度及最近更新时间都优)

2.4 API 及文档支持对比

两者在REST API方面都很强大,可以满足大多数内容管理需求。Nuxeo 的 REST API 更加注重简单和直接,而 Alfresco 的 REST API 功能覆盖全面,并且有CMIS标准的支持。

  • Alfresco 文档地址:https://docs.alfresco.com/ CMIS 标准:提供了一个通用的API,使得不同的内容管理系统能够互操作和数据交换,解决了系统间的兼容性问题。–对于我们可能意义不大,目前没有对接多个DMS系统的需求;
  • Nuxeo 文档地址:https://doc.nuxeo.com/ Nuxeo Automation API 是Nuxeo平台提供的一个高级API,旨在简化复杂的业务逻辑和工作流操作。它允许开发者通过预定义的操作(Operations)和链(Chains)来自动化各种内容管理任务。通过Nuxeo的Automation API,可以用简单的配置文件来定义和执行这些步骤,而不需要编写复杂的代码。 --有一定意义

2.5 SDK 对比

Nuxeo 和 Alfresco 在使用文档和技术支持方面表现基本相当,并且都没有提官方中文文档。

2.6 性能对比

Nuxeo 和 Alfresco 在性能方面都做出了努力,并且都提供了一系列性能优化和监控工具。
两者的架构设计都具有良好的可扩展性,可以根据需求灵活扩展和部署。都支持横向扩容。

2.7 部署对比

2.7.1 数据库支持

Nuxeo 和 Alfresco 目前并未官方支持 TiDB,但是都支持 PostgreSQL、MySQL等;

2.7.2 文件存储支持

Nuxeo 和 Alfresco都使用数据库来存储文档内容和元数据,也支持对接云存储,如:Amazon S3、Microsoft Azure Blob Storage、Google Cloud Storage 等,但是都不支持阿里OSS。

2.7.3其他依赖中间件

核心功能都是基于 Java 编写的,它通常作为一个独立的应用程序部署,不需要额外的中间件,都包含了内置的嵌入式 Web 容器。根据具体的部署需求,都可能会依赖于其他一些组件。

  • Nuxeo 如 Elasticsearch(用于全文搜索)、Kafka(用于异步处理)、Redis(用于缓存) Nuxeo 的工作流引擎是基于 Java 自研的,该引擎是 Nuxeo 平台的一部分。
  • Alfresco Solr(用于全文搜索)、Apache ActiveMQ(用于消息队列)、CIFS/SMB(用于 Windows 文件共享)等。 Alfresco内置工作流引擎(如Activiti),支持自定义业务流程。

2.8 定制和扩展对比(Alfresco主打开箱即用、Nuxeo主打高扩展性)

如果需要高度定制化、高扩展性,并且有能力处理复杂的技术架构和二次开发,Nuxeo 可能更适合你的需求。
如果需要快速部署、开箱即用、稳定成熟的功能和良好的技术支持,尤其是有企业级支持需求,Alfresco 可能是更好的选择。

2.9 其他

目前Nuxeo和Alfresco均不支持对文档特定部分进行注释,如果将来要支持该功能一定涉及二开;

3. Nuxeo API/SDK 调研

  • API 查看某个Nuxeo实例下所有 API 及 API Doc 方法: http://{serverRoot}/nuxeo/api/v1/automation/doc在这里插入图片描述
  • SDK (文档地址:https://doc.nuxeo.com/client-java/3.14/) nuxeo-java-client 只能从Nuxeo的Maven仓库进行加载,建议下载之后手工传到自己的私服仓库中,maven依赖如下:
<dependency><groupId>org.nuxeo.client</groupId><artifactId>nuxeo-java-client</artifactId><version>3.14.0</version></dependency>

Nuxeo的Maven仓库地址:

<repository><id>public-releases</id><name>nuxeo</name><url>https://packages.nuxeo.com/repository/maven-public</url></repository>

Nuxeo Java SDK 外部依赖较多,测试是否少依赖可以运行以下代码确认:

packagecom.beem.nuxeo.demo.sdk.test;importorg.junit.After;importorg.junit.Assert;importorg.junit.Before;importorg.junit.Test;importorg.junit.runner.RunWith;importorg.mockito.junit.MockitoJUnitRunner;importorg.nuxeo.client.NuxeoClient;importorg.nuxeo.client.objects.user.User;importstaticcom.beem.nuxeo.demo.sdk.NuxeoConstant.*;/**
 * SdkBaseTest
 *
 * @author chenx
 */@RunWith(MockitoJUnitRunner.class)publicclassSdkBaseTest{
   privateNuxeoClient client;@Beforepublicvoidbefore(){
   this.client =newNuxeoClient.Builder().url(BASE_URL_NUXEO).authentication(USER_NAME_NUXEO_ADMIN,PASSWORD_NUXEO_ADMIN).schemas("*").connect();}@Afterpublicvoidafter(){
   this.client.disconnect();}@TestpublicvoidbaseTest(){
   User user =this.client.getCurrentUser();System.out.println(user.getUserName());Assert.assertNotNull(user);}}

3.1 API 鉴权

**建议:开发过程中建议使用Nuxeo SDK,这样默认使用OAuth方式鉴权;特殊情况下可以自己写Http请求并使用基础鉴权方式。

3.1.1 Basic Authentication

在请求头中包含用户名和密码的Base64编码;

3.1.2 OAuth 2.0

1、注册客户端:首先在Nuxeo管理界面注册一个OAuth客户端应用,获取客户端ID和客户端密钥。
2、获取授权码:引导用户访问授权URL,获取授权码。
3、交换访问令牌:使用授权码换取访问令牌。
4、使用访问令牌:在API请求中使用访问令牌。

3.1.3 Session Authentication

首先通过登录接口获取会话,然后在随后的请求中包含会话ID。

3.1.4 API Key

Nuxeo允许为用户创建API密钥,这些密钥可以用于鉴权。

3.1.5 自定义插件鉴权

开发一个 Nuxeo 插件,以支持基于手机短信验证码的认证方式。该插件可以与您的用户体系进行集成,验证用户的身份。

3.2 用户

3.2.1 创建用户

  • Http请求示例
POST /nuxeo/api/v1/user HTTP/1.1
Authorization: Basic QWRtaW5pc3RyYXRvcjpBZG1pbmlzdHJhdG9y
User-Agent: okhttp/3.14.4 NuxeoJavaClient/3.14.0
Content-Type: application/json;charset=UTF-8
Content-Length: 320
Host: 172.30.1.176:8080
Connection: Keep-Alive
Accept-Encoding: gzip{
   "id":null,"properties":{
   "password":"password123","username":"newuser3"},"extendedGroups":[],"password":"password123","firstName":null,"company":null,"groups":null,"administrator":false,"email":null,"anonymous":false,"lastName":null,"entity-type":"user","isAdministrator":false,"isAnonymous":false,"username":"newuser3"}

HTTP/1.1 201 
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
X-UA-Compatible: IE=10;IE=11
Cache-Control: no-cache
X-Content-Type-Options: nosniff
Content-Security-Policy: img-src data: blob: *; default-src blob: *; script-src 'unsafe-inline''unsafe-eval' data: *; style-src 'unsafe-inline' *; font-src data: *
X-XSS-Protection: 1;mode=block
Content-Type: application/json; nuxeo-entity=user
Transfer-Encoding: chunked
Date: Thu, 23 May 2024 09:15:03 GMT
Keep-Alive: timeout=20
Connection: keep-alive

e4
{
   "entity-type":"user","id":"newuser3","properties":{
   "firstName":null,"lastName":null,"tenantId":null,"groups":[],"company":null,"email":null,"username":"newuser3"},"extendedGroups":[],"isAdministrator":false,"isAnonymous":false}0
  • JDK 示例
@TestpublicvoidcreateUserTest(){
   User newUser =newUser();
    newUser.setUserName("newuser3");
    newUser.setPassword("password123");UserManager userManager =this.client.userManager();User createdUser = userManager.createUser(newUser);String userId = createdUser.getId();System.out.println("User created successfully with ID: "+ userId);Assert.assertTrue(true);}

3.2.2 查找用户

  • Http请求示例
GET /nuxeo/api/v1/user/newuser2 HTTP/1.1
Authorization: Basic QWRtaW5pc3RyYXRvcjpBZG1pbmlzdHJhdG9y
Content-Type: application/json;charset=UTF-8
User-Agent: okhttp/3.14.4 NuxeoJavaClient/3.14.0
Host: 172.30.1.176:8080
Connection: Keep-Alive
Accept-Encoding: gzip

HTTP/1.1 200 
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
X-UA-Compatible: IE=10;IE=11
Cache-Control: no-cache
X-Content-Type-Options: nosniff
Content-Security-Policy: img-src data: blob: *; default-src blob: *; script-src 'unsafe-inline''unsafe-eval' data: *; style-src 'unsafe-inline' *; font-src data: *
X-XSS-Protection: 1;mode=block
Content-Type: application/json; nuxeo-entity=user
Transfer-Encoding: chunked
Date: Thu, 23 May 2024 09:03:52 GMT
Keep-Alive: timeout=20
Connection: keep-alive

e4
{
   "entity-type":"user","id":"newuser2","properties":{
   "firstName":null,"lastName":null,"tenantId":null,"groups":[],"company":null,"email":null,"username":"newuser2"},"extendedGroups":[],"isAdministrator":false,"isAnonymous":false}0
  • JDK 示例
@TestpublicvoidgetUserTest(){
   String username ="newuser2";UserManager userManager =this.client.userManager();// 如果找不到:NuxeoClientRemoteException: HTTP/404: user does not existUser user = userManager.fetchUser(username);System.out.println("User found with username: "+ user.getUserName());Assert.assertTrue(true);}

3.2.3 删除用户

  • Http请求示例
DELETE /nuxeo/api/v1/user/newuser1 HTTP/1.1
Authorization: Basic QWRtaW5pc3RyYXRvcjpBZG1pbmlzdHJhdG9y
Content-Type: application/json;charset=UTF-8
User-Agent: okhttp/3.14.4 NuxeoJavaClient/3.14.0
Host: 172.30.1.176:8080
Connection: Keep-Alive
Accept-Encoding: gzip

HTTP/1.1 204 
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
X-UA-Compatible: IE=10;IE=11
Cache-Control: no-cache
X-Content-Type-Options: nosniff
Content-Security-Policy: img-src data: blob: *; default-src blob: *; script-src 'unsafe-inline''unsafe-eval' data: *; style-src 'unsafe-inline' *; font-src data: *
X-XSS-Protection: 1;mode=block
Content-Type: application/json
Date: Tue, 28 May 2024 07:28:43 GMT
Keep-Alive: timeout=20
Connection: keep-alive
  • JDK 示例
@TestpublicvoiddeleteUserTest(){
   String username ="newuser1";UserManager userManager =this.client.userManager();
    userManager.deleteUser(username);System.out.println("deleteUser with username: "+ username);Assert.assertTrue(true);}

3.3 组

在Nuxeo中通过将用户添加到组,然后将权限分配给组,可以简化权限管理,同时一个用户可以加入多个不同的组。

在 Nuxeo 中,可以分配的权限类型主要包括以下几种:

  • Read:允许用户查看文档,但不能进行修改。
  • Write:允许用户修改文档,但不能删除文档。
  • Remove:允许用户删除文档。
  • ReadWrite:允许用户查看和修改文档,但不能删除文档。这实际上是将 Read 和 Write 权限组合在一起。
  • Everything:允许用户执行所有操作,包括查看、修改、删除文档等。实际上,这相当于管理员权限。
  • Manage Everything:允许用户管理所有内容和权限。这是最高权限,通常分配给管理员角色。

3.3.1 创建组

  • Http请求示例
POST /nuxeo/api/v1/group HTTP/1.1
Authorization: Basic QWRtaW5pc3RyYXRvcjpBZG1pbmlzdHJhdG9y
User-Agent: okhttp/3.14.4 NuxeoJavaClient/3.14.0
Content-Type: application/json;charset=UTF-8
Content-Length: 124
Host: 172.30.1.176:8080
Connection: Keep-Alive
Accept-Encoding: gzip{
   "memberUsers":null,"memberGroups":null,"parentGroups":null,"entity-type":"group","groupname":"newGroup2","grouplabel":null}

HTTP/1.1 201 
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
X-UA-Compatible: IE=10;IE=11
Cache-Control: no-cache
X-Content-Type-Options: nosniff
Content-Security-Policy: img-src data: blob: *; default-src blob: *; script-src 'unsafe-inline''unsafe-eval' data: *; style-src 'unsafe-inline' *; font-src data: *
X-XSS-Protection: 1;mode=block
Content-Type: application/json; nuxeo-entity=group
Transfer-Encoding: chunked
Date: Thu, 23 May 202411:08:15 GMT
Keep-Alive: timeout=20
Connection: keep-alive

b5
{
   "entity-type":"group","groupname":"newGroup2","grouplabel":"newGroup2","id":"newGroup2","properties":{
   "tenantId":null,"description":null,"grouplabel":null,"groupname":"newGroup2"}}0
  • JDK 示例
@TestpublicvoidcreateGroupTest(){
   UserManager userManager =this.client.userManager();Group newGroup =newGroup();
    newGroup.setGroupName("newGroup2");
    newGroup.setGroupLabel("测试组2");Group createdGroup = userManager.createGroup(newGroup);System.out.println("Group created: "+ createdGroup.getGroupName());Assert.assertTrue(true);}

3.3.2 删除组

  • Http请求示例
DELETE /nuxeo/api/v1/group/newGroup1 HTTP/1.1
Authorization: Basic QWRtaW5pc3RyYXRvcjpBZG1pbmlzdHJhdG9y
Content-Type: application/json;charset=UTF-8
User-Agent: okhttp/3.14.4 NuxeoJavaClient/3.14.0
Host: 172.30.1.176:8080
Connection: Keep-Alive
Accept-Encoding: gzip

HTTP/1.1 204 
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
X-UA-Compatible: IE=10;IE=11
Cache-Control: no-cache
X-Content-Type-Options: nosniff
Content-Security-Policy: img-src data: blob: *; default-src blob: *; script-src 'unsafe-inline''unsafe-eval' data: *; style-src 'unsafe-inline' *; font-src data: *
X-XSS-Protection: 1;mode=block
Date: Mon, 27 May 2024 03:21:10 GMT
Keep-Alive: timeout=20
Connection: keep-alive
  • JDK 示例
@TestpublicvoiddeleteGroupTest(){
   UserManager userManager =this.client.userManager();String groupName ="newGroup1";
    userManager.deleteGroup(groupName);System.out.println("Group deleted: "+ groupName);Assert.assertTrue(true);}

3.3.3 查找组

  • Http请求示例
HTTP/1.1 200 
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
X-UA-Compatible: IE=10;IE=11
Cache-Control: no-cache
X-Content-Type-Options: nosniff
Content-Security-Policy: img-src data: blob: *; default-src blob: *; script-src 'unsafe-inline''unsafe-eval' data: *; style-src 'unsafe-inline' *; font-src data: *
X-XSS-Protection: 1;mode=block
Content-Type: application/json; nuxeo-entity=group
Transfer-Encoding: chunked
Date: Mon, 27 May 2024 03:45:33 GMT
Keep-Alive: timeout=20
Connection: keep-alive

be
{
   "entity-type":"group","groupname":"newGroup3","grouplabel":".........3","id":"newGroup3","properties":{
   "tenantId":null,"description":null,"grouplabel":".........3","groupname":"newGroup3"}}0
  • JDK 示例
@TestpublicvoidgetGroupTest(){
   UserManager userManager =this.client.userManager();String groupName ="newGroup3";// 如果找不到则获得异常:NuxeoClientRemoteException: HTTP/404: group does not existGroup group = userManager.fetchGroup(groupName);System.out.println("Group not found with groupName: "+ group.getGroupName());Assert.assertTrue(true);}

3.3.4 用户加入组

  • Http请求示例
POST /nuxeo/api/v1/user/newuser2/group/newGroup3 HTTP/1.1
Authorization: Basic QWRtaW5pc3RyYXRvcjpBZG1pbmlzdHJhdG9y
Content-Type: application/json;charset=UTF-8
User-Agent: okhttp/3.14.4 NuxeoJavaClient/3.14.0
Content-Length: 0
Host: 172.30.1.176:8080
Connection: Keep-Alive
Accept-Encoding: gzip

HTTP/1.1 201 
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
X-UA-Compatible: IE=10;IE=11
Cache-Control: no-cache
X-Content-Type-Options: nosniff
Content-Security-Policy: img-src data: blob: *; default-src blob: *; script-src 'unsafe-inline''unsafe-eval' data: *; style-src 'unsafe-inline' *; font-src data: *
X-XSS-Protection: 1;mode=block
Content-Type: application/json; nuxeo-entity=user
Transfer-Encoding: chunked
Date: Mon, 27 May 2024 04:04:10 GMT
Keep-Alive: timeout=20
Connection: keep-alive

130{
   "entity-type":"user","id":"newuser2","properties":{
   "firstName":null,"lastName":null,"tenantId":null,"groups":["newGroup3"],"company":null,"email":null,"username":"newuser2"},"extendedGroups":[{
   "name":"newGroup3","label":".........3","url":"group/newGroup3"}],"isAdministrator":false,"isAnonymous":false}0
  • JDK 示例
@TestpublicvoiduserJoinGroupTest(){
   UserManager userManager =this.client.userManager();String username ="newuser2";String groupName ="newGroup3";
    userManager.addUserToGroup(username, groupName);System.out.println("User added to group done, username="+ username +", groupName="+ groupName);Assert.assertTrue(true);}

3.3.5 用户退出组

看起来不支持,官方用户和组的SDK介绍中只有:
Delete
APIs below are available to delete user/group:

  • deleteUser which takes a user name
  • deleteGroup which takes a group name Let’s delete our entities: userManager.deleteUser(“john”); userManager.deleteGroup(“myGroup”); 间接方法:修改群成员的的方式(管理后台抓包如下)
PUT /nuxeo/api/v1/group/newGroup3 HTTP/1.1
Host: 172.30.1.176:8080
Connection: keep-alive
Content-Length: 225
accept: text/plain,application/json, application/json
fetch-group: memberUsers,memberGroups
properties: *
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
Content-Type: application/json
Origin: http://172.30.1.176:8080
Referer: http://172.30.1.176:8080/nuxeo/ui/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=73917BF4464AE2CF70CD8F75DC480671.nuxeo;org.jboss.seam.core.TimeZone=Asia/Shanghai;nuxeo.start.url.fragment=!%2Fadmin%2Fuser-group-management%2Fgroup%2FnewGroup3

{
   "entity-type":"group","groupname":"newGroup3","grouplabel":".........3","id":"newGroup3","properties":{
   "tenantId":null,"description":null,"grouplabel":".........3","groupname":"newGroup3"},"memberUsers":[],"memberGroups":[]}

HTTP/1.1 200 
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
X-UA-Compatible: IE=10;IE=11
Cache-Control: no-cache
X-Content-Type-Options: nosniff
Content-Security-Policy: img-src data: blob: *; default-src blob: *; script-src 'unsafe-inline''unsafe-eval' data: *; style-src 'unsafe-inline' *; font-src data: *
X-XSS-Protection: 1;mode=block
Content-Type: application/json; nuxeo-entity=group
Transfer-Encoding: chunked
Date: Mon, 27 May 2024 06:42:05 GMT
Keep-Alive: timeout=20
Connection: keep-alive

e1
{
   "entity-type":"group","groupname":"newGroup3","grouplabel":".........3","id":"newGroup3","properties":{
   "tenantId":null,"description":null,"grouplabel":".........3","groupname":"newGroup3"},"memberUsers":[],"memberGroups":[]}0

借鉴管理后的思路,通过修改人的组属性一样可以做到将用户移出组,好处是一般来说人对应的组的数据量一般会少很多;

@Testpublic
标签: java 开源软件

本文转载自: https://blog.csdn.net/camelials/article/details/139301626
版权归原作者 BossFriday 所有, 如有侵权,请联系我们删除。

“开源DMS文档管理系统 Nuxeo Vs Alfresco对比及 API 使用概述”的评论:

还没有评论