RESTful Java Web Services

转:http://blog.sina.com.cn/s/blog_628b45090100rnds.html

RESTful

rest简介

rest即RepresentationalStateTransfer,翻译成中文,表述性状态转移,是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。

rest提出了一些设计概念和准则

1.网络上所有的事物都被抽象为资源(resource)

2.每个资源对应唯一一个资源标识(resourceidentifier)

3.通过通用的连接器接口(genericconnectorinterface)对资源进行操作

4.对资源的各种操作不会改变资源标识

5.所有操作无状态(stateless)

对于常见的网络应用,resourceidentifier是url,genericconnectorinterface是HTTP,第4条准则就是我们常说的url不变性。

这些概念中的resouce最容易使人产生误解,resource所指的并不是数据,而是数据+特定的表现形式(representation)。对于不同的链接数据可能是一样的。

HTTP把对一个url的操作限制在了4个之内:GET、POST、PUT和DELETE,操作方法受到架构的限制,这样能够简化开发。

rest能够提高系统的可伸缩性,是因为它强制所有的操作都是stateless的,这样就没有context(上下文)的约束,如果要做分布式,做集群就不需要考虑context。

如何使用rest

可以通过url来设计系统的结构。根据rest,每个url都代表一个resource,而整个系统就是由这些resource组成的。因此,如果url是设计良好的,那么系统的结构也是设计良好的。我们可以先设计出我们认为合理的url。这些url甚至不能连接到任何page或action,但是它们直观地告诉我们:系统对用户的访问接口就是这样的。根据这些url,我们可以很方便地设计系统的结构。

使用REST的关键是如何抽象资源,抽象得越精确,对REST的应用就越好。因此,如何改变我们目前根深蒂固的基于action的思想是最重要的。

静态网站符合RESTful服务,普通的动态网站不符合RESTful服务。动态网站一般要保存session或者cookie,不符合无状态的连接要求。

对于同一个资源的访问,返回的数据类型有多种,image,text,file,XMLstream,JSONstream,但必须能够通过相同的URI来访问。即对于相同的URI,访问的资源是确定的,但返回的数据格式是可以不同的。

任何资源都是可寻址的

客户端与服务端只能通过URI来交换数据。URI是核心,用来管理service,装载资源,决定数据传输格式,发送响应消息。

GET方法用于检索资源,处理流程如下

POST方法用于创建资源

PUT方法用于更新资源

DELETE方法用于删除资源

RESTful风格的webservice各种实现都比较简单,它放弃了SOAP/WSDL协议,而坚持使用标准的计算机硬件以及XML和HTTP网络协议。

RESTWebServicesDesign

1.Analyzetheresourcerequirements.

2.Designtherepresentationforourresources.

3.IdentifytheURIs.

4.Worryaboutimplementationtechnologies.

1.Requirementgathering

2.Resourceidentification

3.Resourcerepresentationdefinition

4.URIdefinition

这个过程不是静态的,而是围绕资源而进行的迭代过程。比如进行到第四步,又发现了一个没有定义好的资源,此时又要重复前面资源定义的步骤。

URI(即API)设计有三个原则:Logical(符合逻辑),Hierarchical(分层的),AsPermanentaswecan(尽力持久不变)。

Jersey框架

最大特点使用注释(Annotations),这就允许Jsrseyresources可以是一个简单的Java类。

URIs每个Jerseyresource都有一个相对应的URI。这是由@Path定义的。

@Path("/users")

publicclassUsersResource{

}

URIs中还可以定义参数

@Path("/users/{username}")

publicclassUserResource{

}

还可以用正则表达式限制参数的值

@Path("/users/{username:[a-zA-Z]}")

publicclassUserResource{

}

以上代码限制变量username只能包含大小写字母。

HTTPmethods

@GET

@POST

@PUT

@DELETE

Relativepathsinmethods

如果要使用URI“/users/messages”,可以像下面这样。类中的方法handleGETRequestMessage()使用了相对路径“/messages”,完整路径为“/users/messages”

@Path("/users")

publicclassUserResource{

@GET

publicStringhandleGETRequest(){

}

@GET

@Path("/messages")

publicStringhandleGETRequestMessages(){

}

}

URIvariables

@PathParam

@Path("/users/{username}")

publicclassUserResource{

@GET

publicStringhandleGET(@PathParam("username")Stringusername){

//Wecanuseusernamehoweverwelike...

}

@POST

publicStringhandlePOST(@PathParam("username")Stringusername){

}

@PUT

publicStringhandlePUT(@PathParam("username")Stringusername){

}

@DELETE

publicStringhandleDELETE(@PathParam("username")String

username){

}

}

四种方法都可以使用URI中的参数,但在POST方法中一般不使用。

Inputandoutputformats

@Consumers

这个注释只用在@POST和@PUT方法。它告诉服务器用哪个方法来处理请求。客户端一般设置“Content-Type”HTTP头,来指明实体中的数据格式。使用方法如下

@Path("/users")

publicclassUserResource{

@PUT

@Consumes("application/xml")

publicvoidupdateUser(Stringrepresentation){

}

}

在这个例子中,updateUser()方法指明接受“application/xml”类型的数据,该数据存储在String变量representation中,以参数的形式存在,名字可以随意。

@Produces

这个注释可以用在@GET,@POST,和@PUT方法。它让框架知道要向客户端(client)发送何种格式的数据。客户端在“Accept”HTTP头中指定需要的数据格式。

@Path("/users")

publicclassUserResource{

@GET

@Produces("application/xml")

publicStringgetXML(Stringrepresentation){

}

@GET

@Produces("application/json")

publicStringgetJSON(Stringrepresentation){

}

}

Parameters

@FormParam

处理HTMLforms数据格式。例如,如下的一个HTML表单

<formaction="/users"method="POST">

Name:<inputtype="text"name="name">

Age:<inputtype="text"name="age">

Address:<inputtype="text"name="address">

</form>

Weusethe@FormParamannotationasfollows:

@Path("/users")

publicclassUserResource{

@POST

@Consumes("application/x-www-form-urlencoded")

publicvoidaddUser(@FormParam("name")Stringname,@FormParam("age")intage,@FormParam

("address")Stringaddress){

}

}

运行时的问题:

客户端访问服务的时候,如果用GET方法访问,需要设置Accept头,即表明希望收到何种格式的数据。如果设置成了服务器不能识别的格式,则会出错。如果客户端没有设置Accept头,则服务器会把请求提交给在资源类中找到的第一个符合要求的方法,即除了@Produces不符合,其它的都符合。

因为所有资源都是无状态的,所以需要权限验证的资源操作,每次都需要附加上必要的验证信息。比如使用用户名以及密码验证的每次都需要将用户名以及密码加在提交的信息之中。有个问题,GET方法一般不能加入用户名以及密码的验证字段,那如何验证呢?

相关推荐