文章关键字 ‘google protobuf’

基于apache mina 2.0.0 M4和google Protocol Buffers 2.0.3的java RPC实例(3.定义RPC请求和应答)

2009年01月13日,星期二

接上一篇: http://618119.com/archives/2009/01/13/127.html

google Protocol Buffers RPC的应答包:
[code]
package com.lizongbo.protobufrpc;

import .io.*;
import java.nio.ByteBuffer;

public class ProtobufRPCRequest {
private String serviceName;
private String methodName;
private byte[] requestMessage;
private int reqByteLen;
public String getServiceName() {
return serviceName;
}

public String getMethodName() {
return methodName;
}

public byte[] getRequestMessage() {

return requestMessage;
}

public int getReqByteLen() {
return reqByteLen;
}

public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}

public void setMethodName(String methodName) {
this.methodName = methodName;
}

public void setRequestMessage(byte[] requestMessage) {

this.requestMessage = requestMessage;
}

public void setReqByteLen(int reqByteLen) {
this.reqByteLen = reqByteLen;
}

public void readFrom(byte[] b, int offset) {
System.out.println("readFrom:" + new String(b));
java.io.ByteArrayInputStream bai = new ByteArrayInputStream(b, offset,
b.length - offset);
DataInputStream buf = new DataInputStream(bai);

try {
// buf.getInt();
int serviceNameLen = buf.readInt();
System.out.println("serviceNameLen==" + serviceNameLen);
byte bt[] = new byte[serviceNameLen];
buf.read(bt);
serviceName = new String(bt);
System.out.println("serviceName==" + serviceName);
int methodNameLen = buf.readInt();
System.out.println("methodNameLen==" + methodNameLen);
bt = new byte[methodNameLen];
buf.read(bt);
methodName = new String(bt);
int requestLen = buf.readInt();
System.out.println("requestLen==" + requestLen);
requestMessage = new byte[requestLen];
buf.read(requestMessage);
} catch (Exception ex) {
ex.printStackTrace();
}
}

public byte[] toByteArray() {
java.io.ByteArrayOutputStream bao = new ByteArrayOutputStream();
DataOutputStream out = new
DataOutputStream(bao);

try {
byte[] serviceNameb = serviceName.getBytes();
System.out.println("serviceNameLen==" + serviceNameb.length);
out.writeInt(serviceNameb.length);
out.write(serviceNameb);
byte[] methodNameb = methodName.getBytes();
System.out.println("methodNameLen==" + methodNameb.length);
out.writeInt(methodNameb.length);
out.write(methodNameb);
System.out.println("requestMessageLen==" + requestMessage.length);
out.writeInt(requestMessage.length);
out.write(requestMessage);
byte[] reqByte = bao.toByteArray();
reqByteLen = reqByte.length;
bao = new ByteArrayOutputStream();
out = new DataOutputStream(bao);
System.out.println("reqByteLen==" + (reqByte.length + 4));
out.writeInt(reqByte.length + 4);
out.write(reqByte);
} catch (IOException ex) {
ex.printStackTrace();
}
return bao.toByteArray();
}

}

[/code]

google Protocol Buffers RPC的应答包:
[code]
package com.lizongbo.protobufrpc;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.io.DataInputStream;
import java.io.ByteArrayInputStream;

public class ProtobufRPCResponse {
private int resByteLen;
private byte[] responseMessage;
public int getResByteLen() {
return resByteLen;
}

public byte[] getResponseMessage() {
return responseMessage;
}

public void setResByteLen(int resByteLen) {
this.resByteLen = resByteLen;
}

public void setResponseMessage(byte[] responseMessage) {
this.responseMessage = responseMessage;
}

public void readFrom(byte[] b, int offset) {

try {//此处不够完善
java.io.ByteArrayInputStream bai = new ByteArrayInputStream(b, offset,
b.length - offset);
DataInputStream buf = new DataInputStream(bai);
resByteLen = buf.readInt();
responseMessage = new byte[resByteLen - 4];
buf.read(responseMessage);
} catch (Exception ex) {
ex.printStackTrace();
}
}

public byte[] toByteArray() {
java.io.ByteArrayOutputStream bao = new ByteArrayOutputStream();
DataOutputStream out = new
DataOutputStream(bao);

try {
out.writeInt(responseMessage.length + 4);
out.write(responseMessage);
} catch (IOException ex) {
ex.printStackTrace();
}
return bao.toByteArray();
}

}

[/code]

Tags: , , , ,

基于apache mina 2.0.0 M4和google Protocol Buffers 2.0.3的java RPC实例(2.service端)

2009年01月13日,星期二

接上一篇:http://618119.com/archives/2009/01/10/124.html
1.接口功能实现:

[code]
package com.lizongbo.mobileqq;

import com.lizongbo.mobileqq.QQUserInfoProtos.*;
import com.google.protobuf.RpcController;
import com.google.protobuf.RpcCallback;

