From f1e652bcce70aaa288654f7e72759924c92f7a61 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 16:04:32 -0400 Subject: [PATCH 01/22] Initial commit --- README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..4973f8e --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# messagepack-docs + +MessagePack Docs \ No newline at end of file From 4ebc3891d9cdfde4726d655c7f96fbac628aac34 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 16:14:53 -0400 Subject: [PATCH 02/22] =?UTF-8?q?=E6=96=87=E6=A1=A3=E7=9A=84=20build=20?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 build.gradle diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..f59cf6d --- /dev/null +++ b/build.gradle @@ -0,0 +1,30 @@ +plugins { + id "org.asciidoctor.convert" version "2.3.0" +} + +apply plugin: 'java' + +version = '1.0.0' + +asciidoctor { + + def build = file('build.gradle') + + attributes 'build-gradle': build, + 'endpoint-url': 'https://docs.ossez.com', + 'source-highlighter': 'coderay', + 'imagesdir': 'images', + 'includedir': '_includes', + 'toc': 'left', + 'icons': 'font', + 'setanchors': '', + 'idprefix': '', + 'idseparator': '-', + 'docinfo1': '' +} + +allprojects { + repositories { + maven { url "https://maven.ossez.com/repository/internal" } + } +} From f191fd47ae7d70aebd5eebe31f4004e89eb27f7f Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 16:17:33 -0400 Subject: [PATCH 03/22] =?UTF-8?q?README=20=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.adoc | 8 ++++++++ README.md | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 README.adoc delete mode 100644 README.md diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..d2e1911 --- /dev/null +++ b/README.adoc @@ -0,0 +1,8 @@ += MessagePack 文档 +YuCheng Hu +:doctype: book +:page-layout: docs +:page-description: Protocol Buffers +:page-keywords: Protocol Buffers + +MessagePack 的相关文档,本文是根据官方的内容和我们项目中的具体实践进行编辑的。 diff --git a/README.md b/README.md deleted file mode 100644 index 4973f8e..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# messagepack-docs - -MessagePack Docs \ No newline at end of file From 7c920fa8874484a1d2c4d7ab9d2c2fb7ab667751 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 16:18:31 -0400 Subject: [PATCH 04/22] =?UTF-8?q?=E6=9E=84=E5=BB=BA=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E8=87=AA=E5=8A=A8=E5=8C=96=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .travis.yml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5796f23 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,40 @@ +language: java +install: true + +jdk: + - openjdk8 + +os: + - linux + +branches: + only: + - master + +cache: + directories: + - $HOME/.gradle + +before_install: + - chmod +x gradlew + + +before_script: + - git fetch + - git checkout -b gh-pages + - git merge origin/master + - git rm --cached --ignore-unmatch index.html + +script: + - ./gradlew asciidoctor + + +deploy: + provider: s3 + access_key_id: "$AWS_ACCESS_KEY" + secret_access_key: "$AWS_SECRET_KEY" + region: us-east-2 + bucket: "com.ossez.docs" + skip_cleanup: true + local_dir: build/asciidoc/html5 + upload-dir: messagepack-docs From f9f812d1e3d243e84dc8847c4a9585535a48e7eb Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 16:47:06 -0400 Subject: [PATCH 05/22] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20gradle=20=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradlew | 188 ++++++++++++++++++++++++++++++++++++++++++++++++ gradlew.bat | 100 ++++++++++++++++++++++++++ settings.gradle | 1 + 3 files changed, 289 insertions(+) create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..b0d6d0a --- /dev/null +++ b/gradlew @@ -0,0 +1,188 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..9991c50 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,100 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..8cf4caa --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'protocol-buffers-docs' From 10c4b99e54967b9e2cd7cb166fd5c907f79acd79 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 16:49:03 -0400 Subject: [PATCH 06/22] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E7=9A=84=E6=BA=90=E4=BB=A3=E7=A0=81=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/docinfo.html | 4 + src/docs/asciidoc/mgspack_0.6.x.adoc | 213 +++++++++++++++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 src/docs/asciidoc/docinfo.html create mode 100644 src/docs/asciidoc/mgspack_0.6.x.adoc diff --git a/src/docs/asciidoc/docinfo.html b/src/docs/asciidoc/docinfo.html new file mode 100644 index 0000000..ab1cdf2 --- /dev/null +++ b/src/docs/asciidoc/docinfo.html @@ -0,0 +1,4 @@ + + + + diff --git a/src/docs/asciidoc/mgspack_0.6.x.adoc b/src/docs/asciidoc/mgspack_0.6.x.adoc new file mode 100644 index 0000000..44f5b03 --- /dev/null +++ b/src/docs/asciidoc/mgspack_0.6.x.adoc @@ -0,0 +1,213 @@ += MessagePack Java 0.6.X QuickStart +YuCheng Hu +:doctype: book +:page-layout: docs +:page-description: Protocol Buffers +:page-keywords: Protocol Buffers + +:imagesdir: images +:includedir: _includes + +中文标题【MessagePack Java 0.6.X 快速开始指南】 + +WARNING: 0.6.x 版本的 MessagePack 已经过期被淘汰了。如果你现在开始使用 MessagePack 话,请不要使用这个版本。 +我们再这里保留 0.6.x 版本的内容主要用于参考用途。 + +欢迎来到 MessagePack 快速开发指南。protocol buffers 是一个语言中立,平台中立针对通讯协议,数据存储和其他领域中对结构化数据进行序列化的扩展方法。 + +本文档主要针对的是 Java,C++ 或 Python 的开发人员希望在开发的应用程序中使用 Protocol Buffers。这个有关 Protocol Buffers 摘要性的介绍将会告诉你如何开始使用 Protocol Buffers。 +如果你希望更加深入的了解有关 Protocol Buffers 的内容,你可以进入 tutorials 或者 protocol buffer encoding 页面来详细了解。 + +有关 API 的参考文档,请参考页面:reference documentation 这里提供了所有这 3 种语言的参考,同时也针对 .proto language 和 style 提供相关的指南。 + +== 什么是 Protocol Buffers +Protocol buffers 是对结构化数据序列化的一个灵活,高效,自动化工具 —— 你可以将 Protocol buffers 想象成 XML,但是体积更小,更快也更加简单。 + +你可以自己定义你的结构化数据,然后你可以使用特定的代码生成工具来非常容易对你的结构化数据进行读取和写入。这些数据的读取和写入可以是一系列的数据流和使用不同的计算机程序语言。 +你甚至可以在不对已经部署的程序进行破坏的情况下更新你的数据结构。 + +== Protocol Buffers 是如何进行工作的 +你需要制定你希望如何将你的数据进行序列化。你是通过 proto 文件来定义你的消息结构化数据的。 + +每一 protocol buffer message 是一个小的信息记录逻辑,这个消息中包含有一系列的名字,变量对照序列。 +下面是一些基本的.proto 文件,这些文件中定义了一个消息,这个消息包含有一个 person 信息: + +[source] +---- +message Person { + required string name = 1; + required int32 id = 2; + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} +---- + +通过上面你可以看到这个消息的格式非常简单—— 每一个消息类型都有一个或者多个唯一进行编号的字段,每一个字段包含有一个名字和变量类型。 + +变量可以为数字(整形或者浮点型)(numbers),布尔类型(booleans),字符串(strings),原生二进制(raw bytes)甚至其他的 protocol buffer 消息类型,能够允许你分级的结构化你的数据。 + +你可以将字段指定为可选字段(optional fields),必须字段(required fields)和重复字段(repeated fields)。你可以从下面的 Protocol Buffer Language Guide 页面中找到更多有关 .proto 的定义。 + +一旦你成功定义了你的消息,你可以针对你使用的语言使用你定义的 .proto 来运行 protocol buffer 编译器(protocol buffer compiler)来生成数据访问类。 + +针对每一个字段,在数据访问类中提供了简单的访问方法(例如 name() 和 set_name())和序列化到原生 2 进制数据和从原生 2 进制数据反序列化的方法。 + +针对上面的定义,如果你现在使用的是 C++ 语言的话,当你把消息定义进行编译后,你将会得到一个称为 Person 的类。 +,对数据进行序列化和从序列化的数据中(protocol buffer 消息)重新获得 Person 数据。 + +然后你可以写一些类似 Person person; 的代码。 + +[source,CPP] +---- +Person person; +person.set_name("John Doe"); +person.set_id(1234); +person.set_email("jdoe@example.com"); +fstream output("myfile", ios::out | ios::binary); +person.SerializeToOstream(&output); +---- + +随后,你可以对消息进行读取: + +[source,CPP] +---- +fstream input("myfile", ios::in | ios::binary); +Person person; +person.ParseFromIstream(&input); +cout << "Name: " << person.name() << endl; +cout << "E-mail: " << person.email() << endl; +---- + +你可以向你的消息中添加新的字段而不会损坏老的消息。这是因为在老的消息处理中,针对新的字段是完全忽略掉的。因此,如果你在你的通讯协议中使用 protocol buffers 为数据结构的话, +你可以对你的协议和消息进行扩展而不需要担心老的代码没有办法编译通过,或者损坏老的代码。 + +你可以访问 API Reference section 页面中的内容来了解完整 protocol buffer 代码的生成和使用。 + +你也可以在 Protocol Buffer Encoding 页面中了解更多protocol buffer 消息是如何进行编码的。 + +== 为什么不使用 XML +针对 XML 来说 Protocol Buffers 具有更多的优势来对序列化结构数据。 + +* 更加简单 +* 小于 XML 3 到 10 倍 +* 快于 XML 20 到 100 倍 +* 松耦合 +* 使用程序工具来创建数据访问类,使数访问类更加简单 +* 假设,你需要讲 person 这个数据进行定义,在 XML 你需要使用: + +[source,XML] +---- + + John Doe + jdoe@example.com + +---- + +来进行定义。 + +在 Protocol Buffers 中针对上面的消息文本化(text format)后显示为: + +[source] +---- +# Textual representation of a protocol buffer. +# This is *not* the binary format used on the wire. +person { + name: "John Doe" + email: "jdoe@example.com" +} +---- + +当上面的消息被编码为 Protocol Buffer 二进制格式(binary format)上面的文字可能小于 28 bytes,并且可能需要 100-200 纳秒(nanoseconds)来进行处理。 + +我们将上面转换为可以人为读取的目的主要是为进行调试和编辑。 + +如果你使用 XML 的话,上面的信息至少需要 69 bytes (你需要删除所有的空格),同时你需要 5,000-10,000 纳秒(nanoseconds)来进行处理。 + +同时,对 protocol buffer 进行操作也是非常容易的: + +[source,CPP] +---- +cout << "Name: " << person.name() << endl; +cout << "E-mail: " << person.email() << endl; +---- + +如果使用的是 XML 的话,你需要进行下面的操作: + +[source,CPP] +---- +cout << "Name: " + << person.getElementsByTagName("name")->item(0)->innerText() + << endl; +cout << "E-mail: " + << person.getElementsByTagName("email")->item(0)->innerText() + << endl; +---- + +但是,protocol buffers 并不是任何时候都会比 XML 好。例如,针对基于文本的标记语言(例如,XML),protocol buffers 就不是一个很好的选项, +因为你不能使用 protocol buffer 更好的在文档中进行交换。更主要的是 HTML 是人类可以阅读和编辑的。protocol buffer 也不是不可以人为的读取,但是针对原生的 protocol buffer 格式是没有办法人为进行读取和编辑的。 + +XML 与 HTML 一样,在某种程度上是一种自我描述数据。protocol buffer 只针对你在 .proto 文件中描述的内容进行表达。 + +== 看起来像一个解决方案,我应该如何开始呢 +Download the package – 这包中含有针对 Java, Python, 和 C++ protocol buffer 编译器源代码,和你需要进行 I/O 和测试的类。希望对你的编译器进行编译和构建,请参考代码中的 README 文件。 + +一旦你完成了所有的设置,请参考 tutorial 页面中的内容来选择你需要的语言——这个能够帮助你使用 protocol buffer 创建一个简单的应用程序。 + +== 介绍 proto3 +在我们最新的 version 3 发行版 中推出了新的语言版本 —— Protocol Buffers language version 3(另称 proto3),在这个版本中针对我们已经存在的语言版本(proto2)使用了一些新的特性。 + +Proto3 简化了 protocol buffer 语言,使其更加容易使用并且能够支持更多的语言:我们当前发行的 proto3 能够让你创建 Java, C++, Python, Java Lite, Ruby, JavaScript, Objective-C, and C#。 + +另外你也可以通过使用 Go protoc 插件来用 proto3 创建 Go 代码,这个插件你可以到 golang/protobuf Github 中下载到。更多的语言还在逐步进行支持中。 + +请注意,这 2 个版本的 API 并不是完全兼容的。为了照顾还在使用老版本的用户,我们将会在新的 protocol buffers 发行中同时支持老的版本。 + +你可以在下面的发行日志(release notes)查看 2 个版本的主要不同。有关 proto3 的句法,请参考 Proto3 Language Guide 中的内容,针对 proto3 的完整文档还没有编写完成,将会随后推出。 + +看起来 proto2 和 proto3 可能会产生一些混淆,这是因为原始的开源 protocol buffers 实际上是 Google 内部语言的第二个版本,同时我们的开源版本也是从 v2.0.0 开始的。 +简单来说就是 proto 最开始的版本是 Google 内部使用的,在 proto 第二个版本的时候,Google 决定进行开源了,所以开源的 proto 是从 proto2 开始的。 + +== 一个简短的历史 +Protocol buffers 最开始是在 Google 内部进行开发的,用于处理在索引服务器上请求/响应(request/response)的协议。 + +在 Protocol buffers 之前,针对请求和响应,使用的是 marshalling/unmarshalling,这个能够支持一系列的协议。但是结果看起来却是非常的难看,例如: +[source] +---- +if (version == 3) { + ... +} else if (version > 4) { + if (version == 5) { + ... + } + ... +} +---- + +明确格式化的的协议也使新版本的协议更加难以推出,这是因为开发者必须能够了解老协议在服务器之间是如何进行处理的,同时也需要了解新的协议。只有对新老协议都有所了解后才能逐步使用新的协议替换老的协议。 + +Protocol buffers 被用来设计解决上面的很多问题: + +* 新的字段比较能够容易的进行定义,中级服务器不需要对数据进行检查,直接对数据进行处理,同时也可以直接传输数据而不需要了解数据是如何进行定义的。 +* 格式使用自描述,能够更加容易支持更多的语言(C++,Java 等)。 + +但是,用户还是需要手动书写他们自己的处理diam。 + +作为系统的进化来说,它获得了许多其他的特性和用途: + +* 自动生成序列化和反序列化代码而避免手动书写这些代码。 +* 除了开始使用短期RPC(远程过程调用)请求,人们开始使用 protocol buffers 作为高效的自描述结构化数据格式(主要针对数据短期存在,例如在 Bigtable)。 +* 服务器RPC接口开始被声明为协议文件的一部分,协议编译器生成根类,用户可以通过服务器接口的实现和重载它们。 + +Protocol buffers 在 Google 中成为针对数据的通用语言—— 随着时间的流逝,在 Google 内部已经有超过 348,952 .proto 文件被定义。这些被用在 RPC 系统和存储系统中存储数据。 From c3819a69e3e41dffd5c04d8eceedaa22fdd237f8 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 16:58:09 -0400 Subject: [PATCH 07/22] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A6=96=E9=A1=B5?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/index.adoc | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/docs/asciidoc/index.adoc diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc new file mode 100644 index 0000000..bffae11 --- /dev/null +++ b/src/docs/asciidoc/index.adoc @@ -0,0 +1,31 @@ += MessagePack 文档 +YuCheng Hu +:doctype: book +:page-layout: docs +:page-description: MessagePack +:page-keywords: MessagePack + +:imagesdir: images +:includedir: _includes + +MessagePack 相关文档的内容。 + +image::https://travis-ci.org/cwiki-us-docs/messagepack-docs.svg?branch=master[] + +image::messagepack-logo.png[] + +== MessagePack 简介 +MessagePack 是一个计算机的数据交换格式。 + +MessagePack 是一个二进制的格式用来表达简单的数据结构,例如数组和关联数组。 + +MessagePack 的目标尽量的简单和紧凑。官方的实现已经实现了多种语言,例如 C, C++, C#, D, Erlang, Go, Haskell, Java, JavaScript, Lua, OCaml, Perl, PHP, Python, Ruby, Scala, Smalltalk, 和 Swift。 + +MessagePack 的了解就是传输的数据格式都是二进制,可以节省用户的流量。 + + + +== Protocol Buffers 文档快速导航 +* xref:developer_guide.adoc[开发者指南] + +image::protocol-buffers-serialization.png[] From 9e29cf14bbcc07a910c1f53d7afaef475de3951d Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 16:58:39 -0400 Subject: [PATCH 08/22] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E7=9A=84=20logo=20=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/images/messagepack-logo.png | Bin 0 -> 3474 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/docs/asciidoc/images/messagepack-logo.png diff --git a/src/docs/asciidoc/images/messagepack-logo.png b/src/docs/asciidoc/images/messagepack-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b4df747f6ccefa3d18048d8c0503ec6a7de9775b GIT binary patch literal 3474 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 literal 0 HcmV?d00001 From eeb5532bff929d94fc4152a03abd352985890295 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 17:01:21 -0400 Subject: [PATCH 09/22] =?UTF-8?q?=E6=8F=90=E4=BA=A4=20gradle=20=E5=88=B0?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E9=A1=B9=E7=9B=AE=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..5c2d1cf016b3885f6930543d57b744ea8c220a1a GIT binary patch literal 55616 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 Date: Mon, 5 Aug 2019 17:52:20 -0400 Subject: [PATCH 10/22] =?UTF-8?q?=E6=9B=B4=E4=BD=BF=E7=94=A8=E7=9A=84?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/mgspack_0.6.x.adoc | 221 +++++---------------------- 1 file changed, 40 insertions(+), 181 deletions(-) diff --git a/src/docs/asciidoc/mgspack_0.6.x.adoc b/src/docs/asciidoc/mgspack_0.6.x.adoc index 44f5b03..08e839c 100644 --- a/src/docs/asciidoc/mgspack_0.6.x.adoc +++ b/src/docs/asciidoc/mgspack_0.6.x.adoc @@ -13,18 +13,44 @@ YuCheng Hu WARNING: 0.6.x 版本的 MessagePack 已经过期被淘汰了。如果你现在开始使用 MessagePack 话,请不要使用这个版本。 我们再这里保留 0.6.x 版本的内容主要用于参考用途。 -欢迎来到 MessagePack 快速开发指南。protocol buffers 是一个语言中立,平台中立针对通讯协议,数据存储和其他领域中对结构化数据进行序列化的扩展方法。 +最新的 MessagePack 版本请参考: https://github.com/msgpack/msgpack-java 中的项目源代码。 -本文档主要针对的是 Java,C++ 或 Python 的开发人员希望在开发的应用程序中使用 Protocol Buffers。这个有关 Protocol Buffers 摘要性的介绍将会告诉你如何开始使用 Protocol Buffers。 -如果你希望更加深入的了解有关 Protocol Buffers 的内容,你可以进入 tutorials 或者 protocol buffer encoding 页面来详细了解。 +TIP: MessagePack 中文文档请参考: http://docs.ossez.com/messagepack-docs/index.html -有关 API 的参考文档,请参考页面:reference documentation 这里提供了所有这 3 种语言的参考,同时也针对 .proto language 和 style 提供相关的指南。 +TIP: MessagePack 测试和示例源代码: https://github.com/cwiki-us-demo/serialize-deserialize-demo-java -== 什么是 Protocol Buffers -Protocol buffers 是对结构化数据序列化的一个灵活,高效,自动化工具 —— 你可以将 Protocol buffers 想象成 XML,但是体积更小,更快也更加简单。 -你可以自己定义你的结构化数据,然后你可以使用特定的代码生成工具来非常容易对你的结构化数据进行读取和写入。这些数据的读取和写入可以是一系列的数据流和使用不同的计算机程序语言。 -你甚至可以在不对已经部署的程序进行破坏的情况下更新你的数据结构。 +这个指南提供了使用 msgpack-java 的快速指南。在开始的时候,我们将会介绍如何安装 msgpack-java,然后将会运行如何使用 msgpack 来对对象序列化/反序列化(serialize/deserizalize)对象。 + +== 安装 +你可以使用下面 2 种方法来安装 msgpack-java —— 从 maven 下载或者直接构建 jar 包。 + +=== 从 Maven2 仓库中进行安装 +MessagePack 针对 Java 的使用已经发布到 Maven 的中央仓库中(Maven Central Repository)。你可以使用下面的参数来配置你项目的 pom.xml 文件。 + +[source,xml] +---- + + org.msgpack + msgpack + ${msgpack.version} + +---- +你需要将 ${msgpack.version} 替换为当前的 MessagePack 版本,有关可以使用的具体版本你可以访问 http://repo1.maven.org/maven2/org/msgpack/msgpack/ 中的版本。 + +请注意,在 0.6.x 版本中最新的版本只更新到 0.6.12。 + +=== 从 git 仓库中进行安装 +你可以从代码仓库中获得最新的代码。 + +[source] +---- + + org.msgpack + msgpack + ${msgpack.version} + +---- == Protocol Buffers 是如何进行工作的 你需要制定你希望如何将你的数据进行序列化。你是通过 proto 文件来定义你的消息结构化数据的。 @@ -34,180 +60,13 @@ Protocol buffers 是对结构化数据序列化的一个灵活,高效,自动 [source] ---- -message Person { - required string name = 1; - required int32 id = 2; - optional string email = 3; - - enum PhoneType { - MOBILE = 0; - HOME = 1; - WORK = 2; - } - - message PhoneNumber { - required string number = 1; - optional PhoneType type = 2 [default = HOME]; - } - - repeated PhoneNumber phone = 4; -} +$ git clone git@github.com:msgpack/msgpack-java.git +$ cd msgpack-java +$ mvn package ---- -通过上面你可以看到这个消息的格式非常简单—— 每一个消息类型都有一个或者多个唯一进行编号的字段,每一个字段包含有一个名字和变量类型。 +使用上面的代码进行编译后u,你将会在 msgpack-java/target 目录中得到 msgpack.jar 包。 -变量可以为数字(整形或者浮点型)(numbers),布尔类型(booleans),字符串(strings),原生二进制(raw bytes)甚至其他的 protocol buffer 消息类型,能够允许你分级的结构化你的数据。 +同时你也需要 https://code.google.com/p/json-simple/ 和 https://github.com/jboss-javassist/javassist 来让 msgpack.jar 可以在项目中使用。否则你将会收到 NoClassDefFoundError 错误。 -你可以将字段指定为可选字段(optional fields),必须字段(required fields)和重复字段(repeated fields)。你可以从下面的 Protocol Buffer Language Guide 页面中找到更多有关 .proto 的定义。 - -一旦你成功定义了你的消息,你可以针对你使用的语言使用你定义的 .proto 来运行 protocol buffer 编译器(protocol buffer compiler)来生成数据访问类。 - -针对每一个字段,在数据访问类中提供了简单的访问方法(例如 name() 和 set_name())和序列化到原生 2 进制数据和从原生 2 进制数据反序列化的方法。 - -针对上面的定义,如果你现在使用的是 C++ 语言的话,当你把消息定义进行编译后,你将会得到一个称为 Person 的类。 -,对数据进行序列化和从序列化的数据中(protocol buffer 消息)重新获得 Person 数据。 - -然后你可以写一些类似 Person person; 的代码。 - -[source,CPP] ----- -Person person; -person.set_name("John Doe"); -person.set_id(1234); -person.set_email("jdoe@example.com"); -fstream output("myfile", ios::out | ios::binary); -person.SerializeToOstream(&output); ----- - -随后,你可以对消息进行读取: - -[source,CPP] ----- -fstream input("myfile", ios::in | ios::binary); -Person person; -person.ParseFromIstream(&input); -cout << "Name: " << person.name() << endl; -cout << "E-mail: " << person.email() << endl; ----- - -你可以向你的消息中添加新的字段而不会损坏老的消息。这是因为在老的消息处理中,针对新的字段是完全忽略掉的。因此,如果你在你的通讯协议中使用 protocol buffers 为数据结构的话, -你可以对你的协议和消息进行扩展而不需要担心老的代码没有办法编译通过,或者损坏老的代码。 - -你可以访问 API Reference section 页面中的内容来了解完整 protocol buffer 代码的生成和使用。 - -你也可以在 Protocol Buffer Encoding 页面中了解更多protocol buffer 消息是如何进行编码的。 - -== 为什么不使用 XML -针对 XML 来说 Protocol Buffers 具有更多的优势来对序列化结构数据。 - -* 更加简单 -* 小于 XML 3 到 10 倍 -* 快于 XML 20 到 100 倍 -* 松耦合 -* 使用程序工具来创建数据访问类,使数访问类更加简单 -* 假设,你需要讲 person 这个数据进行定义,在 XML 你需要使用: - -[source,XML] ----- - - John Doe - jdoe@example.com - ----- - -来进行定义。 - -在 Protocol Buffers 中针对上面的消息文本化(text format)后显示为: - -[source] ----- -# Textual representation of a protocol buffer. -# This is *not* the binary format used on the wire. -person { - name: "John Doe" - email: "jdoe@example.com" -} ----- - -当上面的消息被编码为 Protocol Buffer 二进制格式(binary format)上面的文字可能小于 28 bytes,并且可能需要 100-200 纳秒(nanoseconds)来进行处理。 - -我们将上面转换为可以人为读取的目的主要是为进行调试和编辑。 - -如果你使用 XML 的话,上面的信息至少需要 69 bytes (你需要删除所有的空格),同时你需要 5,000-10,000 纳秒(nanoseconds)来进行处理。 - -同时,对 protocol buffer 进行操作也是非常容易的: - -[source,CPP] ----- -cout << "Name: " << person.name() << endl; -cout << "E-mail: " << person.email() << endl; ----- - -如果使用的是 XML 的话,你需要进行下面的操作: - -[source,CPP] ----- -cout << "Name: " - << person.getElementsByTagName("name")->item(0)->innerText() - << endl; -cout << "E-mail: " - << person.getElementsByTagName("email")->item(0)->innerText() - << endl; ----- - -但是,protocol buffers 并不是任何时候都会比 XML 好。例如,针对基于文本的标记语言(例如,XML),protocol buffers 就不是一个很好的选项, -因为你不能使用 protocol buffer 更好的在文档中进行交换。更主要的是 HTML 是人类可以阅读和编辑的。protocol buffer 也不是不可以人为的读取,但是针对原生的 protocol buffer 格式是没有办法人为进行读取和编辑的。 - -XML 与 HTML 一样,在某种程度上是一种自我描述数据。protocol buffer 只针对你在 .proto 文件中描述的内容进行表达。 - -== 看起来像一个解决方案,我应该如何开始呢 -Download the package – 这包中含有针对 Java, Python, 和 C++ protocol buffer 编译器源代码,和你需要进行 I/O 和测试的类。希望对你的编译器进行编译和构建,请参考代码中的 README 文件。 - -一旦你完成了所有的设置,请参考 tutorial 页面中的内容来选择你需要的语言——这个能够帮助你使用 protocol buffer 创建一个简单的应用程序。 - -== 介绍 proto3 -在我们最新的 version 3 发行版 中推出了新的语言版本 —— Protocol Buffers language version 3(另称 proto3),在这个版本中针对我们已经存在的语言版本(proto2)使用了一些新的特性。 - -Proto3 简化了 protocol buffer 语言,使其更加容易使用并且能够支持更多的语言:我们当前发行的 proto3 能够让你创建 Java, C++, Python, Java Lite, Ruby, JavaScript, Objective-C, and C#。 - -另外你也可以通过使用 Go protoc 插件来用 proto3 创建 Go 代码,这个插件你可以到 golang/protobuf Github 中下载到。更多的语言还在逐步进行支持中。 - -请注意,这 2 个版本的 API 并不是完全兼容的。为了照顾还在使用老版本的用户,我们将会在新的 protocol buffers 发行中同时支持老的版本。 - -你可以在下面的发行日志(release notes)查看 2 个版本的主要不同。有关 proto3 的句法,请参考 Proto3 Language Guide 中的内容,针对 proto3 的完整文档还没有编写完成,将会随后推出。 - -看起来 proto2 和 proto3 可能会产生一些混淆,这是因为原始的开源 protocol buffers 实际上是 Google 内部语言的第二个版本,同时我们的开源版本也是从 v2.0.0 开始的。 -简单来说就是 proto 最开始的版本是 Google 内部使用的,在 proto 第二个版本的时候,Google 决定进行开源了,所以开源的 proto 是从 proto2 开始的。 - -== 一个简短的历史 -Protocol buffers 最开始是在 Google 内部进行开发的,用于处理在索引服务器上请求/响应(request/response)的协议。 - -在 Protocol buffers 之前,针对请求和响应,使用的是 marshalling/unmarshalling,这个能够支持一系列的协议。但是结果看起来却是非常的难看,例如: -[source] ----- -if (version == 3) { - ... -} else if (version > 4) { - if (version == 5) { - ... - } - ... -} ----- - -明确格式化的的协议也使新版本的协议更加难以推出,这是因为开发者必须能够了解老协议在服务器之间是如何进行处理的,同时也需要了解新的协议。只有对新老协议都有所了解后才能逐步使用新的协议替换老的协议。 - -Protocol buffers 被用来设计解决上面的很多问题: - -* 新的字段比较能够容易的进行定义,中级服务器不需要对数据进行检查,直接对数据进行处理,同时也可以直接传输数据而不需要了解数据是如何进行定义的。 -* 格式使用自描述,能够更加容易支持更多的语言(C++,Java 等)。 - -但是,用户还是需要手动书写他们自己的处理diam。 - -作为系统的进化来说,它获得了许多其他的特性和用途: - -* 自动生成序列化和反序列化代码而避免手动书写这些代码。 -* 除了开始使用短期RPC(远程过程调用)请求,人们开始使用 protocol buffers 作为高效的自描述结构化数据格式(主要针对数据短期存在,例如在 Bigtable)。 -* 服务器RPC接口开始被声明为协议文件的一部分,协议编译器生成根类,用户可以通过服务器接口的实现和重载它们。 - -Protocol buffers 在 Google 中成为针对数据的通用语言—— 随着时间的流逝,在 Google 内部已经有超过 348,952 .proto 文件被定义。这些被用在 RPC 系统和存储系统中存储数据。 +== 如何使用 From be9c5d52948678988c464b06e45f307adfdf7756 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 17:53:52 -0400 Subject: [PATCH 11/22] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20=E5=AE=89=E8=A3=85?= =?UTF-8?q?=20=E7=9B=B8=E5=85=B3=E7=9A=84=E6=BA=90=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/mgspack_0.6.x.adoc | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/docs/asciidoc/mgspack_0.6.x.adoc b/src/docs/asciidoc/mgspack_0.6.x.adoc index 08e839c..d632105 100644 --- a/src/docs/asciidoc/mgspack_0.6.x.adoc +++ b/src/docs/asciidoc/mgspack_0.6.x.adoc @@ -43,21 +43,6 @@ MessagePack 针对 Java 的使用已经发布到 Maven 的中央仓库中(Mave === 从 git 仓库中进行安装 你可以从代码仓库中获得最新的代码。 -[source] ----- - - org.msgpack - msgpack - ${msgpack.version} - ----- - -== Protocol Buffers 是如何进行工作的 -你需要制定你希望如何将你的数据进行序列化。你是通过 proto 文件来定义你的消息结构化数据的。 - -每一 protocol buffer message 是一个小的信息记录逻辑,这个消息中包含有一系列的名字,变量对照序列。 -下面是一些基本的.proto 文件,这些文件中定义了一个消息,这个消息包含有一个 person 信息: - [source] ---- $ git clone git@github.com:msgpack/msgpack-java.git From 5feb925873ec441cc18f338b2fdcd72454c8b58e Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 17:55:41 -0400 Subject: [PATCH 12/22] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=BF=AB=E9=80=9F?= =?UTF-8?q?=E5=AF=BC=E8=88=AA=E4=B8=AD=E7=9A=84=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/index.adoc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index bffae11..21b5f73 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -24,8 +24,7 @@ MessagePack 的目标尽量的简单和紧凑。官方的实现已经实现了 MessagePack 的了解就是传输的数据格式都是二进制,可以节省用户的流量。 - -== Protocol Buffers 文档快速导航 -* xref:developer_guide.adoc[开发者指南] +== MessagePack 文档快速导航 +* xref:mgspack_0.6.x.adoc[MessagePack Java 0.6.X 快速开始指南] image::protocol-buffers-serialization.png[] From cd27777ee3280c6d6d8acb8e9c80ccd55bc15b28 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 5 Aug 2019 22:07:01 -0400 Subject: [PATCH 13/22] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BD=BF=E7=94=A8=20JG?= =?UTF-8?q?P=20=E6=A0=BC=E5=BC=8F=E7=9A=84=20logo=20=E5=9B=BE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/images/messagepack-logo.jpg | Bin 0 -> 32861 bytes src/docs/asciidoc/images/messagepack-logo.png | Bin 3474 -> 0 bytes src/docs/asciidoc/index.adoc | 3 +-- 3 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 src/docs/asciidoc/images/messagepack-logo.jpg delete mode 100644 src/docs/asciidoc/images/messagepack-logo.png diff --git a/src/docs/asciidoc/images/messagepack-logo.jpg b/src/docs/asciidoc/images/messagepack-logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5fa2331a8edff4cd1858038665098673f3e4156b GIT binary patch literal 32861 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 Q2oQ*rxV%`2i2j%V0^F9XBLDyZ literal 0 HcmV?d00001 diff --git a/src/docs/asciidoc/images/messagepack-logo.png b/src/docs/asciidoc/images/messagepack-logo.png deleted file mode 100644 index b4df747f6ccefa3d18048d8c0503ec6a7de9775b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3474 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 diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index 21b5f73..c155f2f 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -12,7 +12,7 @@ MessagePack 相关文档的内容。 image::https://travis-ci.org/cwiki-us-docs/messagepack-docs.svg?branch=master[] -image::messagepack-logo.png[] +image::messagepack-logo.jpg[] == MessagePack 简介 MessagePack 是一个计算机的数据交换格式。 @@ -27,4 +27,3 @@ MessagePack 的了解就是传输的数据格式都是二进制,可以节省 == MessagePack 文档快速导航 * xref:mgspack_0.6.x.adoc[MessagePack Java 0.6.X 快速开始指南] -image::protocol-buffers-serialization.png[] From a869f1ddedd8eda1c8ac81351b6ae8bf8da810c9 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Tue, 6 Aug 2019 11:59:01 -0400 Subject: [PATCH 14/22] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=92=8C=E8=BF=87=E6=9C=9F=E7=9A=84=E7=9A=84=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=B9=B6=E4=B8=94=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=88=B0=20GIT=20=E5=BA=93=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/mgspack_0.6.x.adoc | 182 +++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) diff --git a/src/docs/asciidoc/mgspack_0.6.x.adoc b/src/docs/asciidoc/mgspack_0.6.x.adoc index d632105..4ad362a 100644 --- a/src/docs/asciidoc/mgspack_0.6.x.adoc +++ b/src/docs/asciidoc/mgspack_0.6.x.adoc @@ -55,3 +55,185 @@ $ mvn package 同时你也需要 https://code.google.com/p/json-simple/ 和 https://github.com/jboss-javassist/javassist 来让 msgpack.jar 可以在项目中使用。否则你将会收到 NoClassDefFoundError 错误。 == 如何使用 +下面是如何使用的示例代码。 + +=== 使用一个消息打包(message-packable)类 +使用注解 '_@Message_' 来让你可以序列化你自己类中对象的 public 字段。 + +本代码可以在 https://github.com/cwiki-us-demo/messagepack-6-demo-java/blob/master/src/test/java/com/insight/demo/msgpack/MessagePack6Object.java 中下载到本地后进行编译测试。 + +[source,java] +---- +package com.insight.demo.msgpack; + +import org.junit.Test; +import org.msgpack.MessagePack; +import org.msgpack.annotation.Message; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.UUID; + +import static org.junit.Assert.assertEquals; + +/** + * MessagePack6Objects + * + * @author yhu + */ +public class MessagePack6Object { + final Logger logger = LoggerFactory.getLogger(MessagePack6Object.class); + + /** + * MessageData Message Object + */ + @Message // Annotation + public static class MessageData { + // public fields are serialized. + public String uuid; + public String name; + public double version; + } + + + /** + * Test MessagePack6Objects + */ + @Test + public void testMessagePack6Objects() { + logger.debug("MessagePack6Objects for Objects"); + + String uuid = UUID.randomUUID().toString(); + + // INIT OBJ + MessageData src = new MessageData(); + src.uuid = uuid; + src.name = "MessagePack6"; + src.version = 0.6; + + try { + MessagePack msgPack = new MessagePack(); + + // Serialization + logger.debug("------ Serialization ------"); + byte[] bytes = msgPack.write(src); + logger.debug("Bytes Array Length: [{}]", bytes.length); + + // Deserialization + logger.debug("------ Deserialization ------"); + MessageData dst = msgPack.read(bytes, MessageData.class); + logger.debug("Check Object for UUID: [{}]", dst.uuid); + + assertEquals(uuid, dst.uuid); + + } catch (Exception ex) { + logger.error("MessagePack Serialization And Deserialization error", ex); + } + } +} +---- + +如果你希望按照顺序序列化多个对象的话,你可以使用 '_Packer_' 和 '_Unpacker_' 多个对象。 + +这是因为 '_MessagePack.write(Object)_' 和 '_read(byte[])_' 实际上每次都调用创建了 '_Packer_' 和 '_Unpacker_' 对象。 + +为了使用 '_Packer_' 和 '_Unpacker_' 对象,请调用 '_createPacker(OutputStream)_' 和 '_createUnpacker(InputStream)_'。 + +本代码可以 https://github.com/cwiki-us-demo/messagepack-6-demo-java/blob/master/src/test/java/com/insight/demo/msgpack/MessagePack6Objects.java 中查看。 + +[source,java] +---- +package com.insight.demo.msgpack; + +import org.junit.Test; +import org.msgpack.MessagePack; +import org.msgpack.annotation.Message; +import org.msgpack.packer.Packer; +import org.msgpack.unpacker.Unpacker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.UUID; + +import static org.junit.Assert.assertEquals; + +/** + * MessagePack6Objects + * + * @author yhu + */ +public class MessagePack6Objects { + final Logger logger = LoggerFactory.getLogger(MessagePack6Objects.class); + + /** + * MessageData Message Objects + */ + @Message // Annotation + public static class MessageData { + // public fields are serialized. + public String uuid; + public String name; + public double version; + } + + + /** + * Test MessagePack6Objects + */ + @Test + public void testMessagePack6Objects() { + logger.debug("MessagePack6Objects for Objects"); + + String uuid = UUID.randomUUID().toString(); + + // INIT OBJ + MessageData src1 = new MessageData(); + src1.uuid = uuid; + src1.name = "MessagePack6-src1"; + src1.version = 0.6; + + MessageData src2 = new MessageData(); + src2.uuid = uuid; + src2.name = "MessagePack6-src2"; + src2.version = 10.6; + + MessageData src3 = new MessageData(); + src3.uuid = uuid; + src3.name = "MessagePack6-src3"; + src3.version = 1.6; + + try { + MessagePack msgPack = new MessagePack(); + + // Serialization + logger.debug("------ Serialization ------"); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Packer packer = msgPack.createPacker(out); + packer.write(src1); + packer.write(src2); + packer.write(src3); + + byte[] bytes = out.toByteArray(); + logger.debug("Bytes Array Length: [{}]", bytes.length); + + // Deserialization + logger.debug("------ Deserialization ------"); + ByteArrayInputStream in = new ByteArrayInputStream(bytes); + Unpacker unpacker = msgPack.createUnpacker(in); + + MessageData dst1 = unpacker.read(MessageData.class); + MessageData dst2 = unpacker.read(MessageData.class); + MessageData dst3 = unpacker.read(MessageData.class); + + logger.debug("Check Object for UUID: [{}]", dst1.uuid); + + assertEquals(uuid, dst1.uuid); + + } catch (Exception ex) { + logger.error("MessagePack Serialization And Deserialization error", ex); + } + } +} +---- From 0a895131cd86ec4538d93b13c81b0a2f65345d94 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Tue, 6 Aug 2019 23:36:23 -0400 Subject: [PATCH 15/22] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=E5=A4=9A=E7=A7=8D=E7=B1=BB=E5=9E=8B=E7=9A=84=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E5=92=8C=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/mgspack_0.6.x.adoc | 113 +++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/src/docs/asciidoc/mgspack_0.6.x.adoc b/src/docs/asciidoc/mgspack_0.6.x.adoc index 4ad362a..b615468 100644 --- a/src/docs/asciidoc/mgspack_0.6.x.adoc +++ b/src/docs/asciidoc/mgspack_0.6.x.adoc @@ -237,3 +237,116 @@ public class MessagePack6Objects { } } ---- + +=== 多种类型变量的序列化和反序列化(serialization/deserialization) + +类 '_Packer/Unpacker_' 允许序列化和反序列化多种类型的变量,如后续程序所示。这个类启用序列化和反序列化多种类型的变量和序列化主要类型变量以及包装类,'_String_' 对象, +'_byte[]_' 对象,'_ByteBuffer 对象等的方法相似。 + +如上面提示的,你可以序列化和反序列化你自己的对象,前提是你自己的对象需要使用 '_@Message_' 注解。 + +本代码可以在: https://github.com/cwiki-us-demo/messagepack-6-demo-java/blob/master/src/test/java/com/insight/demo/msgpack/MessagePack6Types.java 中找到。 + +[source,java] +---- +package com.insight.demo.msgpack; + +import org.junit.Test; +import org.msgpack.MessagePack; +import org.msgpack.packer.Packer; +import org.msgpack.unpacker.Unpacker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.nio.ByteBuffer; + +/** + * MessagePack6Types + * + * @author yhu + */ +public class MessagePack6Types { + final Logger logger = LoggerFactory.getLogger(MessagePack6Types.class); + + + /** + * Test MessagePack6Types + */ + @Test + public void testMessagePack6Types() { + logger.debug("testMessagePack6Types for Types"); + + MessagePack msgpack = new MessagePack(); + try { + + // + // Serialization + // + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Packer packer = msgpack.createPacker(out); + + // Serialize values of primitive types + packer.write(true); // boolean value + packer.write(10); // int value + packer.write(10.5); // double value + + // Serialize objects of primitive wrapper types + packer.write(Boolean.TRUE); + packer.write(new Integer(10)); + packer.write(new Double(10.5)); + + // Serialize various types of arrays + packer.write(new int[]{1, 2, 3, 4}); + packer.write(new Double[]{10.5, 20.5}); + packer.write(new String[]{"msg", "pack", "for", "java"}); + packer.write(new byte[]{0x30, 0x31, 0x32}); // byte array + + // Serialize various types of other reference values + packer.write("MessagePack"); // String object + packer.write(ByteBuffer.wrap(new byte[]{0x30, 0x31, 0x32})); // ByteBuffer object + packer.write(BigInteger.ONE); // BigInteger object + + // + // Deserialization + // + byte[] bytes = out.toByteArray(); + ByteArrayInputStream in = new ByteArrayInputStream(bytes); + Unpacker unpacker = msgpack.createUnpacker(in); + + // to primitive values + boolean b = unpacker.readBoolean(); // boolean value + int i = unpacker.readInt(); // int value + double d = unpacker.readDouble(); // double value + + // to primitive wrapper value + Boolean wb = unpacker.read(Boolean.class); + Integer wi = unpacker.read(Integer.class); + Double wd = unpacker.read(Double.class); + + // to arrays + int[] ia = unpacker.read(int[].class); + Double[] da = unpacker.read(Double[].class); + String[] sa = unpacker.read(String[].class); + byte[] ba = unpacker.read(byte[].class); + + // to String object, ByteBuffer object, BigInteger object, List object and Map object + String ws = unpacker.read(String.class); + ByteBuffer buf = unpacker.read(ByteBuffer.class); + BigInteger bi = unpacker.read(BigInteger.class); + + } catch (Exception ex) { + logger.error("MessagePack Serialization And Deserialization error", ex); + } + } +} +---- + +方法 '_Packer#write()_' 允许序列化多种类型的数据。 + +类 '_Unpacker_' 针对反序列化二进制数据为主要变量,提供了一个反序列化方法。例如,你希望将二进制数据反序列化为 '_boolean_' (或者 '_int_') 数据类型,你可以使用 '_Unpacker_' 中的 '_readBoolean_' (或者 '_readInt_') 方法。 + +'_Unpacker_' 同时也为参考变量提供了一个读取的方法。这个方法允许为一个参考变量从二进制数据中进行反序列化。参考变量的定义为你将类型指定为一个参数。 +例如,你希望反序列化二进制数据到 '_String_' (或者 '_byte[]_') 对象,你必须在调用 '_read(String.class)_' (或者 '_read(byte[].class)_') 方法的时候定义描述。 From b84cd2d94b7af8558850cd1f5b0002f66c460be4 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Wed, 7 Aug 2019 00:13:19 -0400 Subject: [PATCH 16/22] =?UTF-8?q?List=20=E5=85=83=E7=B4=A0=E7=9A=84?= =?UTF-8?q?=E5=BA=8F=E5=88=97=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/mgspack_0.6.x.adoc | 106 ++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/src/docs/asciidoc/mgspack_0.6.x.adoc b/src/docs/asciidoc/mgspack_0.6.x.adoc index b615468..2d91e8b 100644 --- a/src/docs/asciidoc/mgspack_0.6.x.adoc +++ b/src/docs/asciidoc/mgspack_0.6.x.adoc @@ -245,7 +245,7 @@ public class MessagePack6Objects { 如上面提示的,你可以序列化和反序列化你自己的对象,前提是你自己的对象需要使用 '_@Message_' 注解。 -本代码可以在: https://github.com/cwiki-us-demo/messagepack-6-demo-java/blob/master/src/test/java/com/insight/demo/msgpack/MessagePack6Types.java 中找到。 +本代码可以在 https://github.com/cwiki-us-demo/messagepack-6-demo-java/blob/master/src/test/java/com/insight/demo/msgpack/MessagePack6Types.java 中查看。 [source,java] ---- @@ -350,3 +350,107 @@ public class MessagePack6Types { '_Unpacker_' 同时也为参考变量提供了一个读取的方法。这个方法允许为一个参考变量从二进制数据中进行反序列化。参考变量的定义为你将类型指定为一个参数。 例如,你希望反序列化二进制数据到 '_String_' (或者 '_byte[]_') 对象,你必须在调用 '_read(String.class)_' (或者 '_read(byte[].class)_') 方法的时候定义描述。 + +== List, Map 对象的序列化和反序列化(serialization/deserialization) +为了序列化原生的容器对象例如  '_List_' 和 '_Map_' 对象,你必须使用 '_Template_'。 + +'_Template_' 对象是 serializer 和 deserializer 的配对。例如,为了序列化一个 '_List_' 对象,在 '_List_' 对象中 '_Integer_' 对象为元素,你可以使用下面的方法来创建一个模板对象(Template object)。 + +[source,java] +---- +Template listTmpl = Templates.tList(Templates.TInteger); +---- + +类 '_tList_', '_TInteger_' 是静态方法,字段为 '_Templates_'。 + +一个 '_List 和 '_Map_' 对象的用例如下显示: + +本代码可以在 https://github.com/cwiki-us-demo/messagepack-6-demo-java/blob/master/src/test/java/com/insight/demo/msgpack/MessagePack6Template.java 中查看。 + +[source,java] +---- +package com.insight.demo.msgpack; + +import org.junit.Test; +import org.msgpack.MessagePack; +import org.msgpack.packer.Packer; +import org.msgpack.template.Template; +import org.msgpack.unpacker.Unpacker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.msgpack.template.Templates.*; + +/** + * MessagePack6Template + * + * @author yhu + */ +public class MessagePack6Template { + final Logger logger = LoggerFactory.getLogger(MessagePack6Template.class); + + + /** + * Test MessagePack6Template + */ + @Test + public void testMessagePack6Template() { + logger.debug("MessagePack6Template for Template"); + + MessagePack msgpack = new MessagePack(); + try { + + // Create templates for serializing/deserializing List and Map objects + Template> listTmpl = tList(TString); + Template> mapTmpl = tMap(TString, TString); + + // + // Serialization + // + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Packer packer = msgpack.createPacker(out); + + // Serialize List object + List list = new ArrayList(); + list.add("msgpack"); + list.add("for"); + list.add("java"); + packer.write(list); // List object + + // Serialize Map object + Map map = new HashMap(); + map.put("sadayuki", "furuhashi"); + map.put("muga", "nishizawa"); + packer.write(map); // Map object + + // + // Deserialization + // + + byte[] bytes = out.toByteArray(); + ByteArrayInputStream in = new ByteArrayInputStream(bytes); + Unpacker unpacker = msgpack.createUnpacker(in); + + // to List object + List dstList = unpacker.read(listTmpl); + + // to Map object + Map dstMap = unpacker.read(mapTmpl); + + } catch (Exception ex) { + logger.error("MessagePack Serialization And Deserialization error", ex); + } + } +} + +---- From 1543c6789450a73798ea9a394239d91a7440ddda Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Wed, 7 Aug 2019 00:46:36 -0400 Subject: [PATCH 17/22] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AE=8C=E6=95=B4?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/mgspack_0.6.x.adoc | 102 +++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/docs/asciidoc/mgspack_0.6.x.adoc b/src/docs/asciidoc/mgspack_0.6.x.adoc index 2d91e8b..c5aaeb3 100644 --- a/src/docs/asciidoc/mgspack_0.6.x.adoc +++ b/src/docs/asciidoc/mgspack_0.6.x.adoc @@ -454,3 +454,105 @@ public class MessagePack6Template { } ---- + +=== 不使用注解(annotations)来序列化 +如果你不能添加 @Message 到你的定义对象中但是你还是希望进行序列化。你可以使用 register 方法来在类中启用序列化对象。 + +如下的代码所示: + +[source,java] +---- +MessagePack msgpack = new MessagePack(); +msgpack.register(MyMessage2.class); +---- + +例如,如果 MyMessage2 类被包含到了外部的库中了。你没有办法比较容易的编辑源代码,添加 '_@Message_' 到源代码中。 + +register 方法能够允许为 MyMessage2 自动创建一个 serializer 和 deserializer 对。 + +你可以在执行方面后序列化对象 MyMessage2。 + +=== 可选字段 +你可添加一个新的字段来保持可用性。在新字段中使用 '_@Optional_' 注解。 + +[source,java] +---- +@Message +public static class MyMessage { + public String name; + public double version; + + // new field + @Optional + public int flag = 0; +} +---- + +如果你尝试反序列化老版本数据的话,可选字段将会被忽略。 + +=== 动态类型 +我们知道 Java 是一个静态类型的语言。通过输入 '_Value_' MessagePack能够实现动态的特性。  + +'_Value_' 有方法来检查自己的类型('_isIntegerType()_', '_isArrayType()_', 等...),同时也转换为自己的类型 ('_asStringValue()_', '_convert(Template)_')。 + +本代码可以在 https://github.com/cwiki-us-demo/messagepack-6-demo-java/blob/master/src/test/java/com/insight/demo/msgpack/MessagePack6DynamicTyping.java 中查看。 + +[source,java] +---- +package com.insight.demo.msgpack; + +import org.junit.Test; +import org.msgpack.MessagePack; +import org.msgpack.type.Value; +import org.msgpack.unpacker.Converter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +import static org.msgpack.template.Templates.TString; +import static org.msgpack.template.Templates.tList; + +/** + * MessagePack6Objects + * + * @author yhu + */ +public class MessagePack6DynamicTyping { + final Logger logger = LoggerFactory.getLogger(MessagePack6DynamicTyping.class); + + + /** + * Test MessagePack6Objects + */ + @Test + public void MessagePack6DynamicTyping() { + logger.debug("MessagePack6Objects for Objects"); + + // Create serialize objects. + List src = new ArrayList(); + src.add("msgpack"); + src.add("kumofs"); + src.add("viver"); + + MessagePack msgpack = new MessagePack(); + + try { + + // Serialize + byte[] raw = msgpack.write(src); + + // Deserialize directly using a template + List dst1 = msgpack.read(raw, tList(TString)); + + // Or, Deserialze to Value then convert type. + Value dynamic = msgpack.read(raw); + List dst2 = new Converter(dynamic).read(tList(TString)); + + } catch (Exception ex) { + logger.error("MessagePack Serialization And Deserialization error", ex); + } + } +} +---- From e976c34ac9ad88718db39c4eeac98c7be2d67864 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Tue, 10 Sep 2019 14:22:22 -0400 Subject: [PATCH 18/22] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E7=9A=84=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 8cf4caa..ba2796a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -rootProject.name = 'protocol-buffers-docs' +rootProject.name = 'messagepack-docs' From 34c6c5ba850ceb8f1b36a0ae1fa6fcd95ffc76a6 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Tue, 10 Sep 2019 16:40:39 -0400 Subject: [PATCH 19/22] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=20OSSEZ=20=E7=9A=84=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 98 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 17 deletions(-) diff --git a/build.gradle b/build.gradle index f59cf6d..09a22cb 100644 --- a/build.gradle +++ b/build.gradle @@ -6,25 +6,89 @@ apply plugin: 'java' version = '1.0.0' -asciidoctor { - - def build = file('build.gradle') - - attributes 'build-gradle': build, - 'endpoint-url': 'https://docs.ossez.com', - 'source-highlighter': 'coderay', - 'imagesdir': 'images', - 'includedir': '_includes', - 'toc': 'left', - 'icons': 'font', - 'setanchors': '', - 'idprefix': '', - 'idseparator': '-', - 'docinfo1': '' -} - allprojects { repositories { maven { url "https://maven.ossez.com/repository/internal" } } + + ext { + environmentProperty = project.hasProperty('environment') ? getProperty('environment') : 'hsql' + + docResourcesVersion = '0.1.0' + + } + + apply plugin: 'idea' } + +configurations { + docs +} + +dependencies { + docs "com.ossez.docresources:ossez-doc-resources:${docResourcesVersion}@zip" +} + + +task prepareAsciidocBuildZH(type: Sync) { + dependsOn configurations.docs + // copy doc resources + from { + configurations.docs.collect { zipTree(it) } + } + // and doc sources + from "src/docs/asciidoc/" + // to a build directory of your choice + into "$buildDir/asciidoc/assemble" + +} + +task('makePDFZH', type: org.asciidoctor.gradle.AsciidoctorTask){ + dependsOn prepareAsciidocBuildZH + backends 'pdf' + sourceDir "$buildDir/asciidoc/assemble" + sources { + include 'index-single.adoc' + } + options doctype: 'book', eruby: 'erubis' + logDocuments = true + attributes 'icons': 'font', + 'sectanchors': '', + 'sectnums': '', + 'toc': '', + 'source-highlighter' : 'coderay', + revnumber: project.version +} + + + +asciidoctor { + dependsOn makePDFZH + backends 'html5' + sourceDir "$buildDir/asciidoc/assemble" + resources { + from(sourceDir) { + include 'images/*', 'css/**', 'js/**' + } + } + options doctype: 'book', eruby: 'erubis' + logDocuments = true + attributes 'docinfo': 'shared', + // use provided stylesheet + stylesdir: "css/", + stylesheet: 'ossez.css', + 'linkcss': true, + 'icons': 'font', + 'sectanchors': '', + // use provided highlighter + 'source-highlighter=highlight.js', + 'highlightjsdir=js/highlight', + 'highlightjs-theme=atom-one-dark-reasonable', + 'idprefix': '', + 'idseparator': '-', + 'spring-version': project.version, + 'allow-uri-read': '', + revnumber: project.version +} + + From 25f039d237bd94252bdee6f1ba08759880aecf0a Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Tue, 10 Sep 2019 23:15:37 -0400 Subject: [PATCH 20/22] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E7=9A=84=20toc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/mgspack_0.6.x.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/docs/asciidoc/mgspack_0.6.x.adoc b/src/docs/asciidoc/mgspack_0.6.x.adoc index c5aaeb3..052c6ed 100644 --- a/src/docs/asciidoc/mgspack_0.6.x.adoc +++ b/src/docs/asciidoc/mgspack_0.6.x.adoc @@ -1,6 +1,9 @@ = MessagePack Java 0.6.X QuickStart YuCheng Hu :doctype: book +:toc: left +:toclevels: 4 + :page-layout: docs :page-description: Protocol Buffers :page-keywords: Protocol Buffers From 13067122c7b40a894ea66d2148e4138e6ebfc286 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Tue, 10 Sep 2019 23:18:40 -0400 Subject: [PATCH 21/22] =?UTF-8?q?=E9=92=88=E5=AF=B9=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20.gitignore=20=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9560353 --- /dev/null +++ b/.gitignore @@ -0,0 +1,183 @@ +### Gradle ### +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +### Gradle Patch ### +**/build/ + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +.idea + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint From 02dfa8fc58552dda247a1f94ba821c416c076e1a Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Tue, 10 Sep 2019 23:20:14 -0400 Subject: [PATCH 22/22] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E7=9A=84=E6=8F=8F=E8=BF=B0=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index d2e1911..6812545 100644 --- a/README.adoc +++ b/README.adoc @@ -2,7 +2,7 @@ YuCheng Hu :doctype: book :page-layout: docs -:page-description: Protocol Buffers -:page-keywords: Protocol Buffers +:page-description: MessagePack +:page-keywords: MessagePack MessagePack 的相关文档,本文是根据官方的内容和我们项目中的具体实践进行编辑的。