`
shijunjuan
  • 浏览: 45323 次
  • 性别: 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整合了Jersey和Protobuf,搭建了一个简单的Rest web service的工程,仅当作学习; 客户端是用python写的一个简单工程;

    python安装protobuf和编译教程和安装包文件_详细好用

    python安装protobuf和编译教程和安装包文件_详细好用

    unity3d&Protobuf&Socket

    unity3d应用Protobuf实现Socket通信

    protobuf编译好的文件

    编译好直接可以使用的protobuf文件。运行bat文件,即可直接生成对应.proto的头文件和源文件

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

    实现protobuf和json互相转换python3源码,protobuf是Google开源的新传输协议,压缩效率和传输效率比XML和json都要高

    google protobuf的应用

    服务器端与客户端通信,使用google protobuf作为交互数据的序列化工具,其中客户端使用select机制实现I/O复用,服务端使用epoll机制,提高并发连接时的处理效率。软件环境:linux。文件dealpack.cc是服务端和客户端...

    google protobuf 最新源代码

    google protobuf 最新源代码google protobuf 最新源代码google protobuf 最新源代码google protobuf 最新源代码google protobuf 最新源代码google protobuf 最新源代码google protobuf 最新源代码google protobuf ...

    protobuf 3.5.1

    可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。 压缩包中包括如下文件: protobuf-all-...

    protobufDemo.rar

    protobufDemo protobuf例程protobufDemo protobuf例程protobufDemo protobuf例程protobufDemo protobuf例程protobufDemo protobuf例程protobufDemo protobuf例程protobufDemo protobuf例程

    compile_protobuf_protobuf:compile_protobuf_

    protobuf 建立proto文件的依赖编译关系

    protobuf3.4源码和win32

    protobuf3.4源码和win32

    ros2 msg转protobuf 案例

    ros2使用自建类型编译,订阅以及发布的demo,并且包括和protobuf互转的使用方式. 自建类型为序列化数据{uint32 size, uint8 data[] }

    protobuf 3.6.1

    可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。 压缩包中包括如下文件: java库 ...

    protobuf 3.5.0

    可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。 压缩包中包括如下文件: protobuf-all-...

    protobuf序列化和反序列化技术

    大数据场景下序列化和反序列化技术,谷歌提供技术 protobuf-jetbrains-plugin-0.13.0.zip

    Protobuf应用实例

    Protobuf 实例 JAVA 编解码技术

    Protobuf-master包

    android,java,protobuf,

    protobuf 2.5版 jar包

    protobuf2.5.jar 可直接使用

    mina和protobuf整合教程

    mina和protobuf整合教程,mina不像nety自带protobuf整合,这个教程叙述了mina和protbuf的整合。

    protobuf2.6.1

    包含protobuf2.6.1编译好的lib和exe,把lib文件放到c:\windows即可。并带有protobuf的windows和linux的源码包。

Global site tag (gtag.js) - Google Analytics