Protocol Buffers学习小记-基于servlet的http RPC实现
2016-08-22 17:08
429 查看
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
[c-sharp] view
plain copy
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 服务的实现
[java] view
plain copy
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<User> 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
[java] view
plain copy
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<User> done = new RpcCallback<User>() {
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
[xhtml] view
plain copy
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
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">
<display-name>protobuf</display-name>
<servlet>
<servlet-name>UserServiceServlet</servlet-name>
<servlet-class>servlet.UserServiceServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>UserServiceServlet</servlet-name>
<url-pattern>/UserService</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
4、客户端代码
[java] view
plain copy
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<Message> 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<mce:script type="text/javascript" src="http://hi.images.csdn.net/js/blog/tiny_mce/themes/advanced/langs/zh.js" mce_src="http://hi.images.csdn.net/js/blog/tiny_mce/themes/advanced/langs/zh.js"></mce:script><mce:script type="text/javascript" src="http://hi.images.csdn.net/js/blog/tiny_mce/plugins/syntaxhl/langs/zh.js" mce_src="http://hi.images.csdn.net/js/blog/tiny_mce/plugins/syntaxhl/langs/zh.js"></mce:script>.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<User> done = new RpcCallback<User>()
{
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);
}
}
本文尝试了http RPC的实现,运行在Tomcat的servlet中。需要注意的是,这只是个测试,实现是不完整的,并且代码很不好看,很不好复用。
主要参考: http://www.eishay.com/2008/11/protobuf-vs-spring-rpc.html
1、定义协议格式
user.proto
[c-sharp] view
plain copy
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 服务的实现
[java] view
plain copy
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<User> 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
[java] view
plain copy
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<User> done = new RpcCallback<User>() {
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
[xhtml] view
plain copy
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
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">
<display-name>protobuf</display-name>
<servlet>
<servlet-name>UserServiceServlet</servlet-name>
<servlet-class>servlet.UserServiceServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>UserServiceServlet</servlet-name>
<url-pattern>/UserService</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
4、客户端代码
[java] view
plain copy
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<Message> 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<mce:script type="text/javascript" src="http://hi.images.csdn.net/js/blog/tiny_mce/themes/advanced/langs/zh.js" mce_src="http://hi.images.csdn.net/js/blog/tiny_mce/themes/advanced/langs/zh.js"></mce:script><mce:script type="text/javascript" src="http://hi.images.csdn.net/js/blog/tiny_mce/plugins/syntaxhl/langs/zh.js" mce_src="http://hi.images.csdn.net/js/blog/tiny_mce/plugins/syntaxhl/langs/zh.js"></mce:script>.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<User> done = new RpcCallback<User>()
{
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);
}
}
相关文章推荐
- Protocol Buffers学习小记-基于servlet的http RPC实现
- Java学习3:基于Intellij IDEA实现一个简单Servlet
- RPC的实现原理,是基于HTTP协议的还是tcp协议的?
- 基于TCP和HTTP协议的RPC简单实现
- 分布式学习笔记1通过Java自己实现简单的HTTP RPC框架
- 基于TCP和HTTP协议的RPC简单实现
- 利用SpringMVC实现基于Http和Json的轻量级RPC框架
- 基于TCP和HTTP协议的RPC简单实现
- Servlet与Jsp学习笔记--2、POST HTTP Request
- 学习笔记---使用prototype.js扩展struts标签实现xmlhttprequest
- HttpServletRequest接口中的getMethod()方法的实现
- HTTP协议学习 HTTP客户/服务器模式中信息交换的实现:
- JAVA学习提高之---- FileUpload组件实现多文件上传(JSP+SERVLET)实现
- MVC学习之实现HTTP-GET的Delete Action方法
- GeoServer学习手记(四):Servlet及HTTP派发过程之一
- Servlet 学习笔记4:HTTP应答状态
- Servlet 学习笔记5:HTTP应答头
- 转:几种基于HTTP协议的RPC性能比较,以及ICE接口性能测试比较
- 传智播客Servlet学习,Servlet执行时一般要实现的几个方法
- ServletContextListener HttpSessionListener 接口的实现与应用