# 1. 概述 数字对象体系(Digital Object Architecture,下面简称为DOA)是图灵奖得主、互联网发明人Robert E. Kahn提出的一种实现异构信息系统互操作的新型计算架构。 在DOA架构中,将信息资源抽象表示为数字对象(Digital Object,下面简称DO),所有的DO都存储在DO Repository中,并且支持通过数字对象接口协议(Digital Object Interface Protocol,下面简称DOIP)来对外提供服务。每一种DO具有全球可解析的唯一标识,可以通过标识与解析协议(Identifier/Resolution Protocol,下面简称IRP)向Handle System进行注册与解析。同时每一个DO也具有对该DO进行描述的元信息,元信息存储在DO Registry(一种特殊的DO Repository)中,也支持通过DOIP来对外提供服务。 根据上面的描述,在DOA架构中,有三种构件和两种协议。三种构件分别是:Handle System,DO Repository和DO Registry。两种协议分别是:DOIP和IRP。北京大学提供了DOIP和IRP的代码实现,并提供了用于开发DO Repository,DO Registry以及Client的软件开发工具包(Software Development Kit,简称SDK)。服务提供者,可以基于该SDK实现DO Repository和DO Registry功能。同时,我们提供用于对接国内主流Handle System提供者的支持代码,比如中数、中科院网络中心等。服务提供者可以基于该代码开发用于提供标识与解析的服务。最终使用者,可以基于Client的SDK开发基于DOA的应用程序。 # 2. 快速上手 ## 2.1 环境准备 相关的代码均采用Java编写,在使用相关代码前,请确保本地已经安装了JDK(>= Java 1.8)。 ## 2.2 下载示例代码 * LHSMock [v1.0](https://public.internetapi.cn/releases/doa/ri/lhsmock.zip) 提供一个模拟的标识/解析环境。 * example-Repository [v1.0](https://public.internetapi.cn/releases/doa/ri/repo.zip) 提供一个包含概念验证功能的数字对象仓库。 * example-Registry [v1.0](https://public.internetapi.cn/releases/doa/ri/regi.zip) 提供一个包含概念验证功能的数字对象注册表。 * example-Client [v1.0](https://public.internetapi.cn/releases/doa/ri/client.zip) 提供一个与数字对象仓库、数字对象注册表进行交互的客户端工具。 ## 2.3 运行代码 下载回来的示例代码是一个压缩包,解压后包含一个jar包和一些支持文件(里面包含示例代码运行需要使用的配置文件)。 ### 2.3.1 使用Client与Repository进行交互 1. 启动mockLHS 下载的压缩包解压后,得到如下目录和文件。 ```bash libs LHSMock-1.0.jar ``` 执行如下命令,开启模拟的标识解析服务。 ```bash java -jar LHSMock-1.0.jar [The actual rocksdb path:] D:\test\tmp\lhsmock\.\handleRecords ``` 2. 启动Respository 将Repository示例代码解压后,打开命令窗口,进入包含jar包的目录,此时目录内容如下: ```bash keys libs default_repo.json account.json SimpleRepository-1.0.jar ``` 执行如下命令,开启Repository: ```bash java -jar SimpleRepository-1.0.jar ``` 此时,命令行出现如下日志信息,表示Repository启动成功。 ```bash java -jar .\SimpleRepository-1.0.jar [INFO ]00:27:36.533 load config from: default_repo.json (DoipServiceConfig.java:22) [INFO ]00:27:38.514 [HandleService] response from LHS: 86.5000.470/Repository.Test.00 (SimpleRepositoryMain.java:123) [INFO ]00:27:38.728 DOIPServiceInfo: {"id":"86.5000.470/Repository.Test.00","serviceDescription":"local repository for test","publicKey":"{\"kty\":\"RSA\",\"n\":\"AIaJrbLDedKLMIFVaO9hHFhsJgZDCVQH2-QFvrArazIa4yGsR3rYSxqmYQFMTBfw-IP9Alx5LUKVeCbuo2rVlj26-DV4HAaCUnR6SfCZrasDQYiRqo2Hinv47-mWUImhH6lMzhi9jxggWLlfSrfDze3d9ijT_LGBYd0rfV84OIPjHjb5u9t0_Wxnegunvz9sDDsUJT2BZAmkN6lKdGWF9owm06b9BRnCCUetvsDAFjyH0clhPiBdwdoYJC1zQOe0qdeRzErp9A_OlUSKaojgKjjSpw52CPLMw7iJx_0v7i9qJrQhvt-2woZvaSWI9Y157hWLFW_dUX2ywuUveqCWa-s\",\"e\":\"AQAB\",\"use\":\"sig\"}","serviceName":"TestTLSRepository0","port":1718,"ipAddress":"127.0.0.1","protocol":"tls","protocolVersion":"2.0","listenerInfos":[{"url":"tls://127.0.0.1:1718","protocolVersion":"2.0","messageFormat":"delimiter"}],"owner":"86.5000.470/dou.SUPER0"} (DoipServerImpl.java:34) [INFO ]00:27:40.939 start at:1718 (NettyTLSDoipListener.java:63) ``` 3. 修改客户端配置文件 将Client示例代码解压后,打开命令窗口,进入包含jar包的目录,此时目录内容如下: ```bash libs Client-1.0.jar default_client.json default_client_regi.json default_client_repo.json ``` Client默认情况下使用default_client.json作为配置文件,配置文件的内容需要根据具体需要进行修改。如果要连接示例里面的Repository和Registry,请使用命令行参数-cf指定配置文件。(default_client_repo.json用于连接示例里面的Repository,default_client_regi.json用于连接示例里面的Registry)。 4. 使用Client发送操作请求 Client是一个DOIP客户端命令行工具,支持DOIP的7种基本操作。不加参数直接执行,会显示工具的帮助信息,如下: ``` java -jar .\Client-1.0.jar usage: DOIPCMDClient [-c ] [-cf ] [-d ] [-h] [-i] [-l] [-r ] [-s ] [-u ] basic doip operations to illustrate usage of the protocol -c,--create create do in doip repository/registry, e.g. create do: -c 86.5000.470/do.test DO message, create meta: -c 86.5000.470/do.test Meta description -cf,--config path to config file -d,--delete delete do in doip repository/registry, e.g. -d 86.5000.470/do.test -h display this help message -i,--hello get doip service information, e.g. -i -l,--list get repository/registry supported operations, e.g. -l -r,--retrieve retrieve do in doip repository/registry, e.g. -r 86.5000.470/do.test -s,--search search meta info in registry, e.g. -s key_word -u,--update update do in doip repository/registry, e.g. -u 86.5000.470/do.test DO new_message Please report issues at https://gitee.com/BDWare/doip-sdk.git ``` (1)发送hello操作请求 ``` java -jar .\Client-1.0.jar -i -cf .\default_client_repo.json [INFO ]16:56:32.280 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]16:56:34.777 client sending message: {"requestId":"1701103136","targetId":"86.5000.470/doip.localTcpRepo","operationId":"0.DOIP/Op.Hello","authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]16:56:35.353 client received message: {"requestId":"1701103136","status":"0.DOIP/Status.001"} # {"id":"86.5000.470/doip.localTcpRepo","type":"0.TYPE/DO.DOIPServiceInfo","attributes":{"serviceName":"TestMultiTransProtocol","serviceDescription":"test local Repository","owner":"86.5000.470/dou.SUPER","publicKey":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwUjtYUciJbdU5BYYFYykS33+1Wnm8KHf9+0/9EolcIWYro7xX8x9OHwF3nYu8xfhjjKo6Ma4WzI/ON5UO447eynCSKbvzJZV01rzuk03ED9rWfYQQyZrI6WyDtLAnwkG4ZJ+9ik75F+JF5YRHNb7bU0VU7FEtPS16uzF9twHi9JzZcfI8fwFKPO9Xzp6UagHzibIuRTLmU+Jl4jnzvU4MJsQlfcmyMM7VWM8oHCkd9NzC+XIr7GH/a3zcI8WEY9D1mLrwYR8UERd6rqSJ3W03O21s4+lLOGgGoRmtJERVqwK2TF789Fa7N9+9bZJJ3dAaP16iynHfOl5tb7Jmr4tLwIDAQAB","protocol":"tls","protocolVersion":"2.0","port":1718,"ipAddress":"127.0.0.1","listenerInfos":"[{\"url\":\"tls://127.0.0.1:1718\",\"protocolVersion\":\"2.0\",\"messageFormat\":\"delimiter\"}]","isSigned":"true"}} # {"bytesAlg":{"hashAlg":"SHA-256"},"signatures":{"payload":"eyJpZCI6Ijg2LjUwMDAuNDcwL2RvaXAubG9jYWxUY3BSZXBvIiwidHlwZSI6IjAuVFlQRS9ETy5ET0lQU2VydmljZUluZm8iLCJhdHRyaWJ1dGVzIjp7InNlcnZpY2VOYW1lIjoiVGVzdE11bHRpVHJhbnNQcm90b2NvbCIsInNlcnZpY2VEZXNjcmlwdGlvbiI6InRlc3QgbG9jYWwgUmVwb3NpdG9yeSIsIm93bmVyIjoiODYuNTAwMC40NzAvZG91LlNVUEVSIiwicHVibGljS2V5IjoiTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF3VWp0WVVjaUpiZFU1QllZRll5a1MzMysxV25tOEtIZjkrMC85RW9sY0lXWXJvN3hYOHg5T0h3RjNuWXU4eGZoampLbzZNYTRXekkvT041VU80NDdleW5DU0tidnpKWlYwMXJ6dWswM0VEOXJXZllRUXlackk2V3lEdExBbndrRzRaSis5aWs3NUYrSkY1WVJITmI3YlUwVlU3RkV0UFMxNnV6Rjl0d0hpOUp6WmNmSThmd0ZLUE85WHpwNlVhZ0h6aWJJdVJUTG1VK0psNGpuenZVNE1Kc1FsZmNteU1NN1ZXTThvSENrZDlOekMrWElyN0dIL2EzemNJOFdFWTlEMW1McndZUjhVRVJkNnJxU0ozVzAzTzIxczQrbExPR2dHb1JtdEpFUlZxd0syVEY3ODlGYTdOOSs5YlpKSjNkQWFQMTZpeW5IZk9sNXRiN0ptcjR0THdJREFRQUIiLCJwcm90b2NvbCI6InRscyIsInByb3RvY29sVmVyc2lvbiI6IjIuMCIsInBvcnQiOjE3MTgsImlwQWRkcmVzcyI6IjEyNy4wLjAuMSIsImxpc3RlbmVySW5mb3MiOiJbe1widXJsXCI6XCJ0bHM6Ly8xMjcuMC4wLjE6MTcxOFwiLFwicHJvdG9jb2xWZXJzaW9uXCI6XCIyLjBcIixcIm1lc3NhZ2VGb3JtYXRcIjpcImRlbGltaXRlclwifV0iLCJpc1NpZ25lZCI6InRydWUifX0","signatures":[{"protected":"eyJhbGciOiJSUzI1NiJ9","header":{"kid":"86.5000.470/dou.SUPER"},"signature":"fuoDyqZMElZ-8i5ptQ09TBz5AIp0wcVzoDVqECkmWPnjPMSVRCjpwaw6wqsRSqCMhKJbGPZn3GMmuFaybqa1S2daPq7WNw2-UpsdjqYE_uMNLrbtQNe-dz5PmBOK4gtmrNURLlofJqSWhw2vv6h0CnsIgqqN7r3IuuGglHU2QAdchywBf_FcgxGqJv3JuoGu_QGQpVufi0k1yD4ziVEs4_NN62_uZgkQXY7eSB-mzNKGv6c5WvF9-5Nm9Mej7KBHlFkNv30zx1SToYHCSc0xeXuTXfmyOzyO1W7piB1s6nZX47g5S5YysTytmdHm0OIlpcX6pqSVpSxx2oULl8oe8w"}]}} (DelimiterMessageClientCodec.java:85) ``` (2)发送listOperation操作请求 ``` java -jar .\Client-1.0.jar -l -cf .\default_client_repo.json [INFO ]16:56:54.083 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]16:56:56.385 client sending message: {"requestId":"-1340345561","targetId":"86.5000.470/doip.localTcpRepo","operationId":"0.DOIP/Op.ListOperations","authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]16:56:56.581 client received message: {"requestId":"-1340345561","status":"0.DOIP/Status.001","output":["0.DOIP/Op.Hello","0.DOIP/Op.ListOperations","0.DOIP/Op.Retrieve","0.DOIP/Op.Create","0.DOIP/Op.Update","0.DOIP/Op.Delete","0.DOIP/Op.Search","0.DOIP/Op.Extension","0.DOIP/Op.Unknown"]} (DelimiterMessageClientCodec.java:85) ``` (3)发送create操作请求 ``` java -jar .\Client-1.0.jar -c 86.5000.470/do.test01 DO hello -cf .\default_client_repo.json [INFO ]16:58:59.062 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]16:59:01.354 client sending message: {"requestId":"1646813081","targetId":"86.5000.470/doip.localTcpRepo","operationId":"0.DOIP/Op.Create","authentication":{"username":"admin","password":"password"}} # {"id":"86.5000.470/do.test01","type":"0.TYPE/DO","attributes":{"content":{"create":"hello","name":"create","description":"this is an example for create"}}} # # (DelimiterMessageClientCodec.java:35) [INFO ]16:59:01.548 client received message: {"requestId":"1646813081","status":"0.DOIP/Status.001"} # {"id":"86.5000.470/do.test01","type":"0.TYPE/DO","attributes":{"content":{"create":"hello","name":"create","description":"this is an example for create"}}} (DelimiterMessageClientCodec.java:85) ``` (4)发送update操作请求 ``` java -jar .\Client-1.0.jar -u 86.5000.470/do.test01 DO hello_update -cf .\default_client_repo.json [INFO ]16:59:36.850 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]16:59:39.151 client sending message: {"requestId":"-1386601504","targetId":"86.5000.470/do.test01","operationId":"0.DOIP/Op.Update","authentication":{"username":"admin","password":"password"}} # {"id":"86.5000.470/do.test01","type":"0.TYPE/DO","attributes":{"content":{"update":"hello_update","name":"update","description":"this is an example for update"}}} # # (DelimiterMessageClientCodec.java:35) [INFO ]16:59:39.338 client received message: {"requestId":"-1386601504","status":"0.DOIP/Status.001"} # {"id":"86.5000.470/do.test01","type":"0.TYPE/DO","attributes":{"content":{"update":"hello_update","name":"update","description":"this is an example for update"}}} (DelimiterMessageClientCodec.java:85) ``` (5)发送retrieve操作请求 ``` java -jar .\Client-1.0.jar -r 86.5000.470/do.test01 -cf .\default_client_repo.json [INFO ]17:00:05.143 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]17:00:07.485 client sending message: {"requestId":"1775903427","targetId":"86.5000.470/do.test01","operationId":"0.DOIP/Op.Retrieve","attributes":{"includeElementData":"true"},"authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]17:00:07.686 client received message: {"requestId":"1775903427","status":"0.DOIP/Status.001"} # {"id":"86.5000.470/do.test01","type":"0.TYPE/DO","attributes":{"content":{"update":"hello_update","name":"update","description":"this is an example for update"}}} (DelimiterMessageClientCodec.java:85) ``` (6)发送delete操作请求 ``` java -jar .\Client-1.0.jar -d 86.5000.470/do.test01 -cf .\default_client_repo.json [INFO ]17:00:22.094 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]17:00:24.340 client sending message: {"requestId":"-762527615","targetId":"86.5000.470/do.test01","operationId":"0.DOIP/Op.Delete","authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]17:00:24.491 client received message: {"requestId":"-762527615","status":"0.DOIP/Status.001"} (DelimiterMessageClientCodec.java:85) ``` (7)发送search操作请求 ``` java -jar .\Client-1.0.jar -s "hello" -cf .\default_client_repo.json [INFO ]17:01:09.654 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]17:01:11.913 client sending message: {"requestId":"1513536436","targetId":"86.5000.470/doip.localTcpRepo","operationId":"0.DOIP/Op.Search","attributes":{"query":"hello","pageNum":0,"pageSize":10,"type":"full","sortFields":"id:ASC"},"authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]17:01:12.078 client received message: {"requestId":"1513536436","status":"0.DOIP/Status.200","output":{"message":"Unsupported Operation!"}} (DelimiterMessageClientCodec.java:85) ``` __注意__:根据DOIP标准,Repository不支持search操作。 ### 2.3.2 使用Client与Registry进行交互 1. 启动mockLHS ```bash libs LHSMock-1.0.jar ``` 执行如下命令,开启模拟的标识解析服务。 ```bash java -jar LHSMock-1.0.jar [The actual rocksdb path:] D:\test\tmp\lhsmock\.\handleRecords ``` 2. 启动Registry 将Registry示例代码解压后,打开命令窗口,进入包含jar包的目录,此时目录内容如下: ```bash keys libs default_regi.json account.json SimpleRegistry-1.0.jar ``` 执行如下命令,开启Registry: ```bash java -jar SimpleRegistry-1.0.jar ``` 此时,命令行出现如下日志信息,表示Registry启动成功。 ```bash java -jar .\SimpleRegistry-1.0.jar [INFO ]00:29:27.019 load config from: default_regi.json (DoipServiceConfig.java:22) [INFO ]00:29:27.105 index path: index (DoIndexerLuceneImpl.java:39) [INFO ]00:29:29.626 [HandleService] response from LHS: 86.5000.470/Registry.Test (SimpleRegistryMain.java:135) [INFO ]00:29:29.649 DOIPServiceInfo: {"id":"86.5000.470/Registry.Test","serviceDescription":"local registry for test","publicKey":"{\"kty\":\"RSA\",\"n\":\"AJcJWZYZcmilUFcOMf-1d5qaSyAbchfmRL8Cu8QFsBOvG0xKK32yuLavb84AvB3mz7oy5lrKu8rooD2rs2hhMo8Mnj3qhUWYTpbuatm6pZy9YOKgzJo3DRZyUgUQuLlmSyh34rjM_HR_d9nYxImzbVhiAi4mQp9dErWJHF0lQfU30qMjxFzuIzoK8CHWgtf57TCzEaTP0gNO7mD3QKjC49kMy7RBoOu6EQBCag9YKfXcTysHRhFrCWBDyUTN49YNMS1-RU4a8YPgNXL7du2n2LpnFFnFk9c6fz_Zv2zyvts1WkLFhS6ZBjtfMJwavc1w2MaTtv_-8doOeeSreWNJiik\",\"e\":\"AQAB\",\"use\":\"sig\"}","serviceName":"TestTLSRegistry","port":1720,"ipAddress":"127.0.0.1","protocol":"tls","protocolVersion":"2.0","listenerInfos":[{"url":"tls://127.0.0.1:1720","protocolVersion":"2.0","messageFormat":"delimiter"}],"owner":"86.5000.470/dou.SUPER"} (DoipServerImpl.java:34) [INFO ]00:29:31.834 start at:1720 (NettyTLSDoipListener.java:63) ``` 3. 修改客户端配置文件 将Client示例代码解压后,打开命令窗口,进入包含jar包的目录,此时目录内容如下: ```bash libs Client-1.0.jar default_client.json default_client_regi.json default_client_repo.json ``` Client默认情况下使用default_client.json作为配置文件,配置文件的内容需要根据具体需要进行修改。如果要连接示例里面的Repository和Registry,请使用命令行参数-cf指定配置文件。(default_client_repo.json用于连接示例里面的Repository,default_client_regi.json用于连接示例里面的Registry)。 4. 使用Client发送操作请求 Client的基本用法,请参考2.3.1中的步骤3。与Registry交互过程中,需要注意的事项事:1. 创建DO时制定的类型需要为“Meta”;2. Registry支持search操作。 (1)发送hello操作 ```bash java -jar .\Client-1.0.jar -i -cf .\default_client_regi.json [INFO ]17:10:54.658 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]17:10:56.929 client sending message: {"requestId":"1632407099","targetId":"86.5000.470/dou.TEST","operationId":"0.DOIP/Op.Hello","authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]17:10:57.529 client received message: {"requestId":"1632407099","status":"0.DOIP/Status.001"} # {"id":"86.5000.470/dou.TEST","type":"0.TYPE/DO.DOIPServiceInfo","attributes":{"serviceName":"TestTLSRegistry","serviceDescription":"test local TLS Registry","owner":"86.5000.470/dou.SUPER","publicKey":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgHes68FmNYTgj2UKMu0cAc6+1izOoAkOkcYu+wS3/utvtA98CutdjogZjPVnYP4lumA1TrKo9zY0xGyo/8hkMY3C7Bn9kK3+o1uT0Jv5qPmxcr8E1vZg6joe2k38pHKBkjIctqHDXVrzcoQG1EiUSNQwbhlT/EjNmdzt2+ykmkHf+jiocjwc6TAL0EmifHk4o6kmn4LHvChmTfaMeRUnT2Ol6Aral+dd5RfVhQ1lNsoRfTk7QVR9GETmgLOLDQTbWAkMGg/p6LgQml0eulTTg5SCuoFKY81wruPVeoQ6yfmfX11aKHS88XOEg5qUARGlwncaxMUFqTPpiJwKzzlJrwIDAQAB","protocol":"tls","protocolVersion":"2.0","port":1720,"ipAddress":"127.0.0.1","listenerInfos":"[{\"url\":\"tls://127.0.0.1:1720\",\"protocolVersion\":\"2.0\",\"messageFormat\":\"delimiter\"}]","isSigned":"true"}} # {"bytesAlg":{"hashAlg":"SHA-256"},"signatures":{"payload":"eyJpZCI6Ijg2LjUwMDAuNDcwL2RvdS5URVNUIiwidHlwZSI6IjAuVFlQRS9ETy5ET0lQU2VydmljZUluZm8iLCJhdHRyaWJ1dGVzIjp7InNlcnZpY2VOYW1lIjoiVGVzdFRMU1JlZ2lzdHJ5Iiwic2VydmljZURlc2NyaXB0aW9uIjoidGVzdCBsb2NhbCBUTFMgUmVnaXN0cnkiLCJvd25lciI6Ijg2LjUwMDAuNDcwL2RvdS5TVVBFUiIsInB1YmxpY0tleSI6Ik1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBZ0hlczY4Rm1OWVRnajJVS011MGNBYzYrMWl6T29Ba09rY1l1K3dTMy91dHZ0QTk4Q3V0ZGpvZ1pqUFZuWVA0bHVtQTFUcktvOXpZMHhHeW8vOGhrTVkzQzdCbjlrSzMrbzF1VDBKdjVxUG14Y3I4RTF2Wmc2am9lMmszOHBIS0JrakljdHFIRFhWcnpjb1FHMUVpVVNOUXdiaGxUL0VqTm1kenQyK3lrbWtIZitqaW9jandjNlRBTDBFbWlmSGs0bzZrbW40TEh2Q2htVGZhTWVSVW5UMk9sNkFyYWwrZGQ1UmZWaFExbE5zb1JmVGs3UVZSOUdFVG1nTE9MRFFUYldBa01HZy9wNkxnUW1sMGV1bFRUZzVTQ3VvRktZODF3cnVQVmVvUTZ5Zm1mWDExYUtIUzg4WE9FZzVxVUFSR2x3bmNheE1VRnFUUHBpSndLenpsSnJ3SURBUUFCIiwicHJvdG9jb2wiOiJ0bHMiLCJwcm90b2NvbFZlcnNpb24iOiIyLjAiLCJwb3J0IjoxNzIwLCJpcEFkZHJlc3MiOiIxMjcuMC4wLjEiLCJsaXN0ZW5lckluZm9zIjoiW3tcInVybFwiOlwidGxzOi8vMTI3LjAuMC4xOjE3MjBcIixcInByb3RvY29sVmVyc2lvblwiOlwiMi4wXCIsXCJtZXNzYWdlRm9ybWF0XCI6XCJkZWxpbWl0ZXJcIn1dIiwiaXNTaWduZWQiOiJ0cnVlIn19","signatures":[{"protected":"eyJhbGciOiJSUzI1NiJ9","header":{"kid":"86.5000.470/dou.SUPER"},"signature":"XYJanYr50DDMRwwy9h8Ayy5JOAgvLnI6T__UgAxCjvxSBVPItMYpID5Yok4t6x9Jslna4o9P6ddf0O8fa2R3qv9XVzM-_6FehOeS-fKwb0J_HkncKk2NMVk1W7OSq8NvhsTn6jvREGWCSCnQH1Z3Lr6XyH0t68FkrGj186UNBagIk_Q3Vc_doYQfwlo3gJ3p_rjN26WcrllhjIWLGjxlWoN_XWoy3kn5Vr3_5pQu8Tn64qUFKdDFKvtomu-Tr-noYDf13AOlTaAAg8VsIgc-pbM4hEd2KdoBvGn9xANGFKE7ruoTSbOV79zM_cxFVZnQRPSAHKVHapBFWCCYdJmsKQ"}]}} (DelimiterMessageClientCodec.java:85) ``` (2)发送listOperation操作 ```bash java -jar .\Client-1.0.jar -l -cf .\default_client_regi.json [INFO ]17:11:38.824 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]17:11:41.068 client sending message: {"requestId":"453969307","targetId":"86.5000.470/dou.TEST","operationId":"0.DOIP/Op.ListOperations","authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]17:11:41.258 client received message: {"requestId":"453969307","status":"0.DOIP/Status.001","output":["0.DOIP/Op.Hello","0.DOIP/Op.ListOperations","0.DOIP/Op.Retrieve","0.DOIP/Op.Create","0.DOIP/Op.Update","0.DOIP/Op.Delete","0.DOIP/Op.Search","0.DOIP/Op.Extension","0.DOIP/Op.Unknown"]} (DelimiterMessageClientCodec.java:85) ``` (3)发送create操作 ```bash java -jar .\Client-1.0.jar -c 86.5000.470/meta.test01 Meta metainfo -cf .\default_client_regi.json [INFO ]17:14:39.364 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]17:14:41.588 client sending message: {"requestId":"495617923","targetId":"86.5000.470/dou.TEST","operationId":"0.DOIP/Op.Create","authentication":{"username":"admin","password":"password"}} # {"id":"86.5000.470/meta.test01","type":"0.TYPE/DO.Metadata","attributes":{"content":{"create":"metainfo","name":"create","description":"this is an example for create"}}} # # (DelimiterMessageClientCodec.java:35) [INFO ]17:14:41.832 client received message: {"requestId":"495617923","status":"0.DOIP/Status.001"} # {"id":"86.5000.470/meta.test01","type":"0.TYPE/DO.Metadata","attributes":{"content":{"create":"metainfo","name":"create","description":"this is an example for create"}}} (DelimiterMessageClientCodec.java:85) ``` (4)发送update操作 ```bash java -jar .\Client-1.0.jar -u 86.5000.470/meta.test01 Meta metainfo_update -cf .\default_client_regi.json [INFO ]17:15:04.887 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]17:15:07.150 client sending message: {"requestId":"1654592549","targetId":"86.5000.470/meta.test01","operationId":"0.DOIP/Op.Update","authentication":{"username":"admin","password":"password"}} # {"id":"86.5000.470/meta.test01","type":"0.TYPE/DO.Metadata","attributes":{"content":{"update":"metainfo_update","name":"update","description":"this is an example for update"}}} # # (DelimiterMessageClientCodec.java:35) [INFO ]17:15:07.454 client received message: {"requestId":"1654592549","status":"0.DOIP/Status.001"} # {"id":"86.5000.470/meta.test01","type":"0.TYPE/DO.Metadata","attributes":{"content":{"update":"metainfo_update","name":"update","description":"this is an example for update"}}} (DelimiterMessageClientCodec.java:85) ``` (5)发送retrieve操作 ```bash java -jar .\Client-1.0.jar -r 86.5000.470/meta.test01 -cf .\default_client_regi.json [INFO ]17:15:23.620 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]17:15:25.938 client sending message: {"requestId":"-1789595138","targetId":"86.5000.470/meta.test01","operationId":"0.DOIP/Op.Retrieve","attributes":{"includeElementData":"true"},"authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]17:15:26.108 client received message: {"requestId":"-1789595138","status":"0.DOIP/Status.001"} # {"id":"86.5000.470/meta.test01","type":"0.TYPE/DO.Metadata","attributes":{"content":{"update":"metainfo_update","name":"update","description":"this is an example for update"}}} (DelimiterMessageClientCodec.java:85) ``` (6)发送search操作 ```bash java -jar .\Client-1.0.jar -s "metainfo_update" -cf .\default_client_regi.json [INFO ]17:16:00.188 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]17:16:02.441 client sending message: {"requestId":"2052262241","targetId":"86.5000.470/dou.TEST","operationId":"0.DOIP/Op.Search","attributes":{"query":"metainfo_update","pageNum":0,"pageSize":10,"type":"full","sortFields":"id:ASC"},"authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]17:16:02.726 client received message: {"requestId":"2052262241","status":"0.DOIP/Status.001","output":{"size":1,"results":[{"id":"86.5000.470/meta.test01","type":"0.TYPE/DO.Metadata","attributes":{"content":{"update":"metainfo_update","name":"update","description":"this is an example for update"}}}]}} (DelimiterMessageClientCodec.java:85) ``` (7)发送delete操作 ```bash java -jar .\Client-1.0.jar -d 86.5000.470/meta.test01 -cf .\default_client_regi.json [INFO ]17:16:38.767 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]17:16:40.975 client sending message: {"requestId":"779456898","targetId":"86.5000.470/meta.test01","operationId":"0.DOIP/Op.Delete","authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]17:16:41.160 client received message: {"requestId":"779456898","status":"0.DOIP/Status.001"} (DelimiterMessageClientCodec.java:85) ``` # 3. 与其他DOIP实现进行互操作 ## 3.1 cordra ### 3.1.1 使用PKU实现的DOIP客户端访问cordra实现的DOIP服务 参考cordra提供的文档搭建cordra的DOIP服务,注册用户,并记录账户。使用PKU实现的DOIP客户端工具访问cordra的DOIP服务,使用已经注册的用户凭据来通过认证。这里以cordra2.1版本为例来进行说明。 1. 启动cordra的DOIP服务 将下载的cordra2.1代码进行解压,目录结构如下: ```bash Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2020/5/8 23:28 bin d----- 2020/5/8 23:28 cordra-client-handle-storage d----- 2021/1/17 14:00 data d----- 2020/5/8 23:28 docker d----- 2020/5/8 23:28 extensions d----- 2020/8/6 23:26 src d----- 2020/5/8 23:28 sw -a---- 2020/5/8 23:28 14152 cordra-client-LICENSE.txt -a---- 2020/7/27 10:49 948067 cordra-technical-manual-2.1.0.pdf -a---- 2020/5/8 23:28 66548 LICENSE.txt -a---- 2020/5/8 23:28 1503 README.txt -a---- 2020/5/8 23:28 45 shutdown -a---- 2020/5/8 23:28 61 shutdown.bat -a---- 2020/5/8 23:28 44 startup -a---- 2020/5/8 23:28 60 startup.bat ``` 根据README.txt中的提示,修改admin的初始密码。然后通过启动脚本(Linux和MacOS中使用startup,Windows中使用startup.bat)开启DOIP服务。看到如下信息,表示启动完成。 ```bash data dir: D:\App\cordra-2.1.0\data Initializing HTTP interface on port 8080 Initializing HTTPS interface on port 8443 Using existing keypair for HTTPS. Storage: bdbje Index: lucene Initializing Handle TCP interface on port 2641 Initializing DOIP interface on port 9000 Startup complete. ``` 2. 配置PKU DOIP客户端 当完成cordra服务端启动后,修改PKU DOIP客户端的配置文件。该配置文件与客户端的jar包放在一个目录,文件名为:default_client.json。修改内容如下,其中userPass为第一步配置的admin初始密码,这里假设为"password": ```json { "repoID": "20.5000.123/service", "repoURL": "tls://127.0.0.1:9000", "userName": "admin", "userPass": "password", "enableIRP": false } ``` 3. 使用DOIP客户端与cordra服务端进行交互 (1) 查看服务端信息: ```bash java -jar .\DoipSDK-1.0.jar -i [INFO ]16:37:25.727 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]16:37:27.743 client sending message: {"requestId":"-886484722","targetId":"20.5000.123/service","operationId":"0.DOIP/Op.Hello","authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]16:37:27.979 client received message: {"requestId":"-886484722","status":"0.DOIP/Status.001","output":{"id":"20.5000.123/service","type":"0.TYPE/DOIPService","attributes":{"ipAddress":"127.0.0.1","port":9000,"protocol":"TCP","protocolVersion":"2.0","publicKey":{"kty":"RSA","n":"i8MxV1gugMrs_GdSNDRzxzoj87vJZ9tlUyDHFYJ6oHJDtmD2F2VK_hwqTLQgadmmKTs2RfHfzIIrkz1vWqvGLMMaTvvmYpqjZml64FDXEXP1yynAhV34ylJ7ChYENmbc1gEkv44wqG8lvQdyeysxM9tz6VSlYwT1AjfAute9QjtscU5Hpzr7kBTOpRRE7za3dCErPmBbNZKDy9ZUREIsOik0jwnlEs7uGJgh4AoQR--qczbTO-VLafDE1pmIfaeQU9WAPD2euXZ34vaLyV2MsZQ4BGJq4xYYbBoKdSXikdRQ3NMsGjPalajdYdxwWCt0yVWbP9MGObTiv3OlOToyuQ","e":"AQAB"}}}} (DelimiterMessageClientCodec.java:85) ``` (2) 查看服务端支持的操作: ```bash java -jar .\DoipSDK-1.0.jar -l [INFO ]16:40:23.876 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]16:40:25.922 client sending message: {"requestId":"-1201986326","targetId":"20.5000.123/service","operationId":"0.DOIP/Op.ListOperations","authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]16:40:26.100 client received message: {"requestId":"-1201986326","status":"0.DOIP/Status.001","output":["0.DOIP/Op.Hello","0.DOIP/Op.ListOperations","0.DOIP/Op.Create","0.DOIP/Op.Search"]} (DelimiterMessageClientCodec.java:85) ``` (3) 创建数字对象: ```bash java -jar .\DoipSDK-1.0.jar -c 86.5000.470/do.cordra.test0 DO hello [INFO ]16:39:09.847 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]16:39:11.800 client sending message: {"requestId":"-1058388874","targetId":"20.5000.123/service","operationId":"0.DOIP/Op.Create","authentication":{"username":"admin","password":"password"}} # {"id":"86.5000.470/do.cordra.test0","type":"0.TYPE/DO","attributes":{"content":{"create":"hello","name":"create","description":"this is an example for create"}}} # # (DelimiterMessageClientCodec.java:35) [INFO ]16:39:12.019 client received message: {"requestId":"-1058388874","status":"0.DOIP/Status.001","output":{"id":"86.5000.470/do.cordra.test0","type":"0.TYPE/DO","attributes":{"content":{"name":"create","description":"this is an example for create","create":"hello"},"metadata":{"createdOn":1610872751960,"createdBy":"admin","modifiedOn":1610872751960,"modifiedBy":"admin","txnId":1610872751963003}},"elements":[]}} (DelimiterMessageClientCodec.java:85) ``` (4) 更新数字对象: ```bash java -jar .\DoipSDK-1.0.jar -u 86.5000.470/do.cordra.test0 DO hello_update [INFO ]16:42:05.815 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]16:42:07.871 client sending message: {"requestId":"-702244521","targetId":"86.5000.470/do.cordra.test0","operationId":"0.DOIP/Op.Update","authentication":{"username":"admin","password":"password"}} # {"id":"86.5000.470/do.cordra.test0","type":"0.TYPE/DO","attributes":{"content":{"update":"hello_update","name":"update","description":"this is an example for update"}}} # # (DelimiterMessageClientCodec.java:35) [INFO ]16:42:08.083 client received message: {"requestId":"-702244521","status":"0.DOIP/Status.001","output":{"id":"86.5000.470/do.cordra.test0","type":"0.TYPE/DO","attributes":{"content":{"name":"update","description":"this is an example for update","update":"hello_update"},"metadata":{"createdOn":1610872751960,"createdBy":"admin","modifiedOn":1610872928052,"modifiedBy":"admin","txnId":1610872928045004}},"elements":[]}} (DelimiterMessageClientCodec.java:85) ``` (5) 获取数字对象 ```bash java -jar .\DoipSDK-1.0.jar -r 86.5000.470/do.cordra.test0 [INFO ]16:45:24.997 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]16:45:27.069 client sending message: {"requestId":"1215397185","targetId":"86.5000.470/do.cordra.test0","operationId":"0.DOIP/Op.Retrieve","attributes":{"includeElementData":"true"},"authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]16:45:27.241 client received message: {"requestId":"1215397185","status":"0.DOIP/Status.001"} # {"id":"86.5000.470/do.cordra.test0","type":"0.TYPE/DO","attributes":{"content":{"name":"update","description":"this is an example for update","update":"hello_update"},"metadata":{"createdOn":1610872751960,"createdBy":"admin","modifiedOn":1610872928052,"modifiedBy":"admin","txnId":1610872928045004}},"elements":[]} (DelimiterMessageClientCodec.java:85) ``` (6) 检索数字对象: ```bash java -jar .\DoipSDK-1.0.jar -s "+type:0.TYPE/DO +/name:update" [INFO ]16:43:18.653 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]16:43:20.683 client sending message: {"requestId":"-328328880","targetId":"20.5000.123/service","operationId":"0.DOIP/Op.Search","attributes":{"query":"+type:0.TYPE/DO +/name:update","pageNum":0,"pageSize":10,"type":"full","sortFields":"id:ASC"},"authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]16:43:20.892 client received message: {"requestId":"-328328880","status":"0.DOIP/Status.001"} # { "size": 1, "results": [ { "id": "86.5000.470/do.cordra.test0", "type": "0.TYPE/DO", "attributes": { "content": { "name": "update", "description": "this is an example for update", "update": "hello_update" }, "metadata": { "createdOn": 1610872751960, "createdBy": "admin", "modifiedOn": 1610872928052, "modifiedBy": "admin", "txnId": 1610872928045004 } }, "elements": [] } ] } (DelimiterMessageClientCodec.java:85) ``` (7) 删除数字对象: ```bash java -jar .\DoipSDK-1.0.jar -d 86.5000.470/do.cordra.test0 [INFO ]16:46:55.354 load config from: default_client.json (DOIPCMDClient.java:192) [INFO ]16:46:57.436 client sending message: {"requestId":"-1326115326","targetId":"86.5000.470/do.cordra.test0","operationId":"0.DOIP/Op.Delete","authentication":{"username":"admin","password":"password"}} # # (DelimiterMessageClientCodec.java:35) [INFO ]16:46:57.627 client received message: {"requestId":"-1326115326","status":"0.DOIP/Status.001"} (DelimiterMessageClientCodec.java:85) ``` ### 3.1.2 使用cordra客户端访问PKU实现的DOIP服务 参考cordra提供的客户端开发代码,编写客户端程序,详细请参考cordra[相关文档](https://www.cordra.org/documentation/client/doip-java.html)。 __注意__:由于实现的差异,cordra客户端不能识别PKU DOIP服务针对hello操作返回的信息(包含签名),会报```Unexpected input segments```的错误。 # 4. 使用SDK编写自己的应用 下载doip-java-sdk [v1.0](https://public.internetapi.cn/releases/doa/ri/DoipSDK-1.0.jar),注意:由于SDK代码采用Java编写,请准备好JDK环境(版本>=java1.8)。 ## 4.1 分析要管理的数据 参考DOIP2.0标准,数字对象是一个比特序列或者比特序列的集合,可以是任何可以分离并唯一标识的东西。 ### 4.1.1 定义数字对象 以下通过一些具体的例子来说明如何通过SDK定义数字对象。 * 字符串 ```java DigitalObject digitalObject = new DigitalObject(doId, doType); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("name", "hello"); jsonObject.addProperty("date", "2021/01/20"); jsonObject.addProperty("description", "this is an example for create"); ``` * 文件(文本、图片、文档) ```java DigitalObject digitalObject = new DigitalObject(doId, doType); JsonObject jsonObject = new JsonObject(); Element element = new Element("file", "txt"); InputStream is = new FileInputStream(strFile); int iAvail = is.available(); byte[] bytes = new byte[iAvail]; is.read(bytes); is.close(); element.setData(bytes); ``` ### 4.1.2 定义元数据格式 您可以根据自己的需求设计自己的元数据格式,比如如果您处理的数据是图书类数据,可以使用都柏林元数据标准。下面通过一个简单的示例来说明如何使用SDK定义元数据格式。 ``` DigitalObject digitalObject = new DigitalObject(doId, DoType.Metadata); JsonObject metadata = new JsonObject(); metadata.addProperty("doGroupName","DOIP"); metadata.addProperty("doGroupDesc","DOIP接口创建"); metadata.addProperty("doName","helloDO"); metadata.addProperty("doDesc","hello world"); digitalObject.addAttribute("metadata",new Gson().toJson(metadata)); digitalObject.addAttribute("owner","86.5000.470/dou.TEST"); ``` ## 4.2 使用SDK开发应用 在源码目录下创建libs目录,将下载的SDK文件解压出来的jar包拷贝到libs目录中,如果您使用gradle,请在build.gradle中添加如下代码: ```groovy repositories { maven { url 'https://maven.aliyun.com/nexus/content/groups/public' } flatDir { dirs 'libs' } } dependencies { testCompile group: 'junit', name: 'junit', version: '4.8.1' //netty implementation 'io.netty:netty-all:4.1.29.Final' //Http utils implementation 'org.apache.httpcomponents:httpclient:4.5.11' //Gson implementation 'com.google.code.gson:gson:2.8.6' // Log4j implementation 'log4j:log4j:1.2.17' // Junit testImplementation 'junit:junit:4.12' //bouncyCastle implementation 'org.bouncycastle:bcprov-jdk15on:1.65' //doip implementation files('libs/DoipSDK-1.0.jar') } ``` ### 4.2.1 实现自定义的Repository 参考源代码:org.bdware.doip.application.SimpleRepositoryMain ### 4.2.2 实现自定义的Registry 参考源代码:org.bdware.doip.application.SimpleRegistryMain ### 4.2.3 实现自定义的Client 参考源代码:org.bdware.doip.application.client.DOIPCMDClient ## 4.3 准备配置信息 ### 4.3.1 生成证书 由于客户端与服务端采用了TLS通信协议,需要配置服务端密钥/证书。请确保环境中安装有keytools工具,然后使用如下命令,生成服务端使用的私钥和证书。 * 为Repository生成证书 ``` keytool -genkey -keyalg RSA -keysize 2048 -validity 365 -keypass 123456 -keystore doip_service_repository.keystore -storepass 123456 -dname "UID=86.5000.470/doip.RepositoryTLSService" ``` * 为Registry生成证书 ``` keytool -genkey -keyalg RSA -keysize 2048 -validity 365 -keypass 123456 -keystore doip_service_registry.keystore -storepass 123456 -dname "UID=86.5000.470/doip.RegistryTLSService" ``` ### 4.3.2 编写配置文件 1. Repository 创建名称为default_repository.conf的文件,写入如下内容。 ```json { "LHSProxyAddress": "http://localhost:10001/", "ownerHandle": "86.5000.470/dou.SUPER0", "certPath": "keys/default_repo_0.keystore", "certPassword": "123456", "repoID": "86.5000.470/Repository.Test.00", "listeners": "[{\"url\":\"tls://127.0.0.1:1718\",\"protocolVersion\":\"2.0\",\"messageFormat\":\"delimiter\"}]", "serviceDescription": "local repository for test", "serviceName": "TestTLSRepository0" } ``` 创建名称为account.json的文件,写入如下内容(下述仅为示例),这将作为Repository管理员的初始账户/密码: ```json { "userName": "admin", "userPass": "password" } ``` 2. Registry 创建名称为default_registry.conf的文件,写入如下内容。 ```json { "LHSProxyAddress": "http://localhost:10001/", "ownerHandle": "86.5000.470/dou.SUPER", "certPath": "keys/default_regi.keystore", "certPassword": "123456", "repoID": "86.5000.470/Registry.Test", "listeners": "[{\"url\":\"tls://127.0.0.1:1720\",\"protocolVersion\":\"2.0\",\"messageFormat\":\"delimiter\"}]", "serviceDescription": "local registry for test", "serviceName": "TestTLSRegistry" } ``` 创建名称为account.json的文件,写入如下内容(下述仅为示例),这将作为Registry管理员的初始账户/密码: ```json { "userName": "admin", "userPass": "password" } ``` 3. Client 创建名称为default_client.conf的文件,写入如下内容。 ```json { "repoID": "86.5000.470/Repository.Test.00", "repoURL": "tls://127.0.0.1:1718", "userID": "86.5000.470/Repository.Test.00", "userName": "admin", "userPass": "password", "enableIRP": true } ``` ## 4.4 部署程序 * 将编译好的Repository代码与default_server_repository.keystore,default_repository.conf放在同一目录,然后执行Repository。 * 将编译好的Registry代码与default_server_registry.keystore,default_registry.conf放在同一目录,然后执行Registry。 * 将编译好的Client代码与default_client_repository.keystore,default_client_registry.keystore,default_client.conf放在同一目录,然后执行Client。 # 5. 接口说明 详细的SDK接口说明文档 # 6. 查看源代码 * doip-java-sdk-src [v1.0](https://gitee.com/BDWare/doip-sdk/tree/extension/)