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

  我们用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的通信协议有了一定的了解,接下来我们就需要了解服务端和客户端是怎样的工作的了。







  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用 Line thrift 协议的示例代码: ```thrift namespace java com.example struct Person { 1: required string name; 2: optional i32 age; } service PersonService { Person getPerson(1: string name); } ``` 通过上述 thrift 定义文件,可以生成对应的 Java 类和接口代码。假设生成的 Java 代码包名为 `com.example`,则 `Person` 类和 `PersonService` 接口的代码如下: ```java package com.example; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; public class Person { private String name; private Integer age; public Person() {} public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } public interface PersonService { public Person getPerson(String name) throws TException; } public class PersonServiceClient implements PersonService { private TTransport transport; private TProtocol protocol; private PersonService.Client client; public PersonServiceClient() throws TTransportException { transport = new TSocket("localhost", 9090); protocol = new TBinaryProtocol(transport); client = new PersonService.Client(protocol); transport.open(); } public void close() { transport.close(); } public Person getPerson(String name) throws TException { return client.getPerson(name); } } public class PersonServiceHandler implements PersonService.Iface { public Person getPerson(String name) throws TException { // TODO: implement the logic to retrieve the person data return new Person(name, 30); } } ``` 在上述代码中,`Person` 类表示一个人的信息,包括姓名和年龄。`PersonService` 接口定义了一个获取人员信息的方法 `getPerson`。`PersonServiceClient` 类是一个 thrift 客户端,用于调用 `getPerson` 方法。`PersonServiceHandler` 类是一个 thrift 服务端,实现了 `getPerson` 方法的具体逻辑。这些类的代码都是根据上述 thrift 定义文件自动生成的。同时,代码中也包含了使用 thrift 进行网络通信的相关代码,如 `TTransport`、`TProtocol` 和 `TSocket` 等类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值