当前位置:   article > 正文

thrift中required和optional的用处_thriftoptional使用

thriftoptional使用

使用技术:thrift的rpc服务

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

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

 

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

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

 

下面的问题测试demo:

  1. idl定义文件(BorrowPerson.thrift):
  2. namespace java littlehow.thrift.demo.optional
  3. #person结构,其中身高是可选的
  4. struct Person
  5. {
  6.   1:i64 id,
  7.   2:string name,
  8.   3:i32 age,
  9.   4:optional i16 height,
  10.   5:optional Work work
  11. }
  12. #工作信息,工作年限是可选的,工资有可选参数,并且有默认值
  13. struct Work
  14. {
  15.   1:i32 workid,
  16.   2:optional i16 workage,
  17.   3:optional string salary = "2500.00" 
  18. }
  19. service BorrowPerson
  20. {
  21.   Person borrowPerson(1:i64 personId)
 
//使用命令thrift.exe -gen java BorrowPerson.thrift生成文件
文件主要结构如下:
person主体如下:
 
  1. public long id; // required
  2. public String name; // required
  3. public int age; // required
  4. public short height; // optional
  5. public Work work; // optional

 

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

 

 
borrowperson主体如下
 
  1. public static class Client extends org.apache.thrift.TServiceClient implements Iface {
  2. public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
  3. public Factory() {}
  4. public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
  5. return new Client(prot);
  6. }
  7. public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
  8. return new Client(iprot, oprot);
  9. }
  10. }
  11. public Client(org.apache.thrift.protocol.TProtocol prot)
  12. {
  13. super(prot, prot);
  14. }
  15. public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
  16. super(iprot, oprot);
  17. }
  18. public Person borrowPerson(long personId) throws TException
  19. {
  20. send_borrowPerson(personId);
  21. return recv_borrowPerson();
  22. }
  23. public void send_borrowPerson(long personId) throws TException
  24. {
  25. borrowPerson_args args = new borrowPerson_args();
  26. args.setPersonId(personId);
  27. sendBase("borrowPerson", args);
  28. }
  29. public Person recv_borrowPerson() throws TException
  30. {
  31. borrowPerson_result result = new borrowPerson_result();
  32. receiveBase(result, "borrowPerson");
  33. if (result.isSetSuccess()) {
  34. return result.success;
  35. }
  36. throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "borrowPerson failed: unknown result");
  37. }
  38. }

 

 
实际业务类:
 
  1. package littlehow.thrift.demo.call.optional;
  2. import littlehow.thrift.demo.optional.BorrowPerson;
  3. import littlehow.thrift.demo.optional.Person;
  4. import littlehow.thrift.demo.optional.Work;
  5. import org.apache.thrift.TException;
  6. import java.util.HashMap;
  7. import java.util.Map;
  8. /**
  9. * BorrowPerson
  10. *
  11. * @author littlehow
  12. * @time 2016-06-27 10:18
  13. */
  14. public class BorrowPersonImpl implements BorrowPerson.Iface{
  15. private static Map<Long, Person> persons = new HashMap<Long, Person>();
  16. static {
  17. //所有信息齐全
  18. Person person = new Person();
  19. person.setId(1);
  20. person.setName("littlehow");
  21. person.setAge(18);
  22. person.setHeight((short) 140);
  23. Work work = new Work();
  24. work.setSalary("500.00");
  25. work.setWorkage((short) 8);
  26. work.setWorkid(1);
  27. person.setWork(work);
  28. persons.put(Long.valueOf(1), person);
  29. //所有信息不全
  30. person = new Person();
  31. person.setId(2);
  32. person.setName("不全");
  33. work = new Work();
  34. work.setWorkid(2);
  35. person.setWork(work);
  36. persons.put(Long.valueOf(2), person);
  37. }
  38. /**
  39. * 借人
  40. * @param personId
  41. * @return
  42. * @throws TException
  43. */
  44. public Person borrowPerson(long personId) throws TException {
  45. if (personId > 2 || personId < 1) return null;
  46. return persons.get(personId);
  47. }
  48. }

 

 
