An overview:
RESTful architecture is the most popular form of Internet software architecture. It is clearly structured, standards-compliant, easy to understand, easy to expand, so the site is being used more and more.
Google Protocol Buffer (referred Protobuf) is a mixed-language Google's internal data standards, is a lightweight and efficient structured data storage format that can be used to structure data serialization, or serialized. It is very suitable for data storage or RPCdata exchange format. Can be used for communication protocols, data storage and other areas of language-independent, platform-independent, scalable serial data format structure. Currently provides C + +, Java, Python three languages of the API.
tomcat Servlet container to the market share of the first and well-known, so this paper spoke of how to use Jersey, Google PB, Tomcat these three magic weapons development REST-style WEB service.
Two environmental structures
jersey version: jersey-archive-1.2-SNAPSHOT
Google PB Version: protobuf-2.3.0
tomcat: tomcat6.0
Eclipse: 3.5.1 + tomcat plug in: http://www.eclipsetotale.com/tomcatPlugin.html
Google PB Version: protobuf-2.3.0
tomcat: tomcat6.0
Eclipse: 3.5.1 + tomcat plug in: http://www.eclipsetotale.com/tomcatPlugin.html
Three projects since lib
sm-3.1.jar
jersey-server-1.2-SNAPSHOT.jar
jackson-core-asl-1.1.1.jar
jersey-spring-1.2-SNAPSHOT.jar
jersey-client-1.2-SNAPSHOT.jar
jettison-1.1.jar
jersey-core-1.2-SNAPSHOT.jar
jsr311-api-1.1.1.jar
jersey-json-1.2-SNAPSHOT.jar
protobuf-java-2.3.0.jar
Please jersey of the package and the package to find the pb the lib
jersey-server-1.2-SNAPSHOT.jar
jackson-core-asl-1.1.1.jar
jersey-spring-1.2-SNAPSHOT.jar
jersey-client-1.2-SNAPSHOT.jar
jettison-1.1.jar
jersey-core-1.2-SNAPSHOT.jar
jsr311-api-1.1.1.jar
jersey-json-1.2-SNAPSHOT.jar
protobuf-java-2.3.0.jar
Please jersey of the package and the package to find the pb the lib
Four hands
4.1 Create a tomcat project in Eclipse,
The Eclipse workspace for the D :/ workspace:
addressbook.proto pb comes with the phone message definition file
compile.bat build scripts to write their own message
protoc.exe pb compiler command-line tool
ContactClient.java access REST service's client-side code
CreatePerson.java generate Person PB write their own structure, and there is D: root directory gadget category
AddressBookResource REST Service Core Resource Class
HelloResource.java Hello world Resource Class
AddressBookStore.java wrote a phonebook storage class server segment to D :/ addressBooks.txt to store files
AddressBookProtos.java addressbook.proto been compiled PB command-line tool to generate java class
ProtobufMessageBodyReader.java server sends Request input streams into PB structures Provider class for the user to wear on a byte-stream into the PB structure
ProtobufMessageBodyWriter.java server into the PB institutions output stream Provider class for the PB structure into a byte stream output to the user
4.3 Code:
- addressbook.proto
- package demo;
- option java_package = "sample.pb";
- 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;
- }
--------------------------------------
compile.bat
protoc-I = D :/ workspace / jerseydemo / src - java_out = D :/ workspace / jerseydemo / src D :/ workspace / jerseydemo / src / demo / pb / addressbook.proto
protoc-I = D :/ workspace / jerseydemo / src - java_out = D :/ workspace / jerseydemo / src D :/ workspace / jerseydemo / src / demo / pb / addressbook.proto
--------------------------------------
ContactClient.java
- package sample.hello.client;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.util.List;
- import sample.pb.AddressBookProtos.Person;
- import sample.pb.AddressBookProtos.Person.PhoneNumber;
- public class ContactClient {
- public static void main (String [] args) throws IOException {
- String url1 = "http://localhost:8080/jerseydemo/rest/addressbook/";
- putContacts (url1, "hery");
- String url2 = "http://localhost:8080/jerseydemo/rest/addressbook/hery";
- getContacts (url2);
- }
- public static void putContacts (String url, String name) throws IOException {
- File file = new File ("D :/" + name + ". Per");
- Person p = Person.parseFrom (new FileInputStream (file));
- byte [] content = p.toByteArray ();
- URL target = new URL (url);
- HttpURLConnection conn = (HttpURLConnection) target.openConnection ();
- conn.setDoOutput (true);
- conn.setDoInput (true);
- conn.setRequestMethod ("PUT");
- conn.setRequestProperty ("Content-Type", "application / x-protobuf");
- conn.setRequestProperty ("Accept", "application / x-protobuf; q = 0.5");
- conn.setRequestProperty ("Content-Length", Integer.toString (content.length));
- / / Set stream mode to decrease memory usage
- conn.setFixedLengthStreamingMode (content.length);
- OutputStream out = conn.getOutputStream ();
- out.write (content);
- out.flush ();
- out.close ();
- conn.connect ();
- / / Check response code
- int code = conn.getResponseCode ();
- boolean success = (code> = 200) && (code <300 span="">300>
- System.out.println ("put person:" + name + "" + (success? "Successful!": "Failed!"));
- }
- public static void getContacts (String url) throws IOException {
- URL target = new URL (url);
- HttpURLConnection conn = (HttpURLConnection) target.openConnection ();
- conn.setDoOutput (true);
- conn.setDoInput (true);
- conn.setRequestMethod ("GET");
- conn.setRequestProperty ("Content-Type", "application / x-protobuf");
- conn.setRequestProperty ("Accept", "application / x-protobuf");
- conn.connect ();
- / / Check response code
- int code = conn.getResponseCode ();
- boolean success = (code> = 200) && (code <300 span="">300>
- InputStream in = success? Conn.getInputStream (): conn.getErrorStream ();
- int size = conn.getContentLength ();
- byte [] response = new byte [size];
- int curr = 0, read = 0;
- while (curr
- read = in.read (response, curr, size - curr);
- if (read <= 0) break;
- curr + = read;
- }
- Person p = Person.parseFrom (response);
- System.out.println ("id:" + p.getId ());
- System.out.println ("name:" + p.getName ());
- System.out.println ("email:" + p.getEmail ());
- List
pl = p.getPhoneList (); - for (PhoneNumber pn: pl) {
- System.out.println ("number:" + pn.getNumber () + "type:" + pn.getType (). Name ());
- }
- }
- }
CreatePerson.java
- package sample.hello.client;
- import java.io.BufferedReader;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintStream;
- import sample.pb.AddressBookProtos.Person;
- public class CreatePerson {
- / / This function fills in a Person message based on user input.
- static Person create (BufferedReader stdin,
- PrintStream stdout) throws IOException {
- Person.Builder person = Person.newBuilder ();
- stdout.print ("Enter person ID:");
- person.setId (Integer.valueOf (stdin.readLine ()));
- stdout.print ("Enter name:");
- person.setName (stdin.readLine ());
- stdout.print ("Enter email address (blank for none):");
- String email = stdin.readLine ();
- if (email.length ()> 0) {
- person.setEmail (email);
- }
- while (true) {
- stdout.print ("Enter a phone number (or leave blank to finish):");
- String number = stdin.readLine ();
- if (number.length () == 0) {
- break;
- }
- Person.PhoneNumber.Builder phoneNumber =
- Person.PhoneNumber.newBuilder (). SetNumber (number);
- stdout.print ("Is this a mobile, home, or work phone?");
- String type = stdin.readLine ();
- if (type.equals ("mobile")) {
- phoneNumber.setType (Person.PhoneType.MOBILE);
- } Else if (type.equals ("home")) {
- phoneNumber.setType (Person.PhoneType.HOME);
- } Else if (type.equals ("work")) {
- phoneNumber.setType (Person.PhoneType.WORK);
- } Else {
- stdout.println ("Unknown phone type. Using default.");
- }
- person.addPhone (phoneNumber);
- }
- return person.build ();
- }
- / / Main function: Reads the entire address book from a file,
- / / Adds one person based on user input, then writes it back out to the same
- / / File.
- public static void main (String [] args) throws Exception {
- Person p = create (new BufferedReader (new InputStreamReader (System.in)),
- System.out);
- / / Write the new address book back to disk.
- FileOutputStream output = new FileOutputStream ("D :/" + p.getName () + ". Per");
- p.writeTo (output);
- output.close ();
- }
- }
AddressBookResource.java
- package sample.hello.resources;
- import javax.ws.rs.GET;
- import javax.ws.rs.PUT;
- import javax.ws.rs.Path;
- import javax.ws.rs.PathParam;
- import javax.ws.rs.core.Response;
- import sample.hello.util.AddressBookStore;
- import sample.pb.AddressBookProtos.Person;
- @ Path ("/ addressbook")
- public class AddressBookResource {
- @ PUT
- public Response putPerson (Person person) {
- AddressBookStore.store (person);
- return Response.ok (). build ();
- }
- @ GET
- @ Path ("/ {name}")
- public Response getPerson (@ PathParam ("name") String name) {
- Person p = AddressBookStore.getPerson (name);
- return Response.ok (p, "application / x-protobuf"). build ();
- }
- }
AddressBookStore.java
- package sample.hello.util;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import sample.pb.AddressBookProtos.AddressBook;
- import sample.pb.AddressBookProtos.Person;
- public class AddressBookStore {
- static AddressBook addressBook = null;
- static {
- try {
- addressBook =
- AddressBook.parseFrom (new FileInputStream ("D :/ addressBooks.txt"));
- } Catch (FileNotFoundException e) {
- e.printStackTrace ();
- } Catch (IOException e) {
- e.printStackTrace ();
- }
- }
- public static Person getPerson (String name) {
- for (Person person: addressBook.getPersonList ()) {
- if (person.getName (). equals (name)) {
- return person;
- }
- }
- return null;
- }
- public static void store (Person p) {
- AddressBook.Builder addressBookBuilder = AddressBook.newBuilder ();
- try {
- String fileName = "D :/ addressBooks.txt";
- File file = new File (fileName);
- if (! file.exists ()) {
- file.createNewFile ();
- }
- addressBookBuilder.mergeFrom (new FileInputStream (fileName));
- addressBookBuilder.addPerson (p);
- addressBookBuilder.build (). writeTo (new FileOutputStream (fileName));
- } Catch (FileNotFoundException e) {
- e.printStackTrace ();
- } Catch (IOException e) {
- e.printStackTrace ();
- }
- }
AddressBookProtos.java automatically generated slightly
ProtobufMessageBodyReader.java
- package sample.pb;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Type;
- import javax.ws.rs.Consumes;
- 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.Provider;
- import sample.pb.AddressBookProtos.Person;
- @ Provider
- @ Consumes ("application / x-protobuf")
- public class ProtobufMessageBodyReader implements MessageBodyReader
- @ Override
- public boolean isReadable (Class type, Type genericType, Annotation [] annotations,
- MediaType mediaType) {
- return mediaType.toString (). equals ("application / x-protobuf");
- }
- @ Override
- public Object readFrom (Class
- Annotation [] annotations, MediaType mediaType,
- MultivaluedMap
httpHeaders, InputStream inputStream) - throws IOException, WebApplicationException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream ();
- byte [] buffer = new byte [4096];
- int read;
- long total = 0L;
- do {
- read = inputStream.read (buffer, 0, buffer.length);
- if (read> 0) {
- baos.write (buffer, 0, read);
- total + = read;
- }
- } While (read> 0);
- return Person.parseFrom (baos.toByteArray ());
- }
- }
ProtobufMessageBodyWriter.java
- package sample.pb;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Type;
- import java.util.Map;
- import java.util.WeakHashMap;
- 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.MessageBodyWriter;
- import javax.ws.rs.ext.Provider;
- import sample.pb.AddressBookProtos.Person;
- @ Provider
- @ Produces ("application / x-protobuf")
- public class ProtobufMessageBodyWriter implements MessageBodyWriter
- / ** A cache to save the cost of duplicated call (getSize, writeTo) to one object. * /
- private Map buffer = new WeakHashMap
web.xml
- Xml version = "1.0" encoding = "UTF-8"?>
xmlns = "http://java.sun.com/xml/ns/javaee" xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" - xsi: schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
- version = "2.5">
-
-
ServletAdaptor </ servlet-name> -
com.sun.jersey.server.impl.container.servlet.ServletAdaptor </ servlet-class> -
1 </ load-on-startup> - </ Servlet>
-
-
ServletAdaptor </ servlet-name> -
/ rest / * </ url-pattern> - </ Servlet-mapping>
- </ Web-app>
Five testing process:
5.1
Set the web application's context name is:
/ Jerseydemo
The root for the web application
/ Context
Using Eclipse tomcat plugin menu
/ Jerseydemo
The root for the web application
/ Context
Using Eclipse tomcat plugin menu
In% TOMACT_HOME% \ conf \ Catalina \ localhost generate documents:
jerseydemo.xml
Reads as follows:
jerseydemo.xml
Reads as follows:
5.2 Running CreatePerson generate Person and written to disk:
View D: root directory, discover new generation hery.per file.
5.3 Start tomcat (I was on the point under the Eclipse kitten)
5.4 Run ContactClient, perform the following results
his shows that we uploaded successfully, and can query by name.
D root directory, while generating a file addressBooks.txt, this is the place to keep the phonebook server segment.
D root directory, while generating a file addressBooks.txt, this is the place to keep the phonebook server segment.
Six complete engineering package file
Modify the downloaded three files named
jerseydemo.part1.rar
jerseydemo.part2.rar
jerseydemo.part3.rar
Then extract