Archive for the ‘ REST ’ Category


Restlet2.0初尝试

今天一直在研究Restlet的API,大约应该是在2007年起,1.0版就已经问世了。但是由于这个概念在当时还是比较新的,所以1.0版本的普及率特别是在国内的普及率还是很低的。百度一下就会发现研究的人的确不多。现在RESTful的概念是越吵越热,且不说它到底好坏与否,但是引起这么多人的关注,就说明了它有其出色的地方。

在网站上看到的Stable的版本是1.6,于是保守地先从这个版本试起,结果发现无论如何添加Connector,都会报找不到Protocol的错,恰好这时James过来看看我,于是在他的建议之下,尝试了2.0m5版本。至少在最简单的程序部分,能够很正常的运行。

下面把一些很简单的步骤作个罗列:

在我看来,完成一个全部由Restlet构造的程序,一共需要四个部分。首先便是资源文件,对于REST概念比较熟悉的同学都应该明白,Resource在REST中是根本中的根本。于是,我们首先定义一个十分简单的Resource,为了简单起见,我们只给它附加两个功能,GET和POST。其中GET方法,很简单的返回一个String,POST方法是将得到的两个数进行相加返回结果字符串。

public class TestResource extends ServerResource{

	@Get
	public String getResultGet(){
		return "This is my test!";
	}

	@Post
	public String getResultPost(Representation entity){
		Form form = new Form(entity);
		String first = form.getFirstValue("first");
		String second = form.getFirstValue("second");
		int a = Integer.parseInt(first);
		int b = Integer.parseInt(second);

		return "The result of "+a+"+"+b+"is "+(a+b);
	}
}

在这一步结束之后,我们需要把资源放到一给应用(Application)中去,同时要提供访问它的路径。我个人心目中就把这个部分成为RouterPath,因为这两个单词也是这个文件中最多见的。

public class RouterPath extends Application{
        @Override
	public Restlet createInboundRoot() {
		// TODO Auto-generated method stub
		Router router = new Router(getContext());

		router.attach("/greeting",TestResource.class);

		return router;
	}
}

在这一给类中,它继承来Application这个类,目的就可以看成是提供了一个程序环境,在这个大的环境之下,你输入的方法,就将被引导到某个类之中去。比如在这里,所有的以greeting结尾的请求,都会被引导到我们刚才所创建的类里面去。

有来这样两样以后,我们只需要启动这个资源让它开始服务就可以了。我把这个类命名为StartResource类。

public class StartResource {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			// Create a new Component.
			Component component = new Component();  

			// Add a new HTTP server listening on port 8182.
			component.getServers().add(Protocol.HTTP, 8182);  

			// Attach the sample application.
			component.getDefaultHost().attach(new RouterPath());  

			// Start the component.
			component.start();
		}catch (Exception e) {
			// Something is wrong.
			e.printStackTrace();
		}
	}
}

我们可以很清楚的看到,这个类启动来在端口8182上的HTTP协议,然后将前面的Application附加在来这个端口上。然后服务就开始启动,等待他人的使用了。

现在我们就可以直接在浏览器中输入这个URL,来调用GET方法了。在这里,我们输入http://localhost:8182/greeting,屏幕上就出现来This is my test!字样。当然浏览器是不支持POST,PUT和DELETE直接在地址栏中的,我们可以用一个简单的JSP界面做一给POST框体,也可以像如下的类用Restlet提供的Client来完成请求。

