Java Web有很多成熟的框架,主要可以分为两类Web Application和Web Services。用于Web Application的框架包括官方的Servlet/JSP, JSTL/JSF以及第三方Struts/Spring MVC(action-based)。Web Services的项目又可以分为基于XML的(SOAP/WSDL)的和基于JSON的,Java Communitiy为这两种方式都定义了标准,Java EE5引入了JAX-WS(Java API for XML Web Services)-JSR224,Java EE6引入了JAX-RS(Java API for RESTful Web Services)-JSR331。RESTful Service由于轻量,好测试,有弹性等特点,越来越受欢迎。Jersey,RESTEasy都是JAX-RS标准的具体实现。
Rest(representational state transfer, 表现层状态转化)是一种渐渐变成Web设计主流的设计理念,最早由Roy Thomas Fielding(HTTP1.0/1.1协议主要设计者之一,Apache作者之一,Apache基金会第一任主席)在2000年的博士论文中提出。
示例,例如有一个图书管理的Restful服务,该服务将会呈现为下面的形式(先不用考虑服务具体如何实现的):
资源:
系统中所有书籍的集合是一个资源,可以用URL http://www.example.com/books 来表示 系统中有本书id为1000,这本书也是一个资源,可以用URL http://www.example.com/books/1000 来表示
操作:
如果想要查看书集中包含哪些具体的书,可以使用GET方法请求集合资源:
GET http://www.example.com/books 如果想要查看id为1000这本书的详细信息,可以GET方法请求单本书的资源:
GET http://www.example.com/books/1000 如果想新增一本书,可以使用POST方法请求集合资源(假如成功后自动生成id为1001):
POST http://www.example.com/books { {‘name‘ : ‘ good book‘}, {‘price‘: 100}} 如果想修改一本书,可以使用PUT方法请求书的资源:
PUT http://www.example.com/books/1001 { {‘price‘: 98} } 如果想删除id为1000的书,可以使用DELETE方法请求单本书的资源:
DELETE http://www.example.com/books/1000
例如/posts/show/1 应该改为/posts/1 用GET方法表明是show操作。
例如 transfer动作 可以修改为POST /transaction from=1&to=2&amout=100.00
例如
http://www.example.com/app/1.0/foo
http://www.example.com/app/2.0/foo
在请求头中区分:
Accept: vnd.example-com.foo+json; version=1.0
Accept: vnd.example-com.foo+json; version=2.0
JAX-RS和所有JAVA EE的技术一样,只提供了技术标准,允许各个厂家有自己的实现版本,实现版本有:RESTEasy(JBoss), Jersey(Sun提供的参考实现), Apache CXF, Restlet(最早的REST框架,先于JAX-RS出现), Apache Wink。JAX-RS基于JavaEE的Servlet。标准中定义的注解大大简化资源位置和参数的描述,仅仅使用注解就可以将一个POJO java类封装成一个Web资源。JAX-RS也有类似于Spring依赖注入的方式,减少类之间的耦合度。
JAX-RS标准的一个简单RESTful Web Service示例,例如有一个greeter的资源,URI为http://localhost:8080/greeter/
@Path("/greeter") public class GreeterResource { @GET @Path("/{name}") public String sayHello(@PathParam("name") String name) { return "Hello, " + name; }
@DELETE @Path("/{name}") public String sayBye(@PathParam("name") String name) { return "Bye, " + name;
}
}
使用GET方法请求该资源 (http://localhost:8080/greeter/tom)
将得到输出: Hello, tom
使用DELETE方法请求该资源 (http://localhost:8080/greeter/lily)
将得到输出: Bye, lily
如果把上面的资源类定义为接口, 将REST服务的定义和实现分离是一种更好的实现方式。代码更简洁清晰,后期修改也更方便。
@Path
若希望一个Java类能够处理REST请求,则这个类必须至少添加一个@Path("/")的annotation;对于方法,这个annotation是可选的,如果不添加,则继承类的定义。
Path里的值可以是复杂表达式,例如@Path("{id}"),其中的{xxx}表示一个模板参数,模板参数是定义在@Path里的通配符,它以 { 开始,中间是一堆字母和数字的混合串(不能包含 / 字符),以} 结尾。又如: @Path("{firstName}-{lastName}")
Path也支持正则表达式,例如:@Path("{id: \\d+}")
优先级检查规则(如果这样的规则还不能解决问题,那就是设计的过于复杂了):
例如
Path的字符(如果Path中的表达式包含需要转义的字符,JAX-RS会自动进行转义;否则会认为以及进行过URL Encoding)
子资源定位符(Subresource Locators),一个指定了@Path注解但未指定HttpMethod注解的方法,该方法可以返回另一个资源类对象,让这个对象接着分发和处理请求子资源的请求。子资源类并不需要作为服务对外暴露,所以类上可以不用加@Path注解。
@Path("/customers") public class CustomerResource { ...... @Path("{database}-db") public CustomerResource getDatabase(@PathParam("database") String db) { // find the instance based on the db parameter CustomerResource resource = locateCustomerResource(db); return resource; } protected CustomerResource locateCustomerResource(String db) { ... }
...... } public class CustomerResource { @GET @Path("{id}") @Produces("application/xml") public StreamingOutput getCustomer(@PathParam("id") int id) { ... } @PUT @Path("{id}") @Consumes("application/xml") public void updateCustomer(@PathParam("id") int id, InputStream is) { ... } }
完全动态分发。上面的例子中指定了@Path注解但未指定HttpMethod注解的方法,该方法可以返回任何类对象。JAX-RS会检查这个对象并自动决定如何分发和处理请求。
@Path("{database}-db") public Object getDatabase(@PathParam("database") String db) {
if(db.equals("europe"))
return locateCustomerResource(db); return "not supported db"; }
@GET, @PUT, @POST, @DELETE 方法可以处理的HTTP请求方法类型
一个方法只有添加了请求方法注解,才能处理请求。
可以自定义请求方法注解,但不要重写HttpMethod定义的注解(GET,POST,PUT,DELETE,HEAD,OPTIONS)
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @HttpMethod("LOCK") public @interface LOCK { }
@Produces 返回的MIME媒体类型,例如application/xml
@Consumes 可接受请求的MIME媒体类型,例如application/xml
@PathParam, @QueryParam, @HeaderParam, @CookieParam, @MatrixParam, @FormParam 参数来自HTTP请求的不同位置
Matrix Param是一个嵌入在URI字符串中的name:value对,修饰Path中的一个片段。例如http://example.cars.com/mercedes/e55;color=black/2006。MMatrix Parm对@Path表达式是透明的,这个例子中还是使用@Path("/e55/{year}")。但是可以用@MatrixParam 注解将MatrixParam的值注入到方法参数中。
例如@GET public String getInfo(@MatrixParam("color") String color){...}
后面的文章中将介绍JAX-RS标准的一个实现:Jersey。
http://www.codedata.com.tw/java/java-restful-1-jersey-and-jax-rs/
http://www.ruanyifeng.com/blog/2011/09/restful
http://liugang594.iteye.com/category/218423
原文:http://www.cnblogs.com/pixy/p/4838268.html