1. RESTful
关于什么是RESTful网上已经有很多资料描述,比如这里以及原文. 而这里说到的JAXRS只是JAVA的一种实现
2. JAX-RS
目前有两个版本的规范:JSR311和JSR339 .查看具体的规范文档,发现提供了JSR339与JSR311相比提供了ClientAPI、Filter and Interceptor、Asynchronous Process等特性。下面简单介绍下需要涉及的要点
resources及入参
在RESTful中将网络中的任何资源描述为Resources,而JAX-RS中则采用特定的annotation来标识该java类作为一个网络资源可供其他访 问。同样resource类也有生命周期和上下文环境的概念,一般来说当客户端发起一个请求该resource类就实例化,当在正确的response后 就进入GC的环节。下面是一个POJO是如何成为一个resource的,前面说了是依靠一系列的annotation
@Path标注javabean为resource,一个resource至少需要一个@Path,可继承
@Path("/rest")
public class RESTPathService {
/**
*\\/rest/meth1
* @return
* @author Administrator
* @date 2013-3-9
*/
@GET
@Path("/meth1")
public Response meth1() {
return Response.status(200).entity("/rest/meth1 is called").build();
}
/**
* \\/rest/meth2/2 OK
* \\/rest/meth2/a Error
* @return
* @author Administrator
* @date 2013-3-9
*/
@GET
@Path("/meth2/{id : \\d+}")//id必须为数字
public Response meth2() {
return Response.status(200).entity("/rest/meth2 is called").build();
}
}
@PathParam标注path template变量为方法参数
@Path("/rest")
public class RESTPathParamService {
@GET
@Path("/meth1/{name}")
public Response meth1(@PathParam("name") String name2) {
return Response.status(200).entity("/rest/meth1/" + name2 + " is called").build();
}
@GET
@Path("/meth2/{name}/{id : \\d+}")
public Response meth2(@PathParam("name") String name2, @PathParam("id") Integer id) {
return Response.status(200).entity("/rest/meth2/" + name2 + "/" + id + " is called").build();
}
}
@QueryParam标注查询变量为方法参数,如?name=robin&age=30将name、age作为方法参数
@Path("/rest")
public class RESTQueryParamService {
/**
* \\/rest/meth1?name=robin&age=30
*
* @param name
* @param age
* @return
* @author Administrator
* @date 2013-3-9
*/
@GET
@Path("/meth1")
public Response meth1(@QueryParam("name") String name, @QueryParam("age") Integer age) {
return Response.status(200).entity("[name=" + name + ", age=" + age + "]").build();
}
/**
* \\/rest/meth2?name=robin&age=30
*
* @param info
* @return
* @author Administrator
* @date 2013-3-9
*/
@GET
@Path("/meth2")
public Response meth2(@Context UriInfo info) {
return Response
.status(200)
.entity("[name=" + info.getQueryParameters().getFirst("name") + ", age="
+ info.getQueryParameters().getFirst("age") + "]").build();
}
/**
* \\/rest/meth3?username=robin&password=123123
*
* @param info
* @return
* @author Administrator
* @date 2013-3-9
*/
@GET
@Path("/meth3")
public Response meth3(@QueryParam("") User user) {
return Response.status(200).entity("[name=" + user.getUsername() + ", password=" + user.getPassword() + "]")
.build();
}
}
@MatrixParam与QueryParam类似,还有FormParam,支持将参数封装为bean对象作为方法参数传入
@Path("/rest")
public class RESTMatrixParamService {
/**
* \\/rest/meth1;name=robin;age=30;
*
* @param name
* @param age
* @return
* @author Administrator
* @date 2013-3-9
*/
@GET
@Path("/meth1")
public Response meth1(@MatrixParam("name") String name, @MatrixParam("age") Integer age) {
return Response.status(200).entity("[name=" + name + ", age=" + age + "]").build();
}
}
@CookieParam 获取cookie作为参数
@HeaderParam 获取header作为参数
@Path("/rest")
public class RESTHeaderParamService {
@GET
@Path("/meth1")
public Response meth1(@HeaderParam("user-agent") String userAgent) {
return Response.status(200).entity("[user-agent=" + userAgent + "]").build();
}
@GET
@Path("/meth2")
public Response meth2(@Context HttpHeaders headers) {
return Response.status(200).entity("[user-agent=" + headers.getRequestHeader("user-agent").get(0) + "]")
.build();
}
}
@Context注入资源的实例,如HttpHeader、UriInfo、Request等,见上面的例子
@DefaultValue标注一个参数的默认值
@Encoded参数编码
methods
在resource类中用来标识该方法作为一个request的HTTP请求方法,只有POJO中的public方法才能暴露为一个resource方法。通常与@Path一起 使用。该类的annotation与HTTP方法一致:@GET,@POST,@PUT,DELETE,HEAD和OPTIONS.
返回类型
一个resource方法可以返回void,Response,GenericEntity以及其他任何的Java类型:
void 返回空的entry body和204的状态码
Response 可自行设定返回的状态码,如果未指定会根据response中的entry来判断,如果entry为null状态码为204,否则为200:
Response.status(200).entity(Object entry).build()
GenericEntity 实际上是对返回对象的简单包装:public class GenericEntity<T>同样对状态码和entry的关系遵循上面Response的原则
Other:一个实体对象即一个普通的POJO对象,为空状态码204,不为空状态码200
异常处理
简单的说异常可以实现WebApplicationException或者采用Response返回特定的错误码如500
uri模板
一个root resource类用@Path
我们常用@Path标注一个POJO类,来表示该类作为一个root resource,而其他的相对路径我们可以标注在方法或者子类的resource中。在annotation的值是自动编码的,如
@Path("widget list/{id}")
@Path("widget%20list/{id}")
是等同的。同时也可以支持正则的请求路径:
@Path("widgets/{path:.+}") -->widgets/a/aa或widgets/a
@Path("widgets/{id: \\d+}") -->widgets/12
MediaType
在JAX-RS中处理请求和相应的mediatype主要用@Consumes和@Produces可用在resource类或方法上
@Produces("text/html")
如果任何类型都支持
@Produces("*/*")
或者多个
@Produces("application/xml", "application/json")