IDL 生成文件

IDL 生成文件在 thrift 栈中的位置。
在这里插入图片描述
对于如下的 thrift :

namespace java com.meituan.service
service HelloService
{   
    string sayHello(1:string username)
}

生成:

// thrift 0.8.0
public class HelloService {
		public interface Iface{
    		public String sayHello(String username) throws org.apache.thrift.TException;
    }
    public interface AsyncIface{
        public void sayHello(String username, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.sayHello_call> resultHandler) throws org.apache.thrift.TException;
    }
  
    public static class Client extends org.apache.thrift.TServiceClient implements Iface {}
    public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {}
    public static class Processor<I extends Iface> extends org.apache.thrift.TBaseProcessor<I> implements org.apache.thrift.TProcessor {}
    public static class sayHello_args implements org.apache.thrift.TBase<sayHello_args, sayHello_args._Fields>, java.io.Serializable, Cloneable {}
    public static class sayHello_result implements org.apache.thrift.TBase<sayHello_result, sayHello_result._Fields>, java.io.Serializable, Cloneable {}
}

Iface & AsyncIface

接口类型被服务器和客户端共同使用。服务器端使用它来做顶层接口,编写实现类。客户端代码使用它作为生成代理的服务接口。

自动生成的接口有两个,一个是同步调用的Iface,一个是异步调用的AsyncIface。异步调用的接口多了一个回调参数。

public interface AsyncMethodCallback<T> {
  public void onComplete(T response);
  public void onError(Exception exception);
}

Client & AsyncClient

public static class Client extends org.apache.thrift.TServiceClient implements Iface {
    // Client 工厂类
    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 Client(org.apache.thrift.protocol.TProtocol prot)
    {
      super(prot, prot);
    }

    public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
      super(iprot, oprot);
    }

    // Iface.sayHello 的实现
    public String sayHello(String username) throws org.apache.thrift.TException
    {
      send_sayHello(username);
      return recv_sayHello();
    }

    public void send_sayHello(String username) throws org.apache.thrift.TException
    {
      // 方法参数的封装类
      sayHello_args args = new sayHello_args();
      args.setUsername(username);
      // 
      sendBase("sayHello", args);
    }

    public String recv_sayHello() throws org.apache.thrift.TException
    {
      // 方法返回值的封装类
      sayHello_result result = new sayHello_result();
      // 
      receiveBase(result, "sayHello");
      if (result.isSetSuccess()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "sayHello failed: unknown result");
    }
  }

参数的发送和结果的返回委托给 TServiceClient 来处理

public abstract class TServiceClient {
    public TServiceClient(TProtocol prot) {
        this(prot, prot);
    }

    public TServiceClient(TProtocol iprot, TProtocol oprot) {
        iprot_ = iprot;
        oprot_ = oprot;
    }

    protected TProtocol iprot_;
    protected TProtocol oprot_;

    protected int seqid_;

    public TProtocol getInputProtocol() {
        return this.iprot_;
    }

    public TProtocol getOutputProtocol() {
        return this.oprot_;
    }

    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();
    }
}

// TServiceClient 的工厂类
public interface TServiceClientFactory<T extends TServiceClient> {
  public T getClient(TProtocol prot);
  public T getClient(TProtocol iprot, TProtocol oprot);
}

Processor

用来支持方法调用,每个服务的实现类都要使用Processor来注册,这样最后服务器端调用接口实现时能定位到具体的实现类。

sayHello_args

方法参数的封装类。

sayHello_args 继承了 TBase,其中包含请求参数的编解码方法 read & write。

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;
  public F fieldForId(int fieldId);
  public boolean isSet(F field);
  public Object getFieldValue(F field);
  public void setFieldValue(F field, Object value);
  public TBase<T, F> deepCopy();
  public void clear();
}
private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<>();                                                                                          
static {                                                                                    
    schemes.put(StandardScheme.class, new sayHello_argsStandardSchemeFactory());            
    schemes.put(TupleScheme.class, new sayHello_argsTupleSchemeFactory());                  
}                                                                                           
@Override                                                                                          
public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { 
    schemes.get(iprot.getScheme()).getScheme().read(iprot, this);                                  
}                                                                                                                                                                                                    
@Override                                                                                          
public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
    schemes.get(oprot.getScheme()).getScheme().write(oprot, this);                                 
}

public interface IScheme<T extends TBase> {
  public void read(org.apache.thrift.protocol.TProtocol iproto, T struct) throws org.apache.thrift.TException;
  public void write(org.apache.thrift.protocol.TProtocol oproto, T struct) throws org.apache.thrift.TException;
}
// IScheme 的两个抽象实现类
public abstract class StandardScheme<T extends TBase> implements IScheme<T> {}
public abstract class TupleScheme<T extends TBase> implements IScheme<T> {}

Thrift 生成的参数类把具体的编解码功能委托给了 XXXScheme 类

