Thrift:Apache Thrift使用简介

来自WHY42

定义thrift服务

Tirift可以下载预编译的thrift.exe,进行开发时,首先定义接口文件,例如下面这个:

namespace cpp  riguz
namespace java riguz.thrift.def
namespace csharp riguz

//通用响应消息体
struct CommonResponse{
    1:bool success      //调用是否成功
    2:string jsonResult //调用成功,返回响应信息;调用失败,返回错误信息
                        //具体返回的信息根据请求方法不同而不同
                        //eg:{result:'abc'} {result:'接口调用失败!'}
                        //{result:[1,2,3,4]}
}
service RiguzService{
	//PING请求,用来测试服务器是否就绪,当服务器维护时,返回错误信息
	//result: OK
	CommonResponse ping(),

	//登录请求,返回一个token及过期时间
	//result: {token:'5A3486D5-4657-287A-D3C6-2E36D97607D8',expires_in:3600}
	CommonResponse login(1:string user,        //用户名
						 2:string passwd,      //密码
						 3:string userAgent    //登录附言,用来标致客户端信息
						 ),
	//注销请求
	CommonResponse logout(1:string token       //客户端token
						 ),			 
	//跳转交易请求
	//result: {trans:'office', panel:'abc.xml'}返回交易的主界面文件名例如XUI
	//        {trans:'office', panel:'<xml?>...</xml>'}(返回交易的主界面的XML)
	CommonResponse chain(1:string token,       //客户端token
						 2:string name         //交易名称,为空则返回当前交易名称
						 ),
	
	//预留拓展接口,用来处理其他自定义的请求
	//请求及返回均以JSON格式返回
	CommonResponse doJson(1:string request    //JSON格式的请求,本方法作为扩展
						 )
}

生成客户端代码

thrift -r --gen java riguz_service.thrift
thrift -r --gen csharp riguz_service.thrift
thrift -r --gen js:jquery riguz_service.thrift

Java服务端

服务端需要实现生成的Java代码中的接口

public class ServiceHandler
        implements RiguzService.Iface {
...
}
public class SocketServer {

    private static ServiceHandler        handler;
    private static RiguzService.Processor processor;

    /**
     * 服务主函数,启动thrift服务
     * 
     * @param args
     */
    public static void main(String[] args) {
        try {
            handler = new ServiceHandler();
            processor = new RiguzService.Processor(handler);

            Runnable RiguzRunnable = new Runnable() {
                @Override
                public void run() {
                    start(processor, 8080);
                }
            };
            Runnable secure = new Runnable() {
                @Override
                public void run() {
                    secure(processor, 9091);
                }
            };
            new Thread(RiguzRunnable).start();
            new Thread(secure).start();
        }
        catch (Exception ex) {

        }

    }

    public static void start(RiguzService.Processor processor, int port) {
        try {
            // 以Socket方式传输
            TServerTransport serverTransport = new TServerSocket(port);
            TServer server = new TSimpleServer(new TSimpleServer.Args(serverTransport).processor(processor));

            // Use this for a multithreaded server
            // TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor));

            System.out.println("Starting thrift server@" + port + " ...");
            server.serve();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void secure(RiguzService.Processor processor, int port) {
        try {
            /*
             * Ref:
             * 生成证书库(包含私钥)有效期365*50=18250天
             * keytool -genkey -alias thrift -keyalg RSA -keystore E:\thrift\ca\keystore -keysize 1024 -validity 18250
             * 
             * 导出凭证文件
             * keytool -export -alias thrift -keystore E:\thrift\ca\keystore -file E:\thrift\ca\truststore.cer
             * 
             * 把认凭证件导入到truststore文件
             * keytool -import -alias thrift -file E:\thrift\ca\truststore.cer -keystore E:\thrift\ca\truststore
             * 
             * 验证新创建的truststore文件
             * keytool -list -v -keystore E:\thrift\ca\truststore
             */
            TSSLTransportParameters params = new TSSLTransportParameters();
            String res = SocketServer.class.getProtectionDomain().getCodeSource().getLocation().getFile();
            File thisJar = new File(res);
            File resourceFile = new File(thisJar.getParentFile(), "thrift.key");
            params.setKeyStore(resourceFile.getAbsolutePath(), "123456", null, null);
            TServerTransport serverTransport = TSSLTransportFactory.getServerSocket(port, 0, null, params);
            TServer server = new TSimpleServer(new TSimpleServer.Args(serverTransport).processor(processor));
            System.out.println("Starting the secure server...");
            server.serve();
        }

        catch (Exception e) {
            e.printStackTrace();
        }
    }

客户端

Java

C#

private static TTransport transport = new THttpClient(new Uri("http://localhost:8080/riguz/thrift"));
private static TProtocol protocol = new TJSONProtocol(transport);
private static RiguzService.Client thriftClient = new RiguzService.Client(protocol);
public static ServiceEngine GetInstance()
{
    if (engine == null)
    { 
        engine = new ServiceEngine();
        transport.Open();
        CommonResponse pingResult = thriftClient.ping();
        Console.WriteLine("Ping:" + pingResult.Success);
    }
    return engine;
}

public bool Login(string userName, string passwd)
{
    CommonResponse result = thriftClient.login(userName, passwd, "Wpf,1.0," + this.ClientId);
    if (result.Success == true)
    {                
        Dictionary<string, string> dict= JsonConvert.DeserializeObject<Dictionary<string, string>>(result.JsonResult);
        token = dict["token"];
        Console.WriteLine("login success:token=" + token);
        return true;
    }
    return false;   
}

JavaScript

var serverurl = "http://localhost:8080/riguz/webreq";
//按钮
$("input[id^=button]").each(function() {
    var id = $(this).attr("id");
    $(this).click(function() {
        var path = $(this).attr("path");
        var dataMap = {
            "module" : path,
            "action" : "click"
        };
        
        //Stack
        $.post(serverurl, dataMap, function(data) {
            var dataMap1 = {
                "action" : "allstack"
            };
            $.post(serverurl, dataMap1, function(data) {
                //操作List
                jQuery.each(data.jsondata, function(i, item) {
                    var type = item.type;
                    if (type == "INFORMATION") {
                        var des=item.description;
                        var info=des.split("|");
                        alert(info[1]);
                    }
                });
            }, "json");

        }, "json");
    });
});