public class UserInfoServiceImpl extends UserInfoService {
public void getUserInfo(RpcController controller,
GetUserInfoRequest request,
RpcCallback < com.lizongbo.mobileqq.
QQUserInfoProtos.GetUserInfoResponse > done) {

GetUserInfoResponse.Builder builder = GetUserInfoResponse.
newBuilder();
builder.setQqNo(request.getQqNo());

if (request.getQqNo() == 123456) {
builder.setResult(0);
QQUser.Builder qb = QQUser.newBuilder();
qb.setQqNo(request.getQqNo());
qb.setNickNmae("lizongbo");
qb.setPostCode("618100");
qb.setSignName("google Protocol Buffers 远程调用");
qb.setAddress("google");
builder.setUserInfo(qb);
} else {
builder.setResult( -1);
}
done.run(builder.build());
}

public void updateUserInfo(RpcController controller,
UpdateUserInfoRequest request,
RpcCallback < com.lizongbo.mobileqq.
QQUserInfoProtos.UpdateUserInfoResponse > done) {
UpdateUserInfoResponse.Builder builder = UpdateUserInfoResponse.
newBuilder();
builder.setQqNo(request.getQqNo());

if (request.getQqNo() == 123456) {
builder.setResult(0);
builder.setMessage("成功!");
} else {
builder.setResult( -1);
builder.setMessage("失败!");
}
done.run(builder.build());
}

}

[/code]

2.RpcController接口的实现:

[code]
package com.lizongbo.mobileqq;

import com.google.protobuf.RpcController;
import com.google.protobuf.RpcCallback;

public class UserInfoServiceRpcController implements RpcController {

public String errorText() {
return "no error";
}

public boolean failed() {
return false;
}

public boolean isCanceled() {
return false;
}

public void notifyOnCancel(RpcCallback callback) {
System.out.println("run RpcCallback by notifyOnCancel");
}

public void reset() {
System.out.println("do nothing");
}

public void setFailed(String reason) {
System.out.println("setFailed " + reason);
}

public void startCancel() {
System.out.println("run startCancel");
}
}

[/code]

Tags: , , , ,

基于apache mina 2.0.0 M4和google Protocol Buffers 2.0.3的java RPC实例(1.准备工作)

2009年01月10日,星期六

基于apache mina 2.0.0 M4和google Protocol Buffers 2.0.3的java RPC实例(1.准备工作)

1.最新的google Protocol Buffers 下载地址为:

http://protobuf.googlecode.com/files/protobuf-2.0.3.zip
http://protobuf.googlecode.com/files/protoc-2.0.3-win32.zip
来源:http://code.google.com/p/protobuf/downloads/list

