thrift中required和optional的用处

使用技术:thrift的rpc服务

问题提出:在java和.net交互的时候,默认值导致数据修改问题。

基本数据类型在服务端传输前没有设置isset值,传输到客户端还是出现isset=true的现象。

 

解决方案:将所有非必须变量添加修饰符optional,这样thrift在序列化的时候发现修饰符为optional并且

isset=false的值时,就会忽略。

 

下面的问题测试demo:

idl定义文件(BorrowPerson.thrift):
namespace java littlehow.thrift.demo.optional
#person结构,其中身高是可选的
struct Person
{
  1:i64 id,
  2:string name,
  3:i32 age,
  4:optional i16 height,
  5:optional Work work
}

#工作信息,工作年限是可选的,工资有可选参数,并且有默认值
struct Work
{
  1:i32 workid,
  2:optional i16 workage,
  3:optional string salary = "2500.00" 
}

service BorrowPerson
{
  Person borrowPerson(1:i64 personId)
} 
 
//使用命令thrift.exe -gen java BorrowPerson.thrift生成文件
文件主要结构如下:
person主体如下:
 
public long id; // required
public String name; // required
public int age; // required
public short height; // optional
public Work work; // optional

 

 
work主体如下:
 
public int workid; // required
public short workage; // optional
public String salary; // optional

 

 
borrowperson主体如下
 
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 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);
  }

  public Person borrowPerson(long personId) throws TException
  {
    send_borrowPerson(personId);
    return recv_borrowPerson();
  }

  public void send_borrowPerson(long personId) throws TException
  {
    borrowPerson_args args = new borrowPerson_args();
    args.setPersonId(personId);
    sendBase("borrowPerson", args);
  }

  public Person recv_borrowPerson() throws TException
  {
    borrowPerson_result result = new borrowPerson_result();
    receiveBase(result, "borrowPerson");
    if (result.isSetSuccess()) {
      return result.success;
    }
    throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "borrowPerson failed: unknown result");
  }

}

 

 
实际业务类:
 
package littlehow.thrift.demo.call.optional;

import littlehow.thrift.demo.optional.BorrowPerson;
import littlehow.thrift.demo.optional.Person;
import littlehow.thrift.demo.optional.Work;
import org.apache.thrift.TException;

import java.util.HashMap;
import java.util.Map;

/**
 * BorrowPerson
 *
 * @author littlehow
 * @time 2016-06-27 10:18
 */
public class BorrowPersonImpl implements BorrowPerson.Iface{
    private static Map<Long, Person> persons = new HashMap<Long, Person>();
    static {
        //所有信息齐全
        Person person = new Person();
        person.setId(1);
        person.setName("littlehow");
        person.setAge(18);
        person.setHeight((short) 140);
        Work work = new Work();
        work.setSalary("500.00");
        work.setWorkage((short) 8);
        work.setWorkid(1);
        person.setWork(work);
        persons.put(Long.valueOf(1), person);
        //所有信息不全
        person = new Person();
        person.setId(2);
        person.setName("不全");
        work = new Work();
        work.setWorkid(2);
        person.setWork(work);
        persons.put(Long.valueOf(2), person);
    }

    /**
     * 借人
     * @param personId
     * @return
     * @throws TException
     */
    public Person borrowPerson(long personId) throws TException {
        if (personId > 2 || personId < 1) return null;
        return persons.get(personId);
    }
}

 

 
测试服务端结构如下:
 
package littlehow.thrift.demo.call.optional;

import littlehow.thrift.demo.AppendService;
import littlehow.thrift.demo.call.AppendServiceImpl;
import littlehow.thrift.demo.optional.BorrowPerson;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;

/**
 * Created by littlehow on 2016/6/27 0024.
 */
public class Server {
    public final static int port = 7456;


