Protocol Buffers学习小记-基于servlet的http RPC实现

Protocol Buffers没有提供RPC的具体实现。不过,你可以在 http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns 找到一些第三方开发的RPC实现。

本文尝试了http RPC的实现,运行在Tomcat的servlet中。需要注意的是,这只是个测试,实现是不完整的,并且代码很不好看,很不好复用。

主要参考: http://www.eishay.com/2008/11/protobuf-vs-spring-rpc.html

1、定义协议格式

user.proto

package mytest;
option java_package = “mytest.protobuf.gen”;
option java_outer_classname = “UserProtos”;
message User {
required string name = 1;
required int32 userId = 2;
required string loginName = 3;
required string password = 4;
}
message UserId {
required int32 userId = 1;
}
service UserService {
rpc getUser (UserId) returns (User);
}

2、生成java代码

protoc –java_out=gen user.proto

3、服务端代码

3.1 服务的实现

package myserver;
import com.google.protobuf.RpcCallback;
import com.google.protobuf.RpcController;
import mytest.protobuf.gen.UserProtos.User;
import mytest.protobuf.gen.UserProtos.UserId;
import mytest.protobuf.gen.UserProtos.UserService;
public class UserServiceHandler extends UserService {
@Override
public void getUser(RpcController controller, UserId request,
RpcCallback done) {

User.Builder user = User.newBuilder();
user.setUserId(100);
user.setLoginName(“login1″);
user.setPassword(“pwd1″);
user.setName(“user1″);

done.run(user.build());
}
}

3.2 servlet

package servlet;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import myserver.UserServiceHandler;
import mytest.protobuf.gen.UserProtos.User;
import mytest.protobuf.gen.UserProtos.UserId;
import com.google.protobuf.RpcCallback;
public class UserServiceServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private UserServiceHandler _handler = new UserServiceHandler();
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter w = response.getWriter();
w.write(“This is a protocal buffer service!”);
w.close();
}
@Override
protected void doPost(HttpServletRequest request,
final HttpServletResponse response) throws ServletException, IOException {

RpcCallback done = new RpcCallback() {
DataOutputStream dos = new DataOutputStream(response.getOutputStream());
public void run(User user) {
try {
byte[] array = user.toByteArray();
dos.writeInt(array.length);
dos.write(array);
dos.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
};
DataInputStream dis = new DataInputStream(request.getInputStream());
byte[] array = new byte[dis.readInt()];
dis.readFully(array);

UserId req = UserId.parseFrom(array);
_handler.getUser(null, req, done);
}
}

3.3 web.xml


xmlns=”http://java.sun.com/xml/ns/j2ee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd”>
protobuf

UserServiceServlet
servlet.UserServiceServlet
1


UserServiceServlet
/UserService


index.html
index.htm
index.jsp

4、客户端代码

package myclient;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import mytest.protobuf.gen.UserProtos.User;
import mytest.protobuf.gen.UserProtos.UserId;
import mytest.protobuf.gen.UserProtos.UserService;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import com.google.protobuf.Message;
import com.google.protobuf.RpcCallback;
import com.google.protobuf.RpcChannel;
import com.google.protobuf.RpcController;
import com.google.protobuf.Descriptors.MethodDescriptor;
public class ClientByHttp {
public static void main(String[] args) {
final HttpClient client = new HttpClient();
RpcChannel channel = new RpcChannel()
{
public void callMethod (MethodDescriptor method,
RpcController controller,
Message request,
Message responsePrototype,
RpcCallback done)
{
try
{
System.out.println(“calling”);
PostMethod post = new PostMethod(“http://localhost:8080/UserService”);

ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
//dos.writeInt(method.getIndex());
byte[] array = request.toByteArray();
dos.writeInt(array.length);
dos.write(array);
dos.flush();
byte[] toSend = baos.toByteArray();

System.out.println(“sending size = ” + toSend.length);
post.setRequestEntity(new ByteArrayRequestEntity(toSend ));

client.executeMethod(post);
DataInputStream dis = new DataInputStream(post.getResponseBodyAsStream());
int size = dis.readInt();
array = new byte[size];
dis.readFully(array);
done.run(responsePrototype.newBuilderForType().mergeFrom(array).build());

System.out.println(“done”);
post.releaseConnection();
}
catch (IOException e)
{
e.printStackTrace();
}
}
};

UserService service = UserService.newStub(channel);

UserId.Builder userId = UserId.newBuilder();
userId.setUserId(1);

RpcCallback done = new RpcCallback()
{
public void run (User user)
{
System.out.println(“name=” + user.getName());
System.out.println(“loginname=” + user.getLoginName());
System.out.println(“password=” + user.getPassword());
}
};

service.getUser(null, userId.build(), done);

}
}



发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

(Spamcheck Enabled)