Apache Thrift learning (2): Getting started with Thrift

Install Thrift

Download the compiler on the official website: https://thrift.apache.org/download

My computer is windows, the downloaded file is decompressed into thrift-0.13.0.exe, renamed to: thrift.exe, just put it in a path.

Configure system variable Path:

Test whether the installation is successful:

.thrift file writing

The composition of the .thrift file is introduced in " Apache Thrift Learning (1): Detailed Introduction to Thrift ". I wo n't repeat it here. Please refer to the official website for detailed documents.

//java的包名
namespace java com.leolee.thrift.person

//定义数据类型的别名
typedef i16 short
typedef i32 int
typedef i64 long
typedef bool boolean
typedef string String

struct Person {

    1: optional String name,
    2: optional int age,
    3: optional boolean married

}


//自定义异常
exception DataException {

    1: optional String msg,
    2: optional String callStack,
    3: optional String data

}

//接口
service PersonService {

    Person getPersonByName(1: required String name) throws (1: DataException dataException),

    void savePerson(1: required Person person) throws (1: DataException dataException),

}

It should be noted here that Thrift supports the use of typedef to define type aliases, and there must also be field identifiers such as " 1:". The attribute used to identify the field in serialized data transmission.

Generate Java code

Generate code in the corresponding directory:

thrift --gen java src/thrift/data.thrift

This command will generate Java code in the current directory through the relative path of the  .thrift file.

Generated DataException (custom exception), Person (java object corresponding to struct), PersonService (business interface layer)

Copy the generated Java files to the project and introduce the Thrift related dependencies of the project:

Write client and server code

First complete the implementation class of PersonService:

package com.leolee.thrift.person.serviceImpl;

import com.leolee.thrift.person.DataException;
import com.leolee.thrift.person.Person;
import com.leolee.thrift.person.PersonService;
import org.apache.thrift.TException;

/**
 * @ClassName PersonServiceImpl
 * @Description: 实现在data.thrift中定义的接口
 * @Author LeoLee
 * @Date 2020/9/6
 * @Version V1.0
 **/
public class PersonServiceImpl implements PersonService.Iface {

    @Override
    public Person getPersonByName(String name) throws DataException, TException {//此处

        System.out.println("Got client param:" + name);

        Person person = new Person();
        person.setAge(25);
        person.setName(name);
        person.setMarried(false);

        System.out.println("getPersonByName调用成功");
        return person;
    }

    @Override
    public void savePerson(Person person) throws DataException, TException {

        System.out.println(person.getName());
        System.out.println(person.getAge());
        System.out.println(person.isMarried());
        System.out.println("savePerson调用成功");
    }
}

Server:

package com.leolee.thrift.person;

import com.leolee.thrift.person.serviceImpl.PersonServiceImpl;
import org.apache.thrift.TProcessorFactory;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TTransportException;

/**
 * @ClassName ThriftServer
 * @Description: thrift服务端
 * @Author LeoLee
 * @Date 2020/9/6
 * @Version V1.0
 **/
public class ThriftServer {

    public static void main(String[] args) throws TTransportException {

        TNonblockingServerSocket serverSocket = new TNonblockingServerSocket(8899);//socket通道对象创建
        THsHaServer.Args arg = new THsHaServer.Args(serverSocket).minWorkerThreads(2).maxWorkerThreads(4);
        PersonService.Processor<PersonServiceImpl> processor = new PersonService.Processor<>(new PersonServiceImpl());

        //工厂
        arg.protocolFactory(new TCompactProtocol.Factory());//协议层工厂对象,该对象会将二进制字节码,最大限度的压缩
        arg.transportFactory(new TFramedTransport.Factory());//构建Framed传输层工厂对象
        arg.processorFactory(new TProcessorFactory(processor));

        TServer server = new THsHaServer(arg);
        System.out.println("Thrift server started");

        //死循环,源源不断的接受socket中传递的请求
        server.serve();
    }
}

Client:

package com.leolee.thrift.person;

import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;

/**
 * @ClassName ThriftClient
 * @Description: Thrift 客户端
 * @Author LeoLee
 * @Date 2020/9/6
 * @Version V1.0
 **/
public class ThriftClient {

    public static void main(String[] args) {

        //服务端transport用的是TFramedTransport,客户端也要用TFramedTransport
        TTransport transport = new TFramedTransport(new TSocket("127.0.0.1", 8899), 60);//对应服务端的传输层方法[TFramed]
        TProtocol protocol = new TCompactProtocol(transport);//对应服务端的协议层方法[TCompact]
        PersonService.Client client = new PersonService.Client(protocol);

        try {
            //打开连接
            transport.open();
            Person person = client.getPersonByName("LeoLee");
            System.out.println("打印getPersonByName请求结果:");
            System.out.println(person.getName());
            System.out.println(person.getAge());
            System.out.println(person.isMarried());

            System.out.println("------------------------");

            Person person2 = new Person();
            person2.setName("LeoLee");
            person2.setAge(25);
            person2.setMarried(false);
            client.savePerson(person2);

        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            transport.close();
        }

    }
}

As you can see, it is very similar to Netty's Socket communication:

  • The server is bound to the port number (8899)
  • Set the server channel communication parameters and add the Service layer interface
        THsHaServer.Args arg = new THsHaServer.Args(serverSocket).minWorkerThreads(2).maxWorkerThreads(4);
        PersonService.Processor<PersonServiceImpl> processor = new PersonService.Processor<>(new PersonServiceImpl());

        //工厂
        arg.protocolFactory(new TCompactProtocol.Factory());
        arg.transportFactory(new TFramedTransport.Factory());
        arg.processorFactory(new TProcessorFactory(processor));

        TServer server = new THsHaServer(arg);
  • The client sets the corresponding server connection information and establishes the channel
        TTransport transport = new TFramedTransport(new TSocket("127.0.0.1", 8899), 60);
        TProtocol protocol = new TCompactProtocol(transport);
        PersonService.Client client = new PersonService.Client(protocol);

        transport.open();

Run test

Start the server and client in turn

Server:

Client:

Those who need code come here to get it: demo project address

Guess you like

Origin blog.csdn.net/qq_25805331/article/details/108449500