一、安装
我机器上已经安装好了 thrift-0.9.1
二、示例
编辑demo.thrift文件,内容如下:
struct UserProfile{
1:i32 id,
//注意这里是逗号,而不是分号
2:string name,
3:string blurb
} //这里没有分号
service UserStorage{
void store(1: UserProfile user),
//注意这里是逗号,而不是分号
UserProfile getUser(1: i32 uid)
}
运行如下命令
cloud1:~/test/thrift/demo # thrift -r --gen cpp demo.thrift
cloud1:~/test/thrift/demo # ls
demo.thrift gen-cpp
可以看到在当前目录下产生了一个gen-cpp的目录,该目录下即以上命令产生的文件:
UserStorage.cpp
UserStorage.h
UserStorage_server.skeleton.cpp
demo_constants.cpp
demo_constants.h
demo_types.cpp
demo_types.h
UserStorage.h
UserStorage_server.skeleton.cpp
demo_constants.cpp
demo_constants.h
demo_types.cpp
demo_types.h
注意:在以上文件中,只有
UserStorage_server.skeleton.cpp
是跟业务相关的,是可以修改的,其余文件都是框架相关的。
UserStorage_server_skeleton.cpp文件内容如下:
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.
// You should copy it to another filename to avoid overwriting it.
#include "UserStorage.h"
#include <protocol/TBinaryProtocol.h>
#include <server/TSimpleServer.h>
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>
#include <map>
#include <protocol/TBinaryProtocol.h>
#include <server/TSimpleServer.h>
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>
#include <map>
using namespace std;
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using boost::shared_ptr;
class UserStorageHandler : virtual public UserStorageIf {
public:
UserStorageHandler() {
// Your initialization goes here
}
public:
UserStorageHandler() {
// Your initialization goes here
}
void store(const UserProfile& user) {
// Your implementation goes here
printf("store\n");
}
// Your implementation goes here
printf("store\n");
}
void getUser(UserProfile& _return, const int32_t uid) {
// Your implementation goes here
printf("getUser\n");
}
};
// Your implementation goes here
printf("getUser\n");
}
};
int main(int argc, char **argv) {
int port = 9090;
shared_ptr<UserStorageHandler> handler(new UserStorageHandler());
shared_ptr<TProcessor> processor(new UserStorageProcessor(handler));
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
int port = 9090;
shared_ptr<UserStorageHandler> handler(new UserStorageHandler());
shared_ptr<TProcessor> processor(new UserStorageProcessor(handler));
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
server.serve();
return 0;
}
server.serve();
return 0;
}
可以看到,该文件只是一个框架,用户可以根据需要扩展该文件,笔者修改如下(蓝色部分为添加的代码,同时将文件改名为UserStorage_server.cpp):
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.
#include "UserStorage.h"
#include <protocol/TBinaryProtocol.h>
#include <server/TSimpleServer.h>
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>
#include <map>
using namespace std;
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using boost::shared_ptr;
class UserStorageHandler : virtual public UserStorageIf {
public:
UserStorageHandler() {
// Your initialization goes here
}
void store(const UserProfile& user) {
// Your implementation goes here
log[user.id] = user;
//实际的保存操作
printf("store\n");
}
void getUser(UserProfile& _return, const int32_t uid) {
// Your implementation goes here
_return = log[uid];
//实际获取操作,注意:在实际生产中,这里还需要异常处理
printf("getUser\n");
}
//增加成员变量,用户保存用户数据,为了简单起见,这里只将数据保存在内存,当然可以可以保存在数据库、文件等等,主要注意,如果保存在其他介质的话
//在初始化的时候记得加载进内存或者打开访问句柄
protected:
map<int32_t, UserProfile> log;
};
int main(int argc, char **argv) {
int port = 9090;
shared_ptr<UserStorageHandler> handler(new UserStorageHandler());
shared_ptr<TProcessor> processor(new UserStorageProcessor(handler));
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
server.serve();
return 0;
}
可以看到以上程序还包括一个简单的服务端代码,问了进行测试,笔者从thrift/tutorial/cpp/目录下copy了一个客户端代码和Makefile
修改如下:
CppClient.cpp (蓝色部分为客户化代码)
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <protocol/TBinaryProtocol.h>
#include <transport/TSocket.h>
#include <transport/TTransportUtils.h>
#include "UserStorage.h"
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace boost;
int main(int argc, char** argv) {
shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
shared_ptr<TTransport> transport(new TBufferedTransport(socket));
shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
UserStorageClient client(protocol);
try {
transport->open();
UserProfile user;
user.id = 1;
user.name = "liqb";
user.blurb = "aaaaaa";
client.store(user);
UserProfile user2;
client.getUser(user2, 1);
printf("user.id = %d user.name = %s user.blurb = %s\n", user2.id, user2.name.c_str(), user2.blurb.c_str());
transport->close();
} catch (TException &tx) {
printf("ERROR: %s\n", tx.what());
}
}
Makefile
BOOST_DIR = /usr/local/boost/include/boost-1_33_1/
THRIFT_DIR = /usr/local/include/thrift
LIB_DIR = /usr/local/lib
GEN_SRC = UserStorage.cpp demo_constants.cpp demo_types.cpp
default: server client
server: UserStorage_server.cpp
g++ -o CppServer -I${THRIFT_DIR} -I${BOOST_DIR} -I../gen-cpp -L${LIB_DIR} -lthrift
UserStorage_server.cpp ${GEN_SRC}
client: CppClient.cpp
g++ -o CppClient -I${THRIFT_DIR} -I${BOOST_DIR} -I../gen-cpp -L${LIB_DIR} -lthrift CppClient.cpp ${GEN_SRC}
clean:
$(RM) -r CppClient CppServer
编译之后产生CppServer 和CppClient 两个可执行程序,分别运行CppServer 和CppClient,即可以看到测试结果。
先运行服务器:
cloud1:~/test/thrift/demo/gen-cpp # ./CppServer
再执行客户端:
cloud1:~/test/thrift/demo/gen-cpp # ./CppClient
user.id = 1 user.name = liqb user.blurb = aaaaaa
cloud1:~/test/thrift/demo/gen-cpp #
服务器上显示:
cloud1:~/test/thrift/demo/gen-cpp # ./CppServer
store
getUser
Python 版客户端:
thrift/tutorial/
下拷:
PythonClient.py 略做修改:
cloud1:~/test/thrift/demo # vi PythonClient.py
1 #!/usr/bin/env python
2
3 #
4 # Licensed to the Apache Software Foundation (ASF) under one
5 # or more contributor license agreements. See the NOTICE file
#!/usr/bin/env python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
import sys, glob
sys.path.append('gen-py')
#sys.path.insert(0, glob.glob('../../lib/py/build/lib.*')[0])
from demo import UserStorage
from demo.ttypes import *
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
try:
# Make socket
transport = TSocket.TSocket('localhost', 9090)
# Buffering is critical. Raw sockets are very slow
transport = TTransport.TBufferedTransport(transport)
# Wrap in a protocol
protocol = TBinaryProtocol.TBinaryProtocol(transport)
# Create a client to use the protocol encoder
client = UserStorage.Client(protocol)
# Connect!
transport.open()
try:
u1 = UserProfile()
u1.id=456
u1.name='nick'
u1.blurb='test bbb'
client.store(u1)
print 'store done!'
except InvalidOperation, io:
print 'InvalidOperation: %r' % io
u = client.getUser(123)
print 'id=%s name=%s blurb=%s' %(u.id,u.name,u.blurb)
# Close!
transport.close()
except Thrift.TException, tx:
print '%s' % (tx.message)
cloud1:~/test/thrift/demo # python PythonClient.py
store done!
id=123 name=jason blurb=test aaa
cloud1:~/test/thrift/demo #
Java 版客户端:
thrift-0.9.1/tutorial/java/src/
下拷:
JavaClient.java
做修改:
重命名为:
UserProfileClient.java
cloud1:~/test/thrift/demo # vi UserProfileClient.java
import org.apache.thrift.TException;
import org.apache.thrift.transport.TSSLTransportFactory;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
public class UserProfileClient {
public static void main(String [] args) {
/*if (args.length != 1) {
System.out.println("Please enter 'simple' or 'secure'");
System.exit(0);
} */
try {
TTransport transport;
//if (args[0].contains("simple")) {
transport = new TSocket("localhost", 9090);
transport.open();
//}
//else {
/*
* Similar to the server, you can use the parameters to setup client parameters or
* use the default settings. On the client side, you will need a TrustStore which
* contains the trusted certificate along with the public key.
* For this example it's a self-signed cert.
*/
//TSSLTransportParameters params = new TSSLTransportParameters();
//params.setTrustStore("../../lib/java/test/.truststore", "thrift", "SunX509", "JKS");
/*
* Get a client transport instead of a server transport. The connection is opened on
* invocation of the factory method, no need to specifically call open()
*/
//transport = TSSLTransportFactory.getClientSocket("localhost", 9091, 0, params);
//}
TProtocol protocol = new TBinaryProtocol(transport);
UserStorage.Client client = new UserStorage.Client(protocol);
int uid=123;
System.out.println(client.getUser(uid));
UserProfile u = new UserProfile();
u.id=999;
u.name="kaining";
u.blurb="test 999";
client.store(u);
transport.close();
} catch (TException x) {
x.printStackTrace();
}
}
}
cloud1:~/test/thrift/demo # cat compile.sh
#!/bin/sh
export CLASS_PATH_JAVA=""
for i in /usr/local/lib/*.jar
do
if [ "x${CLASS_PATH_JAVA}" == "x" ]
then
export CLASS_PATH_JAVA=$i
continue
fi
export CLASS_PATH_JAVA=${CLASS_PATH_JAVA}:$i
#echo $i
done
echo "$CLASS_PATH_JAVA"
javac -classpath $CLASS_PATH_JAVA UserProfileClient.java ./gen-java/*.java
cloud1:~/test/thrift/demo #
cloud1:~/test/thrift/demo # cat run.sh
#!/bin/sh
export CLASS_PATH_JAVA=""
for i in /usr/local/lib/*.jar
do
if [ "x${CLASS_PATH_JAVA}" == "x" ]
then
export CLASS_PATH_JAVA=.:$i
continue
fi
export CLASS_PATH_JAVA=${CLASS_PATH_JAVA}:$i
done
#echo "$CLASS_PATH_JAVA"
java -cp $CLASS_PATH_JAVA:./gen-java UserProfileClient
cloud1:~/test/thrift/demo #
编译,执行compile.sh
cloud1:~/test/thrift/demo # ./compile.sh
/usr/local/lib/commons-codec-1.6.jar:/usr/local/lib/commons-lang3-3.1.jar:/usr/local/lib/commons-logging-1.1.1.jar:/usr/local/lib/httpclient-4.2.5.jar:/usr/local/lib/httpcore-4.2.4.jar:/usr/local/lib/junit-4.4.jar:/usr/local/lib/libthrift-0.9.1-javadoc.jar:/usr/local/lib/libthrift-0.9.1.jar:/usr/local/lib/log4j-1.2.14.jar:/usr/local/lib/servlet-api-2.5.jar:/usr/local/lib/slf4j-api-1.5.8.jar:/usr/local/lib/slf4j-log4j12-1.5.8.jar
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
cloud1:~/test/thrift/demo #
运行,执行run.sh
cloud1:~/test/thrift/demo # ./run.sh
UserProfile(id:123, name:jason, blurb:test aaa)
cloud1:~/test/thrift/demo #
参考:
http://jinghong.iteye.com/blog/1222713
网址:http://blog.163.com/zhangjie_0303/blog/static/9908270620140311022650/