3、thrift原理重点分析之自动生成的代码详解

来源:互联网 发布:xampp for linux 编辑:程序博客网 时间:2024/05/17 15:02

  我们用thrift-0.90.exe能够自动生成代码,仍用UserService.thrift为列

  首先让我们先看一下自动生成的UserService类的结构


  从这个类的结构中我们可以看到,主要有两个接口,两个Client,一个Processor,两个辅助的类*_agrs,*_result,*就是服务中的方法名称。

第一部分:接口部分:Iface、AsyncIface两个接口。

两个接口中的方法就是我们在thrift文件中定义的方法。例如:

在UserService.thrift中我们这样定义的:

service  UserService {list<User> getUser() throws (1:Ex.thriftDataException dataEx,2:Ex.thriftBusinessException businessEx,3:Ex.thriftSystemException systemEx)}
则在这两个接口中创建如下:

 public interface Iface {    public List<User> getUser() throws cn.stq.thrift.exception.thriftDataException, cn.stq.thrift.exception.thriftBusinessException, cn.stq.thrift.exception.thriftSystemException, org.apache.thrift.TException;  }  public interface AsyncIface {    public void getUser(org.apache.thrift.async.AsyncMethodCallback<AsyncClient.getUser_call> resultHandler) throws org.apache.thrift.TException;  }
Iface这个接口用于同步调用,AsyncIface这个接口用于异步调用,并且AsyncIface接口方法中多了一个参数。

 通常我们在实现服务的地方要实现这个接口。例如:

package cn.stq.thrift;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.thrift.TException;import cn.ruida.sms.portal.domain.User;import cn.stq.thrift.exception.thriftBusinessException;import cn.stq.thrift.exception.thriftDataException;import cn.stq.thrift.exception.thriftSystemException;public class UserServiceImpl implements UserService.Iface{public List<Map<String, String>> getUser() throws thriftDataException,thriftBusinessException, thriftSystemException, TException {List<Map<String, String>> list = new ArrayList<Map<String,String>>();Map<String,String>map = new HashMap<String, String>();map.put("loginName", "zhangsan");map.put("birthday", "2014-01-01");map.put("realName", "张三");list.add(map);return list;}private List<Map<String, String>> getUser(List<User> list,List<Map<String, String>> users) {for(User user:list){if(user==null){continue;}Map<String,String>map = new HashMap<String, String>();map.put("loginName", user.getLoginName());map.put("birthday", user.getBirthday());map.put("realName", user.getRealName());users.add(map);}return users;}}

并且在服务端创建TProcessor的是否也用到了这个接口:

TProcessor processor = new UserService.Processor<UserService.Iface>(new UserServiceImpl());

第二个部分:两个Client类 Client和AsyncClient,这两个Client分别对应上面的两个Iface接口,这两个Client分别实现了这两个接口。

Client类中有一下几个部分:Factory类,服务方法,send_*和recv_*方法

1)Factory类中提供了获取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);      } }
第一个getClient方法只传入了一个TProtocol协议对象,第二个getClient方法传入了两个TProtocol协议对象,

iprot:表示输入协议对象,oprot:表示输出协议对象。

前者的方法只有一个协议对象,说明输入协议对象和输出协议对象是用的同一个对象。

2)服务方法。

这里所说的服务方法就是Iface接口中定义的方法,这个服务方法在每一个thrift文件生成的类中实现是相同的。

 public List<User> getUser() throws cn.stq.thrift.exception.thriftDataException, cn.stq.thrift.exception.thriftBusinessException, cn.stq.thrift.exception.thriftSystemException, org.apache.thrift.TException    {      send_getUser();      return recv_getUser();    }
这个服务方法首先调用send_*()方法,然后返回一个recv_*()方法。

3)send_*和revc_*方法

 这里的*表示的是Iface接口的方法名称,不同的Iface,*是不同的。例如在UserService中方法名为getUser,则send_getUser()和recv_getUser().

  send_*方法

  public void send_getUser() throws org.apache.thrift.TException    {      getUser_args args = new getUser_args();      sendBase("getUser", args);    }
  revc_*方法

 public List<User> recv_getUser() throws cn.stq.thrift.exception.thriftDataException, cn.stq.thrift.exception.thriftBusinessException, cn.stq.thrift.exception.thriftSystemException, org.apache.thrift.TException    {      getUser_result result = new getUser_result();      receiveBase(result, "getUser");      if (result.isSetSuccess()) {        return result.success;      }      if (result.dataEx != null) {        throw result.dataEx;      }      if (result.businessEx != null) {        throw result.businessEx;      }      if (result.systemEx != null) {        throw result.systemEx;      }      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getUser failed: unknown result");    }  }
第三部分:Processor类

  这个类的作用封装从输入输出流中读写数据的操作,它实现了TProcessor接口。这个类在整个通信的Processor层,即处理层,是协议层与用户实现的服务代码的纽带。

第四部分:两个辅助的类*_agrs,*_result

*_agrs类封装了服务方法中的参数,getUser()方法中没有参数,如果有参数的话,则参数就是*_agrs类的属性。并且在thrift文件定义的enum、struct、都在这个类中

public static class getUser_args implements org.apache.thrift.TBase<getUser_args, getUser_args._Fields>, java.io.Serializable, Cloneable   {    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getUser_args");
*_result类封装了返回值和抛出的异常。如果有返回值的话,会存储在success属性中

public getUser_result getResult(I iface, getUser_args args) throws org.apache.thrift.TException {        getUser_result result = new getUser_result();        try {          result.success = iface.getUser();        } catch (cn.stq.thrift.exception.thriftDataException dataEx) {          result.dataEx = dataEx;        } catch (cn.stq.thrift.exception.thriftBusinessException businessEx) {          result.businessEx = businessEx;        } catch (cn.stq.thrift.exception.thriftSystemException systemEx) {          result.systemEx = systemEx;        }        return result;      }    }
通过上面的内容,我们对thrift文件自动生成的代码有了一个大致的了解。也就是我们对thrift的通信协议有了一定的了解,接下来我们就需要了解服务端和客户端是怎样的工作的了。







0 0
原创粉丝点击