public class Client {
	public static void main(String[] args) {
		int a=4;
		int b=9;
		ClientResource client = new ClientResource("http://localhost:8182/greeting");
		try {
			System.out.println(client.get().getText());
			Form form = new Form();
			form.add("first", a+"");
			form.add("second",b+"");
			System.out.println(client.post(form.getWebRepresentation()).getText());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

很容易看到,GET方法是可以直接用client得到的,而POST方法需要传入一个参数,也就是Resource端所需要的参数。用类似的办法,我们同样可以完成PUT和DELETE。

以上的这个例子实际上非常基础,但是至少展现来Restlet的一些特点,首先它是一个很完善的既支持客户端又支持服务端的API;其次它的结构也十分清晰,只要很好的划分了不同的请求,就能很好地看清楚之间的逻辑;最后就是API的封装还是很简洁的,尤其是在客户端调用这一块。

明天开始继续深入研究,更多的Tutorial可以参见http://www.restlet.org/documentation/2.0/tutorial

RESTful Web Services Developer’s Guide

Chapter 1
Introduction to RESTful Web Services and Jersey
1. What are RESTful Web Services?
RESTful - REpresentational State Transfer is an architectural style that specifies constraints, such as the uniform interface, that if applied to a web service induce desirable properties, such as performance, scalability, and modifiability, that enable services to work best on the Web.
Data and functionality are considered resources, and these resources are accessed using URIs (Unifomr Resource Identifiers), typically links on the web.
The REST architectural style constrains an architecture to a client-server architecture, and is designed to use a stateless communication protocol, typically HTTP. Clients and servers exchange representations of resources using a standardized interface and protocol.
RESTful web services typically map the four main HTTP methods to the operations they perform: create, retrieve, update and delete.
GET — Get a resource;    POST — Create a resource and other operations, as it has no defined semantics;    PUT — Create or update a resource;    DELETE — delete a resource

2. How does Jersey fit in?
Jersey is Sun’s production quality reference implementation for JSR 311: JAX-RS: The Java API for RESTful Web Services. Jersey implements support for the annotations defined in JSR-311, making it easy for developers to build RESTful web services with Java and Java JVM. Jersey also adds additional features not specified by the JSR.

Chapter 3
Creating a RESTful resource class
Root resource classes are POJOs that are either annotated with @Path or have at least one method annotated with @Path or a request method designator such as @GET, @PUT, @POST,  or @DELETE.
Resource methods are methods of a resource class annotated with a request method designator.

1. Developing RESTful web services with Jersey
Developers decorate Java programming language class files with HTTP-specific annotations to define resources and the actions that can be performed on those resources. Jersey annotations are runtime annotations, therefore, runtime reflection will generate the helper classes and artifacts for the resource, and then the collection of classes and artifacts will be built into a WAR. The resources are exposed to clients by deploying the WAR to a Java EE or web server.

@Path annotation’s value is a relative URI path. What makes JAX-RS so useful is that you can embed variables in the URIs. URI path templates are URIs with variables embedded within the URI syntax.
@GET annotation is a request method designator, along with @POST, @PUT, @DELETE, and @HEAD, that is defined by JAX-RS, and which correspond to the similarly named HTTP methods.
@Produces annotation is used to specify the MIME media types of representations a resource can produce and send back to the client.
@Consumes annotation is used to specify the MIME media types of representations a resource can consume that were sent by the client.

2. What are some of the annotations defined by JAX-RS?

Annotations Description
@Path The @Path annotation’s value is a relative URI path indicating where the Java class will be hosted, for example, /helloworld. You can also embed variables in the URIs to make a URI path template. For example, you could ask for the name of a user, and pass it to the application as a variable in the URI, like this, /helloworld/{username}.
@GET The @GET annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP GET requests. The behavior of a resource is determined by the HTTP method to which the resource is responding.
@POST The @POST annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP POST requests. The behavior of a resource is determined by the HTTP method to which the resource is responding.
@PUT The @PUT annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP PUT requests. The behavior of a resource is determined by the HTTP method to which the resource is responding.
@DELETE The @DELETE annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP DELETE requests. The behavior of a resource is determined by the HTTP method to which the resource is responding.
@HEAD The @HEAD annotation is a request method designator and corresponds to the similarly named HTTP method. The Java method annotated with this request method designator will process HTTP HEAD requests. The behavior of a resource is determined by the HTTP method to which the resource is responding.
@PathParam The @PathParam annotation is a type of parameter that you can extract for use in your resource class. URI path parameters are extracted from the request URI, and the parameter names correspond to the URI path template variable names specified in the @Path class-level annotation.
@QueryParam The @QueryParam annotation is a type of parameter that you can extract for use in your resource class. Query parameters are extracted from the request URI query parameters.
@Consumes The @Consumes annotation is used to specify the MIME media types of representations a resource can consume that were sent by the client.
@Produces The @Produces annotation is used to specify the MIME media type of representations a resource can produce and send back to the client, for example, “text/plain”.
@Provider The @Provider annotation is used for anything that is of interest to the JAX-RS runtime, such as MessageBodyReader and MessageBodyWriter. For HTTP requests, the MessageBodyReader is used to map an HTTP request entity body to method parameters. On the response side, a return value is mapped to an HTTP response entity body using MessageBodyWriter. If the application needs to supply additional metadata, such as HTTP headers or a different status code, a method can return a Response that wraps the entity, and which can be built using Response.ResponseBuilder.

3. The @Path annotation and URI path templates.
The @Path annotation identifies the URI path template to which the resource responds, and is specified at the class level of a resource. URI path templates are URIs with variables embedded within the URI syntax. These variables are substituted at runtime in order for a resource to respond to a request based on the substituted URI. Variables are denoted by curly braces.
@Path (”/users/{username}”)
if user entered user name as Galileo, the web service will respond to the following URL: http://example.com/users/Galileo

The @PathParam annotation may be used on the method parameter of a request method to obtain the value of the username variable.
public class UserResource{
@GET
@Produces(”text/xml”)
public String getUser(@PathParam(”username”) String userName){

}
}

By default, there is no difference between @Path value begin or not begin with a forward slash(/) and end with a forward slash(/) as well. However, Jersey has a redirection mechanism, if enabled, will perform redirection.

4. Responding to HTTP Resources
The behavior of a resource is determined by the HTTP methods (typically GET, POST, PUT, and DELETE)  to which the resource is responding.
By default, the JAX-RS runtime will automatically support the methods HEAD and OPTIONS if not explicitly implemented. For HEAD, the runtime will invoke the implemented GET method (if present) and ignore the response entity (if set). For OPTIONS, the Allow response header will be set to the set of HTTP methods support by the resources. In addition Jersey will return a WADL document describing the resource.
Method decorated with request method designators must return void, a Java programming language type, or a javax.ws.rs.core.Response object. Multiple parameters may be extracted from the URI using the PathParam or QueryParam annotations. Conversion between Java types and entity body is the responsibility of an entity provider, such as MessageBodyReader or MessageBodyWriter. Methods that need to provide additional metadata with a response should return an instance of Response. The ResponseBuilder class provides a convenient way to create a Response instance using a builder pattern. The HTTP PUT and POST methods expect an HTTP request body, so you should use a MessageBodyReader for methods that respond to PUT and POST requests.

5. Using entity providers to map HTTP response and request entity bodies.
Entity providers supply mapping services between representations and their associated Java types.
The following list contains the standard types that are supported automatically for entities. You only need to write an entity provider if you are not choosing one of the following standard types.

6. Using @Consumes and @Produces to customize requests and responses
The @Produces annotation is used to specify the MIME media types or representations a resource can produce and send back to the client. If @Produces is applied at the class level, all the methods in a resource can produce the specified MIME types by default. If it is applied at the method level, it overrides any @Produces annotations applied at the class level.
If no methods in a resource are able to produce the MIME type in a client request, the Jersey runtime sends back an HTTP “406 Not Acceptable” error.
The value of @Produces is an array of String of MIME types.
If a resource class is capable of producing more than one MIME media type, the resource method chosen will correspond to the most acceptable media type as declared by the client. More specifically, the Accept header of the HTTP request declared what is most acceptable.

The @Consumes annotation is used to specify which MIME media types of representations a resource can accept, from the client. If @Consumes is applied at the class level, all the response methods accept the specified MIME types by default. If @Consumes is applied at the method level, it overrides any @Consumes annotations applied at the class level.
If a resource is unable to consume the MIME type of a client request, the Jersey runtime sends back an HTTP “415 Unsupported Media Type” error.
The value of @Consumes is an array of String of acceptable MIME types.

7. Extracting Request Parameters
Parameters of a resource method may be annotated with parameter-based annotations to extract information from a request. There are six types of parameters you can extract for use in your resource class: query parameters, URI path parameters, form parameters, cookie parameters, header parameters, and matrix parameters.
Query parameters are extracted from the request URI query parameters, and are specified by using the javax.rs.QueryParam annotation in the method parameter arguments.
@QueryParam and @PathParam can only be used on the following Java types: all primitive types except char, all wrapper class of primitive types except Character, have a constructor that accepts a single String argument, any class with the static method named valueOf(String) that accpets a single String argument, any class with a constructor that takes a single String as a parameter, List<T>, Set<T>, or SortedSet<T>, where T matches the already listed criteria. Sometimes parameters may contain more than one value for the same name. If this is the case, these types may be used to obtain all values.
If @DefaultValue is not used in conjunction with @QueryOaram, and the query parameter is not present in the request, then value will be an empty collection for List, Set, or SortedSet; null for other object types; and the Java-defined default for primitive types.
URI path parametes are extracted from the request URI, and the parameter names correspond to the URI path template variable names specified in the @Path class-level annotation. URI parameters are specified using the javax.ws.rs.PathParam annotation in the method paraeter arguments.
Form parameters extract information from a request representation that is of the MIME media type application/x-www-form-urlencoded and conforms to the encoding specified by HTML forms.
@Context can be used to obtain contextual Java types related to the request or response.

转载一篇介绍RoR上REST概念的文章

发现这篇文章很基础,但是讲的算是比较清楚。先把链接贴上来,有兴趣的大家可以去看看。尽管有点老了。看完之后,再来谈谈自己对于REST的一些想法。

http://www.letrails.cn/archives/6

Updated 16:21, 感觉自己对J2EE的理解还非常的肤浅,非常非常的肤浅。尽管今天看上去顺利地解决了改解决的问题,但是还有几个地方概念是非常模糊的。下面几点是要在接下来几天里着重解决的:

1. Annotation,这个东西尽管看上去很高级,但是实际上在很多很多的场合都是用的非常的多。但是因为我没有深入地看过Spring,对这一概念仍然是十分混淆。

2. JAXB, 无论是DOM还是SAX,都是很久远的技术,现在的流行时JAXB。要说我有多懂这个概念,谈不上。但是发现他的确是非常神奇,到了今天自己才碰上他,说明我对JAVA阵营真的是落寞很久了。

3. Ruby on Rails,记得我还在读大四的时候,这个概念已经开始炒作了。但是没有跟上去,于是现在就落伍了。但是只落伍了两年,还不算太晚。在就业之前,把这些好好地补一补吧。

  • English Version

    • Cannot read Chinese? Please take a look at my English site, hope you can find more you need there!
  • 感谢支持

  • twitter

    facebook

    linkedin

    • You are currently browsing the archives for the REST category.

  • Categories