    public void start() {
        try {
            /** BorrowPerson */
            TProcessor processor = new BorrowPerson.Processor<BorrowPersonImpl>(new BorrowPersonImpl());
            /** 设置监听端口 */
            TServerTransport transport = new TServerSocket(port);
            /** 采用TCompactProtocol传输协议,服务端和客户端协议使用必须一致
             * 可选的协议有:TBinaryProtocol/TJSONProtocol/TSimpleJSONProtocol/TTupleProtocol
             * 其中TTupleProtocol是TCompactProtocol的子类,可以根据自己的业务选择对应的协议
             */
            TProtocolFactory pf = new TCompactProtocol.Factory();
            TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(transport).protocolFactory(pf).processor(processor));
            System.out.println("server started ,port is " + port);
            server.serve();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Server().start();
    }
}

 

 
测试客户端:
 
package littlehow.thrift.demo.call.optional;

import littlehow.thrift.demo.AppendService;
import littlehow.thrift.demo.call.Server;
import littlehow.thrift.demo.optional.BorrowPerson;
import littlehow.thrift.demo.optional.Person;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;

/**
 * Created by littlehow on 2016/6/27 0024.
 */
public class Client {
    public final String address = "localhost";

    public void run() {
        try {
            TTransport transport = new TSocket(address, Server.port);
            transport.open();
            TProtocol protocol = new TCompactProtocol(transport);
            BorrowPerson.Client client = new BorrowPerson.Client(protocol);
            System.out.println(System.currentTimeMillis());
            //信息齐全
            Person person1 = client.borrowPerson(1);
            //Person(id:1, name:littlehow, age:18, height:140, work:Work(workid:1, workage:8, salary:500.00))
            System.out.println(person1);
            //信息不全
            Person person2 = client.borrowPerson(2);
            //Person(id:2, name:不全, age:0, work:Work(workid:2, salary:2500.00))
            System.out.println(person2);
            System.out.println("height的设置情况:"+person2.isSetHeight());//false
            System.out.println("age的设置情况:"+person2.isSetAge());//true
            System.out.println("work.workage的设置情况:" + person2.getWork().isSetWorkage());//false
            System.out.println(System.currentTimeMillis());
            transport.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Client().run();
    }
}

 

 
测试结果分析:
person1的信息都设置,所以信息都是齐全的。
对person2的输出进行一些讲解:
Person(id:2, name:不全, age:0, work:Work(workid:2, salary:2500.00))

 

 
为什么age:0会被输出,被输出就表明被反序列化回来了,可是我在客户端就没有设置age值啊;
因为:age在定义idl文件的时候用的是默认的修饰(required),所以age会被传输,就是这么简单,
那么后面的height,age,workage的isset输出就知道为什么了,
因为height和workage的修饰变量是optional,所以isset=false,age是required,所以isset=true。
还有一个就是work中salary:2500.00,这个值在服务端没有设置,传输到客户端为什么是2500.00呢,
因为idl文件中有定义default的值为2500.00。
 
想了解thrift设置的详细信息,可以查看链接:

 

 

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Thrift和Protobuf都是用于进行通信传输的工具。Thrift是一个跨语言的远程服务调用框架,支持多种语言,如C++, Java, Python等。而Protobuf是Google开发的一种高效的数据序列化格式,同样也支持多种语言。 Thrift的使用流程如下: 1. 定义thrift文件,该文件定义了数据结构和接口。可以使用IDL语言来描述。 2. 使用thrift编译器生成目标语言的代码。比如使用thrift --gen cpp company.thrift命令可以生成C++的代码。 3. 在代码实现业务逻辑,并调用thrift生成的代码来进行通信操作。 4. 在服务器端,监听指定的端口并处理客户端发送的请求。 5. 在客户端,创建thrift的客户端实例,调用生成的代码的接口进行远程调用。 与Protobuf相比,Thrift在使用上有一些区别。Thrift支持更多编程语言,而Protobuf主要支持C++、Java和Python。另外,Thrift在通信协议方面更灵活,可以支持多种协议,如二进制、压缩、JSON等。而Protobuf主要使用二进制协议进行数据传输。 总的来说,Thrift和Protobuf都是用于进行通信传输的工具,但在实际使用需要根据具体的需求和技术栈选择合适的工具。 [2 [3<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C++ thrift详细教程 及和Protobuf对比](https://blog.csdn.net/zsk4232000/article/details/50353777)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值