private static class sayHello_argsStandardSchemeFactory implements SchemeFactory {                                                        
    @Override                                                                                                                             
    public sayHello_argsStandardScheme getScheme() {                                                                                      
        return new sayHello_argsStandardScheme();                                                                                         
    }                                                                                                                                     
}                                                                                                                                                                                                                                                                                  
private static class sayHello_argsStandardScheme extends StandardScheme<sayHello_args> {                                                                                                                                                                                 
    @Override                                                                                                                             
    public void read(org.apache.thrift.protocol.TProtocol iprot, sayHello_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: // USERNAME                                                                                                       
                    if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {                                                    
                        struct.username = iprot.readString();                                                                             
                        struct.setUsernameIsSet(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();                                                                                                                                                                                                                                        
        struct.validate();                                                                                                                
    }                                                                                                                                     
                                                                                                                                          
    @Override                                                                                                                             
    public void write(org.apache.thrift.protocol.TProtocol oprot, sayHello_args struct) throws org.apache.thrift.TException {             
        struct.validate();                                                                                                                
                                                                                                                                          
        oprot.writeStructBegin(STRUCT_DESC);                                                                                              
        if (struct.username != null) {                                                                                                    
            oprot.writeFieldBegin(USERNAME_FIELD_DESC);                                                                                   
            oprot.writeString(struct.username);                                                                                           
            oprot.writeFieldEnd();                                                                                                        
        }                                                                                                                                 
        oprot.writeFieldStop();                                                                                                           
        oprot.writeStructEnd();                                                                                                           
    }                                                                                                                                                                                                                                                                           
}                                                                                                                                         

_Fields 为参数 id 和参数名称的便捷查找类。

// thrift 中每一个参数都有唯一的序号
public interface TFieldIdEnum {
  public short getThriftFieldId();
  public String getFieldName();
}


public enum _Fields implements org.apache.thrift.TFieldIdEnum {                                                               
    USERNAME((short) 1, "username");                                                                                          
                                                                                                                              
    private static final Map<String, _Fields> byName = new HashMap<>();                                        
                                                                                                                              
    static {                                                                                                                  
        for (_Fields field : EnumSet.allOf(_Fields.class)) {                                                                  
            byName.put(field.getFieldName(), field);                                                                          
        }                                                                                                                     
    }                                                                                                                         
                                                                                                                                                                                                                                                  
    public static _Fields findByThriftId(int fieldId) {                                                                       
        switch (fieldId) {                                                                                                    
            case 1: // USERNAME                                                                                               
                return USERNAME;                                                                                              
            default:                                                                                                          
                return null;                                                                                                  
        }                                                                                                                     
    }                                                                                                                         
                                                                                                                                                                                                                                                   
    public static _Fields findByThriftIdOrThrow(int fieldId) {                                                                
        _Fields fields = findByThriftId(fieldId);                                                                             
        if (fields == null) {                                                                                                 
          throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");                                         
        }                                                                                                                     
        return fields;                                                                                                        
    }                                                                                                                         
                                                                                                                                                                                                                                                    
    public static _Fields findByName(String name) {                                                                           
        return byName.get(name);                                                                                              
    }                                                                                                                         
                                                                                                                              
    private final short _thriftId;                                                                                            
    private final String _fieldName;                                                                                          
                                                                                                                              
    _Fields(short thriftId, String fieldName) {                                                                               
        _thriftId = thriftId;                                                                                                 
        _fieldName = fieldName;                                                                                               
    }                                                                                                                         
                                                                                                                              
    @Override                                                                                                                 
    public short getThriftFieldId() {                                                                                         
        return _thriftId;                                                                                                     
    }                                                                                                                         
                                                                                                                              
    @Override                                                                                                                 
    public String getFieldName() {                                                                                            
        return _fieldName;                                                                                                    
    }                                                                                                                         
}                                                                                                                             

EnumSet.allOf 的使用

import java.util.EnumSet;

/**
 * @author liguanghui02
 * @date 2019/10/11
 */
public enum Tenum {
    RED("red", 1),
    WHITE("white", 2),
    BLACK("black", 3),
    YELLOW("yellow", 4);
    

    private String name;
    private int id;


    Tenum(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public static void main(String[] args) {
        EnumSet<Tenum> tenums = EnumSet.allOf(Tenum.class);
        for (Tenum tenum : tenums) {
            System.out.println(tenum.getName() + ":" + tenum.getId());
        }
    }
}

javap -v Tenum

在这里插入图片描述
这就是 EnumSet.allOf 为什么可以获得所有枚举原因。

sayHello_result

方法返回值的封装类。

与 sayHello_args 类似,不再赘述。

总结

sayHello_result 封装的返回参数的索引为0,名称为 success,因为返回值只能有一个呦。

sayHello_args 封装的请求参数的索引为1,2,3…

thrift 将其他语言中类的概念抽象为 struct

// 伪代码,thrift 不支持 struct 嵌套
struct A {
    struct B {
        struct C {
        }
    }
}

thrift 使用一个字节 00 标识 struct 的结束,对于上面的代码,结束标记为 00 00 00。

客户端仅仅使用了 IDL 生成文件中的 【Iface、Client、sayHello_args、sayHello_result】。

服务端使用 Processor、AsyncProcessor。

TField

public class TField {
    public final String name;
    public final byte type;
    public final short id;

}

TField 标识一个参数,【参数名称:参数类型:序号】

namespace java com.meituan.service
service HelloService
{   
    string sayHello(1:string username)
}

对应:org.apache.thrift.protocol.TField(“username”, org.apache.thrift.protocol.TType.STRING, (short)1)

TStruct

public final class TStruct {
  public final String name;
}

field 的集合。

发布了778 篇原创文章 · 获赞 323 · 访问量 209万+

猜你喜欢

转载自blog.csdn.net/lgh1992314/article/details/105285511
今日推荐