测试服务端结构如下:
 
  1. package littlehow.thrift.demo.call.optional;
  2. import littlehow.thrift.demo.AppendService;
  3. import littlehow.thrift.demo.call.AppendServiceImpl;
  4. import littlehow.thrift.demo.optional.BorrowPerson;
  5. import org.apache.thrift.TProcessor;
  6. import org.apache.thrift.protocol.TCompactProtocol;
  7. import org.apache.thrift.protocol.TProtocolFactory;
  8. import org.apache.thrift.server.TServer;
  9. import org.apache.thrift.server.TThreadPoolServer;
  10. import org.apache.thrift.transport.TServerSocket;
  11. import org.apache.thrift.transport.TServerTransport;
  12. /**
  13. * Created by littlehow on 2016/6/27 0024.
  14. */
  15. public class Server {
  16. public final static int port = 7456;
  17. public void start() {
  18. try {
  19. /** BorrowPerson */
  20. TProcessor processor = new BorrowPerson.Processor<BorrowPersonImpl>(new BorrowPersonImpl());
  21. /** 设置监听端口 */
  22. TServerTransport transport = new TServerSocket(port);
  23. /** 采用TCompactProtocol传输协议,服务端和客户端协议使用必须一致
  24. * 可选的协议有:TBinaryProtocol/TJSONProtocol/TSimpleJSONProtocol/TTupleProtocol
  25. * 其中TTupleProtocol是TCompactProtocol的子类,可以根据自己的业务选择对应的协议
  26. */
  27. TProtocolFactory pf = new TCompactProtocol.Factory();
  28. TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(transport).protocolFactory(pf).processor(processor));
  29. System.out.println("server started ,port is " + port);
  30. server.serve();
  31. } catch (Exception e) {
  32. e.printStackTrace();
  33. }
  34. }
  35. public static void main(String[] args) {
  36. new Server().start();
  37. }
  38. }

 

 
测试客户端:
 
  1. package littlehow.thrift.demo.call.optional;
  2. import littlehow.thrift.demo.AppendService;
  3. import littlehow.thrift.demo.call.Server;
  4. import littlehow.thrift.demo.optional.BorrowPerson;
  5. import littlehow.thrift.demo.optional.Person;
  6. import org.apache.thrift.protocol.TCompactProtocol;
  7. import org.apache.thrift.protocol.TProtocol;
  8. import org.apache.thrift.transport.TSocket;
  9. import org.apache.thrift.transport.TTransport;
  10. /**
  11. * Created by littlehow on 2016/6/27 0024.
  12. */
  13. public class Client {
  14. public final String address = "localhost";
  15. public void run() {
  16. try {
  17. TTransport transport = new TSocket(address, Server.port);
  18. transport.open();
  19. TProtocol protocol = new TCompactProtocol(transport);
  20. BorrowPerson.Client client = new BorrowPerson.Client(protocol);
  21. System.out.println(System.currentTimeMillis());
  22. //信息齐全
  23. Person person1 = client.borrowPerson(1);
  24. //Person(id:1, name:littlehow, age:18, height:140, work:Work(workid:1, workage:8, salary:500.00))
  25. System.out.println(person1);
  26. //信息不全
  27. Person person2 = client.borrowPerson(2);
  28. //Person(id:2, name:不全, age:0, work:Work(workid:2, salary:2500.00))
  29. System.out.println(person2);
  30. System.out.println("height的设置情况:"+person2.isSetHeight());//false
  31. System.out.println("age的设置情况:"+person2.isSetAge());//true
  32. System.out.println("work.workage的设置情况:" + person2.getWork().isSetWorkage());//false
  33. System.out.println(System.currentTimeMillis());
  34. transport.close();
  35. } catch (Exception e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. public static void main(String[] args) {
  40. new Client().run();
  41. }
  42. }

 

 
测试结果分析:
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设置的详细信息,可以查看链接:

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/220852
推荐阅读
相关标签
  

闽ICP备14008679号