<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                IDL是很多RPC框架用來支持跨語言環境調用的一個服務描述組件,一般都是采用文本格式來定義。 更多IDL的思考查看[《理解WSDL, IDL》](http://blog.csdn.net/iter_zc/article/details/39338367) Thrift的不同版本定義IDL的語法也不太相同,這里使用Thrift-0.8.0這個版本來介紹Java下的IDL定義 1. namespace 定義包名 2. struct 定義服務接口的參數,返回值使用到的類結構。如果接口的參數都是基本類型,則不需要定義struct 3. service 定義接口 一個簡單的例子,IDL文件以.thrift為后綴名。  demo.thrift 1. 定義了生成的Java文件的包名為com.thrift.test 2. 定義了一個struct類結構作為參數 3.定義了一個service接口,返回值是int,方法名叫demoMethod,參數有三個,第一個是字符串類型,第二個是上面定義的類Parameter,第三個是Map類型 ~~~ namespace java com.thrift.test struct Parameter{ 1: required i32 id; 2: required string name; } service DemoService{ i32 demoMethod(1:string param1, 2:Parameter param2, 3:map<string,string> param3); } ~~~ IDL支持的數據類型包括以下部分 ~~~ bool 布爾型 byte 8位整數 i16 16位整數 i32 32位整數 i64 64位整數 double 雙精度浮點數 string 字符串 binary 字節數組 list<i16> List集合,必須指明泛型 map<string, string> Map類型,必須指明泛型 set<i32> Set集合,必須指明泛型 ~~~ 有了IDL之后,就可以使用thrift來自動生成輔助代碼,包括客戶端代碼和序列化接口的代碼 ~~~ thrift -r --gen java demo.thrift ~~~ 生成的代碼如下 ![](https://box.kancloud.cn/2016-02-19_56c6c62b14d87.jpg) 每個Struct會單獨生成一個類,每個Service會生成一個類。 看一下生成類的具體結構 ![](https://box.kancloud.cn/2016-02-19_56c6c62b25fe8.jpg) 生成的類主要有5個部分 **1. 接口類型**,默認名稱都是Iface。這個接口類型被服務器和客戶端共同使用。服務器端使用它來做頂層接口,編寫實現類。客戶端代碼使用它作為生成代理的服務接口。 自動生成的接口有兩個,一個是同步調用的Iface,一個是異步調用的AsyncIface。異步調用的接口多了一個回調參數。 ~~~ public interface Iface { public int demoMethod(String param1, Parameter param2, Map<String,String> param3) throws org.apache.thrift.TException; } public interface AsyncIface { public void demoMethod(String param1, Parameter param2, Map<String,String> param3, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.demoMethod_call> resultHandler) throws org.apache.thrift.TException; } ~~~ **2. 客戶端類型**,一個同步調用的客戶端Client,一個異步調用的客戶端AsyncClient **3. Processor**,用來支持方法調用,每個服務的實現類都要使用Processor來注冊,這樣最后服務器端調用接口實現時能定位到具體的實現類。后面會有專門的文章介紹 **4.方法參數的封裝類**,以"方法名_args"命名 **5.方法返回值的封裝類**,以"方法名_result"命名 看一下生成的同步調用客戶端Client的具體代碼 1. 提供一個工廠方法來創建Client對象 2.接口方法的客戶端代理,只做了兩件事,發送方法調用請求;接收返回值 發送方法調用請求做了2件事 1. 創建方法參數對象,封裝方法參數 2. 調用父類的sendBase方法來發送消息。發送消息時先通過writeMessageBegin發送消息頭,再調用方法參數對象的write(TProtocol)方法發送消息體,最后結束發送 接受調用返回值做了2件事 1. 創建方法返回值對象,封裝方法返回值 2. 調用父類的receiveBase方法接收方法返回值。先通過receiveMessage接收消息體,處理異常,然后調用方法參數對象的read(TProtocol)方法來接收消息體,最后結束接收 ~~~ public static class Client extends org.apache.thrift.TServiceClient implements Iface { public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> { public Factory() {} public Client getClient(org.apache.thrift.protocol.TProtocol prot) { return new Client(prot); } public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) { return new Client(iprot, oprot); } }   public int demoMethod(String param1, Parameter param2, Map<String,String> param3) throws org.apache.thrift.TException { send_demoMethod(param1, param2, param3); return recv_demoMethod(); } public void send_demoMethod(String param1, Parameter param2, Map<String,String> param3) throws org.apache.thrift.TException { demoMethod_args args = new demoMethod_args(); args.setParam1(param1); args.setParam2(param2); args.setParam3(param3); sendBase("demoMethod", args); } public int recv_demoMethod() throws org.apache.thrift.TException { demoMethod_result result = new demoMethod_result(); receiveBase(result, "demoMethod"); if (result.isSetSuccess()) { return result.success; } throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "demoMethod failed: unknown result"); } } //org.apache.thrift.TServiceClient.sendBase,客戶端的父類方法 protected void sendBase(String methodName, TBase args) throws TException {   // 發送消息頭 ?? oprot_.writeMessageBegin(new TMessage(methodName, TMessageType.CALL, ++seqid_)); // 發送消息體,由方法參數對象自己處理編解碼 ?? args.write(oprot_); ?? oprot_.writeMessageEnd(); ?? oprot_.getTransport().flush(); } protected void receiveBase(TBase result, String methodName) throws TException { // 接收消息頭 ?? TMessage msg = iprot_.readMessageBegin(); ?? if (msg.type == TMessageType.EXCEPTION) { ???? TApplicationException x = TApplicationException.read(iprot_); ???? iprot_.readMessageEnd(); ???? throw x; ?? } ?? if (msg.seqid != seqid_) { ???? throw new TApplicationException(TApplicationException.BAD_SEQUENCE_ID, methodName + " failed: out of sequence response"); ?? } //由返回值對象自己處理編解碼 ?? result.read(iprot_); ?? iprot_.readMessageEnd(); } ~~~ 看一下方法參數對象 方法參數實現了TBase接口,TBase接口定義了一個對象在某種協議下的編解碼接口。 ~~~ public interface TBase<T extends TBase<?,?>, F extends TFieldIdEnum> extends Comparable<T>, Serializable { public void read(TProtocol iprot) throws TException; public void write(TProtocol oprot) throws TException; } ~~~ 方法參數對象主要做了2件事 1. 創建每個參數的元數據,包括參數類型,順序號。順序號是在IDL定義的時候設置的,用來識別參數的位置,在編解碼的時候有用 2. **實現自己的編解碼方法, read(TProtocol), write(TProtocol)。這里又把具體的編解碼功能委托給了XXXScheme類** ~~~ public static class demoMethod_args implements org.apache.thrift.TBase<demoMethod_args, demoMethod_args._Fields>, java.io.Serializable, Cloneable { private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("demoMethod_args"); private static final org.apache.thrift.protocol.TField PARAM1_FIELD_DESC = new org.apache.thrift.protocol.TField("param1", org.apache.thrift.protocol.TType.STRING, (short)1); private static final org.apache.thrift.protocol.TField PARAM2_FIELD_DESC = new org.apache.thrift.protocol.TField("param2", org.apache.thrift.protocol.TType.STRUCT, (short)2); private static final org.apache.thrift.protocol.TField PARAM3_FIELD_DESC = new org.apache.thrift.protocol.TField("param3", org.apache.thrift.protocol.TType.MAP, (short)3); private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>(); static { schemes.put(StandardScheme.class, new demoMethod_argsStandardSchemeFactory()); schemes.put(TupleScheme.class, new demoMethod_argsTupleSchemeFactory()); } public String param1; // required public Parameter param2; // required public Map<String,String> param3; // required /**The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ public enum _Fields implements org.apache.thrift.TFieldIdEnum { PARAM1((short)1, "param1"), PARAM2((short)2, "param2"), PARAM3((short)3, "param3"); private static final Map<String, _Fields> byName = new HashMap<String, _Fields>(); static { for (_Fields field : EnumSet.allOf(_Fields.class)) { byName.put(field.getFieldName(), field); } }   // 對象自己負責解碼  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { ???? schemes.get(iprot.getScheme()).getScheme().read(iprot, this); ?? } <pre name="code" class="java">  // 對象自己負責編碼 ?? public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { ???? schemes.get(oprot.getScheme()).getScheme().write(oprot, this); ?? } ~~~ 再來看XXXScheme類,這也是自動生成的,是方法參數XXX_args的內部類。 Scheme有兩類,一個是StandardScheme,使用消息頭+消息體的方式來編解碼對象。一個是TupleScheme,直接采用寫消息體的方式編解碼,編碼字節流更小。 ![](https://box.kancloud.cn/2016-02-19_56c6c62b69bd2.jpg) 拿demoMethod_argsStandardScheme舉例, 1. 它的編碼方法就是從writeStructBegin開始逐個寫字段,每個字段寫之前會writeFieldBegin開始,寫字段類型和字段的順序號。如果字段是一個類Struct,就調用這個類自己的編碼方法write(TProtocol)。Thrift會給每個Struct生成類,這些類里面定義了這個類的編解碼方法。最后寫完之后以writeStructEnd結束 2. 它的解碼方法從readStructBegin開始,然后讀字段元數據readFieldBegin,讀1個字節的字段類型,2個字段的字節順序號,然后根據字段類型,來讀相應類型長度的數據。直到讀完用readStructEnd結束。 ~~~ private static class demoMethod_argsStandardScheme extends StandardScheme<demoMethod_args> { public void read(org.apache.thrift.protocol.TProtocol iprot, demoMethod_args struct) throws org.apache.thrift.TException { org.apache.thrift.protocol.TField schemeField; iprot.readStructBegin(); while (true) { schemeField = iprot.readFieldBegin(); if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { break; } switch (schemeField.id) { case 1: // PARAM1 if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { struct.param1 = iprot.readString(); struct.setParam1IsSet(true); } else { org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; case 2: // PARAM2 if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) { struct.param2 = new Parameter(); struct.param2.read(iprot); struct.setParam2IsSet(true); } else { org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; case 3: // PARAM3 if (schemeField.type == org.apache.thrift.protocol.TType.MAP) { { org.apache.thrift.protocol.TMap _map0 = iprot.readMapBegin(); struct.param3 = new HashMap<String,String>(2*_map0.size); for (int _i1 = 0; _i1 < _map0.size; ++_i1) { String _key2; // required String _val3; // required _key2 = iprot.readString(); _val3 = iprot.readString(); struct.param3.put(_key2, _val3); } iprot.readMapEnd(); } struct.setParam3IsSet(true); } else { org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } break; default: org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } iprot.readFieldEnd(); } iprot.readStructEnd(); // check for required fields of primitive type, which can't be checked in the validate method struct.validate(); } public void write(org.apache.thrift.protocol.TProtocol oprot, demoMethod_args struct) throws org.apache.thrift.TException { struct.validate(); oprot.writeStructBegin(STRUCT_DESC); if (struct.param1 != null) { oprot.writeFieldBegin(PARAM1_FIELD_DESC); oprot.writeString(struct.param1); oprot.writeFieldEnd(); } if (struct.param2 != null) { oprot.writeFieldBegin(PARAM2_FIELD_DESC); struct.param2.write(oprot); oprot.writeFieldEnd(); } if (struct.param3 != null) { oprot.writeFieldBegin(PARAM3_FIELD_DESC); { oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, struct.param3.size())); for (Map.Entry<String, String> _iter4 : struct.param3.entrySet()) { oprot.writeString(_iter4.getKey()); oprot.writeString(_iter4.getValue()); } oprot.writeMapEnd(); } oprot.writeFieldEnd(); } oprot.writeFieldStop(); oprot.writeStructEnd(); } } ~~~ ~~~ private static class demoMethod_argsTupleScheme extends TupleScheme<demoMethod_args> { @Override public void write(org.apache.thrift.protocol.TProtocol prot, demoMethod_args struct) throws org.apache.thrift.TException { TTupleProtocol oprot = (TTupleProtocol) prot; BitSet optionals = new BitSet(); if (struct.isSetParam1()) { optionals.set(0); } if (struct.isSetParam2()) { optionals.set(1); } if (struct.isSetParam3()) { optionals.set(2); } oprot.writeBitSet(optionals, 3); if (struct.isSetParam1()) { oprot.writeString(struct.param1); } if (struct.isSetParam2()) { struct.param2.write(oprot); } if (struct.isSetParam3()) { { oprot.writeI32(struct.param3.size()); for (Map.Entry<String, String> _iter5 : struct.param3.entrySet()) { oprot.writeString(_iter5.getKey()); oprot.writeString(_iter5.getValue()); } } } } @Override public void read(org.apache.thrift.protocol.TProtocol prot, demoMethod_args struct) throws org.apache.thrift.TException { TTupleProtocol iprot = (TTupleProtocol) prot; BitSet incoming = iprot.readBitSet(3); if (incoming.get(0)) { struct.param1 = iprot.readString(); struct.setParam1IsSet(true); } if (incoming.get(1)) { struct.param2 = new Parameter(); struct.param2.read(iprot); struct.setParam2IsSet(true); } if (incoming.get(2)) { { org.apache.thrift.protocol.TMap _map6 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, iprot.readI32()); struct.param3 = new HashMap<String,String>(2*_map6.size); for (int _i7 = 0; _i7 < _map6.size; ++_i7) { String _key8; // required String _val9; // required _key8 = iprot.readString(); _val9 = iprot.readString(); struct.param3.put(_key8, _val9); } } struct.setParam3IsSet(true); } } } } ~~~ 方法返回值封裝類的結構和方法參數封裝類的結構和原理完全一致,這里不再贅述。 [   ](http://blog.csdn.net/iter_zc/article/details/39338367)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看