Protostuff开发

作者:chszs,未经博主允许不得转载。

五、Protostuff用法

1、为Java实体产生schemas

<dependency>
  <groupId>io.protostuff</groupId>
  <artifactId>protostuff-core</artifactId>
  <version>1.3.8</version>
</dependency>

2、Runtime schemas

<dependency>
  <groupId>io.protostuff</groupId>
  <artifactId>protostuff-runtime</artifactId>
  <version>1.3.8</version>
</dependency>

3、Protostuff的Maven插件

Protostuff的Maven插件可以从.proto文件中生成Java源码或其它语言的源码——通过使用基于StringTemplate的代码生成器(或扩展)。
下面讲述此插件的用法。

1)项目的结构如下:

<project root>
├───pom.xml
└───src
    └───main
        └───proto
            └───hello.proto

Protocol buffer定义路径是可配置的,但是推荐使用src/main/proto/路径。所有的.proto文件及其子目录都放于此目录下,且会被protobuf定义视为包结构,以import方式导入。

hello.proto的内容如下:

package search;

option java_package = "stuff.ch";

message HelloRequest {
    optional string name = 1;
}

message HelloResponse {
    optional string greeting = 1;
}

service HelloService {
    rpc hello (HelloRequest) returns (HelloResponse);
}

执行命令:

mvn protostuff:compile

在项目目录下产生相应的Java文件。

<project root>
├───pom.xml
└───target
    └───generated-sources
        └───proto
            └───stuff
                └───ch
                    └───HelloRequest.java
                    └───HelloResponse.java

HelloRequest.java的内容如下:

// Generated by http://code.google.com/p/protostuff/ ... DO NOT EDIT!
// Generated from proto

package stuff.ch;

import javax.annotation.Generated;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Objects;

import io.protostuff.GraphIOUtil;
import io.protostuff.Input;
import io.protostuff.Message;
import io.protostuff.Output;
import io.protostuff.Schema;

@Generated("java_bean")
public final class HelloRequest implements Externalizable, Message<HelloRequest>, Schema<HelloRequest> {

    public static Schema<HelloRequest> getSchema() {
        return DEFAULT_INSTANCE;
    }

    public static HelloRequest getDefaultInstance() {
        return DEFAULT_INSTANCE;
    }

    static final HelloRequest DEFAULT_INSTANCE = new HelloRequest();

    private String name;

    public HelloRequest() {

    }

    // getters and setters

    // name

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || this.getClass() != obj.getClass()) {
            return false;
        }
        final HelloRequest that = (HelloRequest) obj;
        return Objects.equals(this.name, that.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }

    @Override
    public String toString() {
        return "HelloRequest{" + "name=" + name + '}';
    }
    // java serialization

    public void readExternal(ObjectInput in) throws IOException {
        GraphIOUtil.mergeDelimitedFrom(in, this, this);
    }

    public void writeExternal(ObjectOutput out) throws IOException {
        GraphIOUtil.writeDelimitedTo(out, this, this);
    }

    // message method

    public Schema<HelloRequest> cachedSchema() {
        return DEFAULT_INSTANCE;
    }

    // schema methods

    public HelloRequest newMessage() {
        return new HelloRequest();
    }

    public Class<HelloRequest> typeClass() {
        return HelloRequest.class;
    }

    public String messageName() {
        return HelloRequest.class.getSimpleName();
    }

    public String messageFullName() {
        return HelloRequest.class.getName();
    }

    public boolean isInitialized(HelloRequest message) {
        return true;
    }

    public void mergeFrom(Input input, HelloRequest message) throws IOException {
        for (int number = input.readFieldNumber(this);; number = input.readFieldNumber(this)) {
            switch (number) {
            case 0:
                return;
            case 1:
                message.name = input.readString();
                break;
            default:
                input.handleUnknownField(number, this);
            }
        }
    }

    public void writeTo(Output output, HelloRequest message) throws IOException {
        if (message.name != null)
            output.writeString(1, message.name, false);
    }

    public String getFieldName(int number) {
        return Integer.toString(number);
    }

    public int getFieldNumber(String name) {
        return Integer.parseInt(name);
    }

}

HelloResponse.java的内容如下:

// Generated by http://code.google.com/p/protostuff/ ... DO NOT EDIT!
// Generated from proto

package stuff.ch;

import javax.annotation.Generated;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Objects;

import io.protostuff.GraphIOUtil;
import io.protostuff.Input;
import io.protostuff.Message;
import io.protostuff.Output;
import io.protostuff.Schema;

@Generated("java_bean")
public final class HelloResponse implements Externalizable, Message<HelloResponse>, Schema<HelloResponse> {

