`
shijunjuan
  • 浏览: 46917 次
  • 性别: Icon_minigender_2
  • 来自: 上海
社区版块
存档分类
最新评论

如何应用Protobuf 和Jersy 打造Rest Service

 
阅读更多

我使用的是Maven Project,所以

1。第一步加入Maven Dependency。

 

		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-server</artifactId>
			<version>1.10</version>
		</dependency>
		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-client</artifactId>
			<version>1.10</version>
		</dependency>
		<dependency>
			<groupId>com.google.protobuf</groupId>
			<artifactId>protobuf-java</artifactId>
			<version>2.4.1</version>
		</dependency>

2。 然后,加入ant plugin来帮助我们产生protobuf 的java bean。

 

 

<build>
    <plugins>
    <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <executions>
          <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>run</goal>
            </goals>
            <configuration>
              <tasks>
                <mkdir dir='target/generated-sources' />
                <exec executable='protoc'>
                  <arg value='--java_out=target/generated-sources' />
                  <arg value='src/main/resources/addressbook.proto' />
                </exec>
              </tasks>
              <sourceRoot>target/generated-sources</sourceRoot>
            </configuration>
            
          </execution>
        </executions>
      </plugin>
      </plugins>
    <pluginManagement>
    	<plugins>
    		<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
    		<plugin>
    			<groupId>org.eclipse.m2e</groupId>
    			<artifactId>lifecycle-mapping</artifactId>
    			<version>1.0.0</version>
    			<configuration>
    				<lifecycleMappingMetadata>
    					<pluginExecutions>
    						<pluginExecution>
    							<pluginExecutionFilter>
    								<groupId>
    									org.apache.maven.plugins
    								</groupId>
    								<artifactId>
    									maven-antrun-plugin
    								</artifactId>
    								<versionRange>[1.3,)</versionRange>
    								<goals>
    									<goal>run</goal>
    								</goals>
    							</pluginExecutionFilter>
    							<action>
    								<ignore></ignore>
    							</action>
    						</pluginExecution>
    					</pluginExecutions>
    				</lifecycleMappingMetadata>
    			</configuration>
    		</plugin>
    	</plugins>
    </pluginManagement>
    </build>

3。 创建addressbook.proto文件

 

 

package tutorial;

option java_package = "com.sampullara.jaxrsprotobuf.tutorial";
option java_outer_classname = "AddressBookProtos";

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}

message AddressBook {
  repeated Person person = 1;
}

4。 运行mvn generate-sources命令来生成AddressBookProtos.java文件。

5。创建rest server端代码AddressBookService.java

package com.sampullara;


import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import com.sampullara.jaxrsprotobuf.tutorial.AddressBookProtos;


@Path("/person")
public class AddressBookService {
    @GET
    @Produces("application/x-protobuf")
    public AddressBookProtos.Person getPerson() {
        return AddressBookProtos.Person.newBuilder()
                .setId(1)
                .setName("Sam")
                .setEmail("sam@sampullara.com")
                .addPhone(AddressBookProtos.Person.PhoneNumber.newBuilder()
                        .setNumber("415-555-1212")
                        .setType(AddressBookProtos.Person.PhoneType.MOBILE)
                        .build())
                .build();
    }

    @POST
    @Consumes("application/x-protobuf")
    @Produces("application/x-protobuf")
    public AddressBookProtos.Person reflect(AddressBookProtos.Person person) {
        return person;
    }
}

 6。创建ProtobufProviders.java文件处理protobuf对象序列化。

package com.sampullara;

import com.google.protobuf.GeneratedMessage;
import com.google.protobuf.Message;

import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.WeakHashMap;

/**
 * These providers implement the conversion of protobuf objects to and from their serialized form over the wire.
 *  
 * User: sam
 * Date: Dec 27, 2008
 * Time: 3:13:17 PM
 */
public class ProtobufProviders {
    @Provider
    @Consumes("application/x-protobuf")
    public static class ProtobufMessageBodyReader implements MessageBodyReader<Message> {
        public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
            return Message.class.isAssignableFrom(type);
        }

        public Message readFrom(Class<Message> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
            try {
                Method newBuilder = type.getMethod("newBuilder");
                GeneratedMessage.Builder builder = (GeneratedMessage.Builder) newBuilder.invoke(type);
                return builder.mergeFrom(entityStream).build();
            } catch (Exception e) {
                throw new WebApplicationException(e);
            }
        }
    }

    @Provider
    @Produces("application/x-protobuf")
    public static class ProtobufMessageBodyWriter implements MessageBodyWriter<Message> {
        public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
            return Message.class.isAssignableFrom(type);
        }

        private Map<Object, byte[]> buffer = new WeakHashMap<Object, byte[]>();

        public long getSize(Message m, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try {
                m.writeTo(baos);
            } catch (IOException e) {
                return -1;
            }
            byte[] bytes = baos.toByteArray();
            buffer.put(m, bytes);
            return bytes.length;
        }

        public void writeTo(Message m, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
            entityStream.write(buffer.remove(m));
        }
    }
}

 7。创建服务器

package com.sampullara;
import java.io.IOException;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import com.sun.net.httpserver.HttpServer;
import com.sun.jersey.api.container.httpserver.HttpServerFactory;
import com.sun.jersey.api.core.PackagesResourceConfig;
import com.sun.jersey.api.core.ResourceConfig;

public class Main {
    public static final URI BASE_URI = UriBuilder.fromUri("http://localhost/").port(9998).build();

   

    public static HttpServer createServer(URI uri) throws IOException {
        ResourceConfig rc = new PackagesResourceConfig("com.sampullara");  
        return HttpServerFactory.create(uri, rc);
    }
}

 

8。编写客户端代码

package com.sampullara;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

import junit.framework.TestCase;

import com.sampullara.ProtobufProviders.ProtobufMessageBodyReader;
import com.sampullara.ProtobufProviders.ProtobufMessageBodyWriter;
import com.sampullara.jaxrsprotobuf.tutorial.AddressBookProtos;
//import com.sun.grizzly.http.SelectorThread;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.net.httpserver.HttpServer;
/**
 * TODO: Edit this
 * <p/>
 * User: sam
 * Date: Dec 27, 2008
 * Time: 5:10:58 PM
 */
public class MainTest extends TestCase {
    private HttpServer server;
    private WebResource r;

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        //start the Grizzly web container and create the client
        server = Main.createServer(Main.BASE_URI);
        server.start();
        ClientConfig cc = new DefaultClientConfig();
        cc.getClasses().add(ProtobufMessageBodyReader.class);
        cc.getClasses().add(ProtobufMessageBodyWriter.class);
        Client c = Client.create(cc);
        r = c.resource(Main.BASE_URI);
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        server.stop(0);
    }

    public void testUsingJerseyClient() {
        WebResource wr = r.path("person");
        AddressBookProtos.Person p = null;
		try {
			p = wr.get(AddressBookProtos.Person.class);
		} catch (UniformInterfaceException e) {
			e.printStackTrace();
		}
        assertEquals("Sam", p.getName());

        AddressBookProtos.Person p2 = wr.type("application/x-protobuf").post(AddressBookProtos.Person.class, p);
        assertEquals(p, p2);
    }

    public void testUsingURLConnection() throws IOException {
        AddressBookProtos.Person person;
        {
            URL url = new URL("http://localhost:9998/person");
            URLConnection urlc = url.openConnection();
            urlc.setDoInput(true);
            urlc.setRequestProperty("Accept", "application/x-protobuf");
            person = AddressBookProtos.Person.newBuilder().mergeFrom(urlc.getInputStream()).build();
            assertEquals("Sam", person.getName());
        }
        {
            URL url = new URL("http://localhost:9998/person");
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setDoInput(true);
            urlc.setDoOutput(true);
            urlc.setRequestMethod("POST");
            urlc.setRequestProperty("Accept", "application/x-protobuf");
            urlc.setRequestProperty("Content-Type", "application/x-protobuf");
            person.writeTo(urlc.getOutputStream());
            AddressBookProtos.Person person2 = AddressBookProtos.Person.newBuilder().mergeFrom(urlc.getInputStream()).build();
            assertEquals(person, person2);
        }
    }

}

 

 

 

分享到:
评论
1 楼 wing_wear 2014-11-27  
不好使啊,大哥。。

相关推荐

    利用spring整合jersey和Protobuf,搭建REST web服务

    这是一个典型的企业级应用开发场景,其中Spring提供了强大的依赖注入和AOP(面向切面编程)功能,Jersey作为JAX-RS(Java API for RESTful Web Services)的实现,负责处理HTTP请求和响应,而Protobuf则是一种高效的...

    使用protobuf和gRPC实现消息订阅系统

    Protobuf是一套类似Json或者XML的数据传输格式和规范,用于不同应用或进程之间进行通信时使用。通信时所传递的信息是通过Protobuf定义的message数据结构进行打包,然后编译成二进制的码流再进行传输或者存储。本次...

    protobuf编译好的文件

    protobuf编译好的文件通常指的是Google开源的Protocol Buffers(简称protobuf)编译后的二进制库、头文件和源代码,这些文件已经过编译,可以直接在开发项目中使用,以实现数据序列化和反序列化的高效通信。protobuf...

    实现protobuf和json互相转换python3源码

    在IT行业中,数据序列化和反序列化是一个关键任务,特别是在网络通信、数据存储和跨平台数据交换中。Google推出的Protocol Buffers...通过理解和应用这些技术,你可以优化你的应用程序,提高数据传输的效率和兼容性。

    protobuf jar 和 protoc 3.6.0

    标题中的“protobuf jar 和 protoc 3.6.0”指的是Google开源的Protocol Buffers(简称protobuf)在3.6.0版本的Java实现库(protobuf-java-3.6.0.jar)和编译器(protoc-3.6.0)。Protocol Buffers是一种高效的数据...

    protobufprotobufprotobufprotobuf

    protobuf,全称Protocol Buffers,是Google开发的一种...通过学习和使用protobuf,开发者可以提升应用程序的效率,优化数据传输,降低系统复杂性。对于任何涉及大量数据交换的项目,protobuf都是一个值得考虑的选择。

    protobuf中文学习文档

    它通过定义消息格式,将数据结构转换为二进制流,相比XML或JSON等文本格式,protobuf在传输和存储时具有更高的效率和更小的体积。protobuf不仅支持C++、Java和Python,还有丰富的语言扩展,如Go、JavaScript、PHP等...

    compile_protobuf_protobuf:compile_protobuf_

    3. **生成源代码**:protoc会生成对应语言的源代码,通常包括一个或多个类,这些类提供了序列化和反序列化protobuf消息的功能。 4. **集成到项目**:将生成的源代码添加到项目中,然后就可以像使用普通类一样使用...

    protobuf序列化和反序列化技术

    protobuf序列化和反序列化技术是大数据处理领域中不可或缺的一部分,尤其在实时大数据场景下,高效的数据传输和存储对性能有着直接影响。谷歌推出的Protocol Buffers(简称protobuf)是一种语言无关、平台无关的数据...

    unity3d&Protobuf&Socket

    在IT行业中,Unity3D是一款广泛应用于游戏开发的跨平台引擎,它支持创建2D、3D、VR和AR等多种类型的游戏。Protobuf(Protocol Buffers)是Google开发的一种数据序列化协议,常用于高效地存储和传输结构化数据。...

    protobuf-3.5-src

    3. 对于特定的开发环境和应用场景,3.5.0可能是一个稳定且广泛使用的版本。 在使用 **protobuf-3.5.0** 源码时,开发者通常会进行以下步骤: 1. 解压 `protobuf-3.5.0` 压缩包。 2. 配置构建环境,这可能涉及设置...

    android studio Kotlin中使用 GRPC和protobuf

    在Android开发中,gRPC和Protocol Buffers(protobuf)是两个强大的工具,它们可以极大地提升应用的性能和可维护性。本教程将详细介绍如何在Android Studio的Kotlin环境中使用gRPC和protobuf进行通信。 gRPC是一个...

    ros2转protobuf,再转dds发出.

    ROS2 (Robot Operating System 2) 是一个开源操作系统,用于构建智能机器人系统和自动化应用。在ROS2中,数据通信是通过DDS(Data Distribution Service)实现的,它是一种标准的实时中间件,用于高效率、可靠的...

    protobuf2.6.1

    在实际应用中,protobuf广泛应用于RPC(远程过程调用)框架、数据库存储、配置文件和日志记录等领域。例如,Google的gRPC框架就是基于protobuf来定义服务接口和交换数据的。 总的来说,protobuf2.6.1提供了在...

    spring boot protobuf demo

    6. **编写服务端代码**:创建一个Spring Boot REST控制器,使用protobuf生成的Java类处理请求和响应。例如,你可以创建一个`PersonController`,处理HTTP请求并将数据转化为protobuf格式。 7. **客户端调用**:...

    Protobuf-master包

    3. **数据持久化**:除了网络通信,Java 应用也可以使用 Protobuf 存储结构化数据到文件或数据库,便于数据交换和迁移。 **四、protobuf 标签** 在 Protobuf 中,每个字段都有一个唯一的整数标签(Tag),用来标识...

    protobuf source v3.21.12

    Protocol Buffers允许开发者定义数据结构的模式(schema),然后生成相应的语言绑定(如C++、Java、Python),使得应用程序可以方便地存储、读取和交换结构化数据。这种序列化格式比XML更紧凑,比JSON更快,且易于...

    protobuf 3.11版本,静态编译

    在Windows环境下,使用Visual Studio 2015进行protobuf的静态编译是一项关键任务,因为静态编译可以将protobuf库与应用程序链接在一起,形成一个单一的可执行文件,避免了运行时对动态库的依赖,提高了部署的便利性...

    protobuf-3.0.0最新版下载

    protoc是protobuf的核心工具,它负责将.proto定义文件转换为各种目标语言(如C++、Java、Python等)的源代码,使得应用程序能够方便地序列化和反序列化protobuf消息。 标签 "protobuf" 和 "protoc" 是与该主题直接...

    Protobuf应用实例

    通过运行这些示例,开发者可以更好地理解和掌握protobuf在JAVA环境中的实际应用。 ### 5. 进阶使用 - **服务端RPC**:protobuf也支持gRPC,一种基于HTTP/2的高性能RPC框架,可用于构建分布式微服务架构。 - **字段...

Global site tag (gtag.js) - Google Analytics