2. 2.0.0-M4下载地址为:
http://apache.freelamp.com/mina/2.0.0-M4/mina-2.0.0-M4.zip
(或:http://www.eu.apache.org/dist/mina/2.0.0-M4/mina-2.0.0-M4.zip)

3.protobuf-rpc的代码:
通过svn取protobuf-rpc的代码到本地。源代码地址在:
http://protobuf-rpc.googlecode.com/svn/trunk/
来源:
http://code.google.com/p/protobuf-rpc/
不过这个例子太简单,并且没有java版本的。

4.建立目录D://protoc/javasrc,
运行命令:
protoc.exe  -I=”D:/Java/protoc/protobuf-2.0.3/src/google/protobuf” –java_out=”D:/Java/protoc/javasrc” D:/Java/protoc/protobuf-2.0.3/src/google/protobuf/descriptor.proto

很奇特,protoc.exe -–java_out=./ D:\Java\protoc\protobuf-2.0.0beta\src\google\protobuf\descriptor.proto 运行出错了。(参考:http://618119.com/archives/2008/07/08/100.html

5.复制D:\Java\protoc\javasrc\com\google\protobuf下的DescriptorProtos.java到
D:\Java\protoc\protobuf-2.0.3\java\src\main\java\com\google\protobuf。
建立java工程到E:\mywork\protobuf,将D:\Java\protoc\protobuf-2.0.3\java\src\main\java\下的文件复制到E:\mywork\protobuf\src。

(以下步骤其实是我绕的弯路)
6.E:\mywork\protobuf\src>svn checkout http://protobuf-rpc.googlecode.com/svn/trunk
/ protobuf--read-only
A    protobuf-rpc-read-only\protoc.sh
A    protobuf-rpc-read-only\protocol
A    protobuf-rpc-read-only\protocol\protobufrpc.proto
A    protobuf-rpc-read-only\LICENSE
A    protobuf-rpc-read-only\protobufrpc
A    protobuf-rpc-read-only\protobufrpc\common.py
A    protobuf-rpc-read-only\protobufrpc\tx.py
A    protobuf-rpc-read-only\protobufrpc\__init__.py
A    protobuf-rpc-read-only\setup.py
A    protobuf-rpc-read-only\setup.sh
A    protobuf-rpc-read-only\examples
A    protobuf-rpc-read-only\examples\test.proto
A    protobuf-rpc-read-only\examples\txproxy.py
A    protobuf-rpc-read-only\examples\txserver.py
取出版本 13。

7.运行命令:
D:\Java\protoc>protoc.exe  -I=”E:\mywork\protobuf\src\protobuf-rpc-read-only\protocol” –java_out=”D:/Java/protoc/javasrc” E:\mywork\protobuf\src\protobuf-rpc-read-only\protocol\protobufrpc.proto

8.将D:\Java\protoc\javasrc下的pbrpc目录复制到E:\mywork\protobuf\src

9将E:\mywork\protobuf\src\protobuf-rpc-read-only\examples下的test.proto改名为:TestRpc.proto
内容改为:

package test;

message EchoRequest {
required string text = 1;
}

message EchoResponse {
required string text = 1;
}

message PingRequest {
required int32 ping = 1;
}

message PingResponse {
required int32 pingRs = 1;
}

message MathBinaryOperationRequest {
required float first = 1;
required float second = 2;
}

message MathResponse {
required float result = 1;
}

service Test {
rpc Ping( PingRequest ) returns( PingResponse );
rpc Echo( EchoRequest ) returns( EchoResponse );
}

service Math {
rpc Add( MathBinaryOperationRequest ) returns( MathResponse );
rpc Multiply( MathBinaryOperationRequest ) returns( MathResponse );
}

10.再运行:
D:\Java\protoc>protoc.exe  -I=”E:\mywork\protobuf\src\protobuf-rpc-read-only\examples” –java_out=”D:/Java/protoc/javasrc” E:\mywork\protobuf\src\protobuf-rpc-read-only\examples\TestRpc.proto

否则因为包名和类名的冲突,会出现如下错误信息:
D:\Java\protoc>protoc.exe  -I=”E:\mywork\protobuf\src\protobuf-rpc-read-only\examples” –java_out=”D:/Java/protoc/javasrc” E:\mywork\protobuf\src\protobuf-rpc-read-only\examples\test.proto
–java_out: test.proto: Cannot generate Java output because the file’s outer class name, “Test”, matches the name of one of the types declared inside it.  Please either rename the type or use the java_outer_classname option to specify a different outer class name for the .proto file.

然后就可以编写这个例子相关接口的实现类了。

下面开始实际例子:.定义service的proto文件

先假设需求为实现一个用户查看并修改自己的个人信息的功能接口。

在D:\Java\protoc\javasrc建立qquserinfo.proto

内容如下:
[code]
package lizongbo.protobuf;
option java_package = "com.lizongbo.mobileqq";
option java_outer_classname = "QQUserInfoProtos";

option optimize_for = CODE_SIZE;// 也可以设置成 SPEED;

//用户信息定义
message QQUser {
required int32 qqNo = 1 [default = 9999];
required string nickNmae = 2 [default = "mobileq"];
required string signName = 3 [default = "手机QQ"];
required string postCode = 4 [default = "618119"];
required string address = 5 [default = "618119.com"];
}

//获取个人信息的请求
message GetUserInfoRequest {
required int32 qqNo = 1;
}
//获取个人信息的应答结果
message GetUserInfoResponse {
required int32 qqNo = 1;
required int32 result = 2;
optional QQUser userInfo = 3;
}

//更新个人信息的请求
message UpdateUserInfoRequest {
required int32 qqNo = 1;
required QQUser userInfo = 2;
}
//更新个人信息的应答结果
message UpdateUserInfoResponse {
required int32 qqNo = 1;
required int32 result = 2;
optional string message = 3;
}

//个人信息操作的service接口
service UserInfoService {

//获取个人信息
rpc getUserInfo( GetUserInfoRequest  ) returns( GetUserInfoResponse );
//与hessian不同,service里直接限制了不能有同名重载方法。
// 比如这样与下面的方法冲突 rpc updateUserInfo( GetUserInfoRequest ) returns( GetUserInfoResponse );
//出错信息为:qquserinfo.proto:45:9: "updateUserInfo" is already defined in "lizongbo.protobuf.UserInfoService".

//更新个人信息
rpc updateUserInfo( UpdateUserInfoRequest ) returns( UpdateUserInfoResponse );

}

//获取个人信息的请求
message QueryOplogRequest {
required int32 adminId = 1;//管理员id
required int32 qqNo = 2;
}
//获取个人信息的应答结果
message QueryOplogResponse {
//用户操作日志
message Oplog {
required int32 qqNo = 1;
required string opName = 2 [default = "get"];
required string opContent = 3 [default = ""];
}
required int32 qqNo = 1;
required int32 result = 2;
repeated Oplog oplogs=3;

}

//供管理员操作的service 接口
service OplogService {
rpc queryOplog(QueryOplogRequest ) returns(QueryOplogResponse);
}

[/code]

运行命令生成相关代码:
protoc.exe  -I=”D:\Java\protoc\javasrc” –java_out=”D:/Java/protoc/javasrc” D:\Java\protoc\javasrc\qquserinfo.proto
复制D:\Java\protoc\javasrc\com\lizongbo\QQUserInfoProtos.java到E:\mywork\protobuf\src\com\lizongbo\mobileqq。
协议定义的源代码就生成好了。

Tags: , , , ,