    public static Schema<HelloResponse> getSchema() {
        return DEFAULT_INSTANCE;
    }

    public static HelloResponse getDefaultInstance() {
        return DEFAULT_INSTANCE;
    }

    static final HelloResponse DEFAULT_INSTANCE = new HelloResponse();

    private String greeting;

    public HelloResponse() {

    }

    // getters and setters

    // greeting

    public String getGreeting() {
        return greeting;
    }

    public void setGreeting(String greeting) {
        this.greeting = greeting;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || this.getClass() != obj.getClass()) {
            return false;
        }
        final HelloResponse that = (HelloResponse) obj;
        return Objects.equals(this.greeting, that.greeting);
    }

    @Override
    public int hashCode() {
        return Objects.hash(greeting);
    }

    @Override
    public String toString() {
        return "HelloResponse{" + "greeting=" + greeting + '}';
    }
    // java serialization

    public void readExternal(ObjectInput in) throws IOException {
        GraphIOUtil.mergeDelimitedFrom(in, this, this);
    }

    public void writeExternal(ObjectOutput out) throws IOException {
        GraphIOUtil.writeDelimitedTo(out, this, this);
    }

    // message method

    public Schema<HelloResponse> cachedSchema() {
        return DEFAULT_INSTANCE;
    }

    // schema methods

    public HelloResponse newMessage() {
        return new HelloResponse();
    }

    public Class<HelloResponse> typeClass() {
        return HelloResponse.class;
    }

    public String messageName() {
        return HelloResponse.class.getSimpleName();
    }

    public String messageFullName() {
        return HelloResponse.class.getName();
    }

    public boolean isInitialized(HelloResponse message) {
        return true;
    }

    public void mergeFrom(Input input, HelloResponse message) throws IOException {
        for (int number = input.readFieldNumber(this);; number = input.readFieldNumber(this)) {
            switch (number) {
            case 0:
                return;
            case 1:
                message.greeting = input.readString();
                break;
            default:
                input.handleUnknownField(number, this);
            }
        }
    }

    public void writeTo(Output output, HelloResponse message) throws IOException {
        if (message.greeting != null)
            output.writeString(1, message.greeting, false);
    }

    public String getFieldName(int number) {
        return Integer.toString(number);
    }

    public int getFieldNumber(String name) {
        return Integer.parseInt(name);
    }

}

编写HelloService.java,内容如下:

package stuff.ch;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtobufIOUtil;
import io.protostuff.Schema;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class HelloService {
    public static final Schema<HelloRequest> SEARCH_REQUEST_SCHEMA = HelloRequest.getSchema();
    public static final Schema<HelloResponse> SEARCH_RESPONSE_SCHEMA = HelloResponse.getSchema();

    /**
     * Sample "hello" rpc method handler.
     *
     * @param requestData
     *            {@code HelloRequest} binary array encoded using Protocol
     *            Buffers
     * @return {@code HelloResponse} binary array encoded using Protocol Buffers
     */
    public byte[] hello(byte[] requestData) throws IOException {
        HelloRequest request = deserialize(requestData);
        HelloResponse response = hello(request);
        return serialize(response);
    }

    private byte[] serialize(HelloResponse response) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        LinkedBuffer buffer = LinkedBuffer.allocate();
        ProtobufIOUtil.writeTo(outputStream, response, SEARCH_RESPONSE_SCHEMA, buffer);
        return outputStream.toByteArray();
    }

    private HelloRequest deserialize(byte[] requestData) {
        HelloRequest request = SEARCH_REQUEST_SCHEMA.newMessage();
        ProtobufIOUtil.mergeFrom(requestData, request, SEARCH_REQUEST_SCHEMA);
        return request;
    }

    /**
     * Service method implementation.
     */
    private HelloResponse hello(HelloRequest request) {
        HelloResponse response = new HelloResponse();
        String name = request.getName();
        response.setGreeting("Hello, " + name);
        return response;
    }
}

编写单元测试类HelloServiceTest.java,内容如下:

package stuff.ch;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class HelloServiceTest {
    public static final byte[] REQUEST = new byte[] { 0x0A, 0x03, '4', '2', '!' };
    public static final byte[] RESPONSE = new byte[] { 0x0A, 0x0A, 'H', 'e', 'l', 'l', 'o', ',', ' ', '4', '2', '!' };

    private HelloService service;

    @Before
    public void setUp() throws Exception {
        service = new HelloService();
    }

    @Test
    public void testSearch() throws Exception {
        byte[] responseData = service.hello(REQUEST);
        Assert.assertArrayEquals(RESPONSE, responseData);
    }
}

运行单元测试,测试通过。