Protocol buffer配置-生成jar包和java文件

    Protocol Buffer是谷歌開源的一種序列化和反序列化機制,類似於XML,JSON 解析,但是Protocol Buffer 更靈活、更高效、更簡單。
    具體在實際開發中,Protocal Buffer表現怎麼樣,我也不知道,因爲我很少用它,至於爲什麼會學習它,完全是因爲Android Launcher3裏面的backup.proto把我牽引了過去,Protocol buffer的高效性,谷歌官網也有實例來說明,而執行消耗時間精確到了納秒,關於它的詳細介紹還是看官網:https://developers.google.com/protocol-buffers。 嗯,沒錯,又是英文,又要FQ。
    這個開源項目,谷歌已經放到了github,Link:https://github.com/google/protobuf/ , release版本:https://github.com/google/protobuf/releases
    那麼現在就以Java來配置Protocol buffer,操作系統是Windows,目的:手動編譯jar包,手動將xx.proto文件生成爲xx.java文件。  
    要編譯,那麼就要環境。根據根據github上的文檔,它是用maven來管理的,Link:https://github.com/google/protobuf/tree/master/java
    下載安裝maven,並加入環境變量,例如:     
D:\apache-maven-3.3.9\bin;D:\protobuf-3.0.0-alpha-2\src
    下載Protocol buffer 文件,例如我用的:protobuf-java-3.0.0-alpha-2.zip
    下載Protocol 可執行文件,Link:http://central.maven.org/maven2/com/google/protobuf/protoc/ 選擇對應的版本,我使用的是:protoc-3.0.0-alpha-2-windows-x86_32.exe。
    解壓protobuf-java-3.0.0-alpha-2.zip,並將protoc-3.0.0-alpha-2-windows-x86_32.exe重命名爲protoc.exe,複製到protobuf-java-3.0.0-alpha-2/src目錄下,同樣將protoc.exe路徑加入到環境變量。
    打開cmd 切換到protobuf-java-3.0.0-alpha-2目錄,可查詢maven 和 protoc.exe的版本號:
    
    然後根據github上文檔的提示:mvn install (安裝相關庫),切換到../javanano目錄,mvn test(測試環境是否配置妥當):
    
    出現上面界面,基本上環境是沒有問題了,就可以mvn package:
    
    然後到目錄../javanano/target下,就會看到protobuf-javanano-3.0.0-alpha-2.jar了,至此,手動生成JAR包,成功!
    
    然後就來手動解析xx.proto文件,將它生成爲xx.java文件。這裏以protobuf-java-3.0.0-alpha-2/example裏面的例子來實驗一下。
    這個操作需要指令,官網和github上的文檔都有說明:   
    protoc --proto_path=src --java_out=build/gen src/foo.proto
    protoc 就是protoc.exe了,前面已經加入到環境變量中, proto_path 就是xx.proto的路徑了,java_out就是生成的xx.java文件的存放路徑了,最後面跟着還是xx.proto文件
    這裏,以examples/addressbook.proto 爲例。
    在cmd敲入如下指令:   
protoc --proto_path=examples --java_out=examples examples/addressbook.proto
    遺憾的是,沒有成功,報錯了:
    
    意思是說,addressbook.proto 文件中需要使用syntax = "proto2",這個屬性,根據proto的版本來的。在addressbook.proto中加上這句話:   
    ...
    syntax = "proto2";
    package tutorial;
    option java_package = "com.example.tutorial";
    option java_outer_classname = "AddressBookProtos";
    ...
    再重新執行上面的命令,結果成功生成了AddressBookProtos.java文件,文件路徑:../examples/com/example/tutorial/AddressBookProtos.java:   
    package com.example.tutorial;
    public final class AddressBookProtos {
          private AddressBookProtos() {}
          public static void registerAllExtensions(
              com.google.protobuf.ExtensionRegistry registry) {
          }
          public interface PersonOrBuilder extends
          // @@protoc_insertion_point(interface_extends:tutorial.Person)
          com.google.protobuf.MessageOrBuilder {

        /**
         * <code>required string name = 1;</code>
         */
        boolean hasName();
        /**
         * <code>required string name = 1;</code>
         */
        java.lang.String getName();
       ......
   }
      那麼好,有點小激動,終於生成了xx.java文件了。不過很遺憾的是,xx.java文件是生成了,但是此文件生成的是錯誤的,裏面的內容是有問題的,在實際的開發中,
  當引用這個文件中的內容後,肯定會報錯。那麼爲什麼了。
      剛接觸protocol buffer的朋友,肯定會跟我剛開始一樣以爲成功了,其實非也。那麼請注意,我使用的protoc版本爲nano版本,在protobuf-3.0.0-alpha-2目錄下沒有
  java目錄,而是javanano目錄,對,就是這個坑,我掉進去了。
      這兩個版本之前是有區別的,不妨打開protobuf-3.0.0-alpha-2/javanano/Pom.xml文件,查看下groupId:
     <groupId>com.google.protobuf.nano</groupId>
     <artifactId>protobuf-javanano</artifactId>
     <version>3.0.0-alpha-2</version>
     而在非nano版本中,groupId爲: <groupId>com.google.protobuf</groupId>,回去看看生成的AddressBookProtos.java文件,會有部分類似於下面這條語句的內容:    
com.google.protobuf.ExtensionRegistry registry
     所有這些內容,對於nano版本都是錯誤的,前面的com.google.protobuf都應該對應於groundId,所以對於nano版本,應該爲:
com.google.protobuf.nano.ExtensionRegistry registry
     那麼問題出在哪裏,要跳出這個坑,還需要認真閱讀文檔,請參閱protobuf-3.0.0-alpha-2/javanano/README.tet,
     或者https://github.com/google/protobuf/tree/master/javanano。有這麼一段內容:   
- Invoke with --javanano_out, e.g.:
    ./protoc '--javanano_out=\
    java_package=src/proto/simple-data.proto|my_package,\
    java_outer_classname=src/proto/simple-data.proto|OuterName\
     :.' src/proto/simple-data.proto
    於是乎我果斷將java_out修改爲javanano_out:    
protoc --proto_path=examples --javanano_out=examples examples/addressbook.proto
    生成的xx.java文件如下:   
public interface AddressBookProtos {

      public static final class Person extends
      com.google.protobuf.nano.MessageNano {

      // enum PhoneType
      public static final int MOBILE = 0;
      public static final int HOME = 1;
      public static final int WORK = 2;

      public static final class PhoneNumber extends
         com.google.protobuf.nano.MessageNano {

         private static volatile PhoneNumber[] _emptyArray;
         public static PhoneNumber[] emptyArray() {
         // Lazily initializes the empty array
          if (_emptyArray == null) {
             synchronized (
                com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {
             if (_emptyArray == null) {
              _emptyArray = new PhoneNumber[0];
              }
            }
          }
          return _emptyArray;
        }
     ...
    }
  看到上面的內容,終於出現了com.google.protobuf.nano.xxxxx,這樣就跟grounpId對應上了,對應於nano版本。
  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章