使用thrift实现java调用c++实现的简单webservice
首先是安装thrift,这花费了不少时间。
关于安装步骤,apache的官方说明已经比较详细了:
http://wiki.apache.org/thrift/ThriftRequirements
http://wiki.apache.org/thrift/ThriftInstallation
看起来依赖的库很多,但其实关键的也就是
boost
ant
ivy
slf4j
byacc
(安装的具体依赖关系需要继续验证)
1.首先需要定义一个service,也就是新建一个.thrift文件。
在任意位置创建一个文件夹作为项目目录,下面到操作如无说明均是在此目录下进行。
让我们来创建一个.thrift文件吧:
文件名:jobsm.thrift
文件内容:
struct JobInfo {
1: i32 jobid = 0,
2: string user,
}
service JobScheduler{
void ping(),
bool addJob(1:JobInfo job),
JobInfo getJob()
}
2.使用c++构建server端:
通过thrift命令生成cpp代码:
$ thrift -r --gen cpp jobsm.thrift
成功后我们会见到生成的gen-cpp文件夹,进入gen-cpp/,可以看到很多自动生成的c++源文件,创建我们自己的server代码:
文件名:
JobScheduler_server.cpp
文件内容:
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.
#include <iostream>
#include <queue>
#include "JobScheduler.h"
#include <protocol/TBinaryProtocol.h>
#include <server/TSimpleServer.h>
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using boost::shared_ptr;
class JobSchedulerHandler : virtual public JobSchedulerIf {
private:
std::queue<JobInfo> container;
public:
JobSchedulerHandler() : container() {
// Your initialization goes here
}
void ping() {
// Your implementation goes here
printf("run ping/n");
}
bool addJob(const JobInfo& job) {
// Your implementation goes here
std::cout<<"add job's id is "<<job.jobid<<std::endl;
std::cout<<"add job's user is "<<job.user<<std::endl;
container.push(job);
printf("run addJob/n");
}
void getJob(JobInfo& _return) {
// Your implementation goes here
_return = container.front();
container.pop();
std::cout<<"pop job's id is "<<_return.jobid<<std::endl;
std::cout<<"pop job's user is "<<_return.user<<std::endl;
printf("run getJob/n");
}
};
int main(int argc, char **argv) {
int port = 9090;
shared_ptr<JobSchedulerHandler> handler(new JobSchedulerHandler());
shared_ptr<TProcessor> processor(new JobSchedulerProcessor(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 -r --gen java jobsm.thrift
成功后我们会见到生成的gen-java文件夹,进入gen-java/,可以看到很多自动生成的java文件,创建我们自己的client代码:
文件名:JavaClient.java
文件内容:
import org.apache.thrift.TException;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransportException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.ArrayList;
public class JavaClient {
public static void main(String [] args) {
try{
TTransport transport = new TSocket("localhost", 9090);
TProtocol protocol = new TBinaryProtocol(transport);
JobScheduler.Client client = new JobScheduler.Client(protocol);
transport.open();
for(int i=0; i<args.length; i++) {
System.out.println(args[i]);
}
client.ping();
System.out.println("ping()");
JobInfo job = new JobInfo();
if(args.length > 0 && args[0] != null)
job.setJobid(Integer.parseInt(args[0]));
else
job.setJobid(0);
if(args.length >1 && args[1] != null)
job.setUser(args[1]);
else
job.setUser("default");
client.addJob(job);
System.out.println("addJob");
JobInfo job2 = client.getJob();
System.out.println("getJob. JobId is "+ job2.getJobid() + ". JobUser is " + job2.getUser());
} catch (TException x) {
x.printStackTrace();
}
}
}
让我们使用ant来编译这个java工程吧,在gen-java目录下新建一个build.xml文件
文件内容:
<project name="jobscheduler" default="jobscheduler" basedir=".">
<description>JobScheduler</description>
<property name="src" location="./" />
<property name="gen" location="./" />
<property name="build" location="build" />
<path id="libs.classpath">
<pathelement path="/usr/thrift-0.5.0/lib/java/libthrift.jar" />
<fileset dir="/usr/thrift-0.5.0/lib/java/build/ivy/lib">
<include name="*.jar" />
</fileset>
</path>
<path id="build.classpath">
<path refid="libs.classpath" />
<pathelement path="${gen}" />
</path>
<target name="init">
<tstamp />
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${gen}" destdir="${build}" classpathref="libs.classpath" />
<javac srcdir="${src}" destdir="${build}" classpathref="build.classpath" />
</target>
<target name="jobscheduler" depends="compile">
<jar jarfile="jobscheduler.jar" basedir="${build}"/>
</target>
<target name="clean">
<delete dir="${build}" />
<delete file="jobscheduler.jar" />
</target>
</project>
好了,执行 $ ant
成功后就生成了build目录和一个新的jar包,再写一个shell来运行客户端吧。
文件名:JavaClient
文件内容:
#!/bin/sh
LIB_DIR=/usr/thrift-0.5.0/lib/java/
IVY_DIR=$LIB_DIR/build/ivy/lib/
java -cp $IVY_DIR/*:$LIB_DIR/libthrift.jar:jobscheduler.jar JavaClient $1 $2
运行客户端:
$ ./JavaClient 123 userABC
可以看到server端和client端都有对应的显示。
说明一个简单的webservice成功完成!