一、若希望一个Java类能够处理REST请求,则这个类必须至少添加一个@Path("/")的annotation;对于方法,这个annotation是可选的,如果不添加,则继承类的定义。
二、一个方法上只有添加了某个Http Method的annotation,例如@GET,才有资格处理请求。
三、@Path里的值可以是一个复杂的表达式,例如@Path("{id}") ,其中 {id}表达式代码了一个模板参数;一个模板参数是一个定义在@Path里的通配符,它以 { 开始,中间是一堆字母和数字的混合串(不能包含 / 字符),以} 结尾。又如: @Path("{firstName}-{lastName}") .
四、@Path也支持正则表达式,例如: @Path("{id:\\d+}") ,其中 \\d+ 表示一个数字。格式为: A : B
五、可以自定http method的annotation,具体参考已经有的实现,例如@GET的实现:
Java代码
1. @Target({ElementType.METHOD})
2. @Retention(RetentionPolicy.RUNTIME)
3. @HttpMethod(HttpMethod.GET)
4. public @interface GET {
5. }
其中HttpMethod的实现为:
Java代码
1. @Target({ElementType.ANNOTATION_TYPE})
2. @Retention(RetentionPolicy.RUNTIME)
3. @Documented
4. public @interface HttpMethod {
5.
6. /**
7. * HTTP GET method
8. */
9. public static final String GET="GET";
10. /**
11. * HTTP POST method
12. */
13. public static final String POST="POST";
14. /**
15. * HTTP PUT method
16. */
17. public static final String PUT="PUT";
18. /**
19. * HTTP DELETE method
20. */
21. public static final String DELETE="DELETE";
22. /**
23. * HTTP HEAD method
24. */
25. public static final String HEAD="HEAD";
26. /**
27. * HTTP OPTIONS method
28. */
29. public static final String OPTIONS="OPTIONS";
30.
31. /**
32. * Specifies the name of a HTTP method. E.g. "GET".
33. */
34. String value();
35.}
因此,可以如下自定义新的http 请求方法:
Java代码
1. @Target({ElementType.METHOD})
2. @Retention(RetentionPolicy.RUNTIME)
3. @HttpMethod("LOCK")
4. public @interface LOCK {
5. }
注:请不要试图重写HttpMethodannotation。
六、Path的优先级规则
· 首先检查匹配的字符的个数,匹配的个数越多越优先
· 其次检查内嵌的模板表达式的个数,个数越多越优先
· 最后是非缺省模板表达式的个数;缺省模板即未定义正则表达式的模板
例如以下顺利:
Java代码
1. 1 /customers/{id}/{name}/address
2. 2 /customers/{id : .+}/address
3. 3 /customers/{id}/address
4. 4 /customers/{id : .+}
如果以上匹配不能解决你的问题,那多半是因为你的设计过于复杂,需要重新审视。
七、允许、保留和需要转意的字符
· 所以有 a-z、A-Z、0-9 都被允许
· 所有: _-!.~'()* 都被允许
· 所有: ,;:$&+=?/[]@ 都是保留字符 (需要转意)
· 所有其他字符需要用 % 进行转意;格式为 %HH (%加两个十六进制数)
注:如果Path中uri的表达式包含有需要转意的字符,JAX-RS会自动进行转意;否则会视之为已经进行了URL的encoding。
八、Matrix Param
Matrix Param是一个嵌在URI字符串中的name-value对,例如:
http://example.cars.com/mercedes/e55;color=black/2006
Matrix Param用于修饰特定的片段,如上修饰e55片段;不同于Query Param,用于修饰整个URI资源。
Matrix Param不出现在@Path的表达式中,例如以上URI对应的@Path的表达式可能是:@Path("/e55/{year}")。
但是可以用@MatrixParamannotation来取得Matrix Param的值,例如:@MatrixParam("color")
九、Subresource Locators
SubresourcesLocators是指一个指定了@Path annotation,但未指定HttpMethod的annotation,例如@GET,的Java方法。这个方法返回一个含有JAX-RS annotation的REST Service对象,这个对象知道怎么去分发剩余的请求。
例如:
Java代码
1. @Path("/customers")
2. public class CustomerDatabaseResource {
3. @Path("{database}-db")
4. public CustomerResource getDatabase(@PathParam("database") String db) {
5. // find the instance based on the db parameter
6. CustomerResource resource = locateCustomerResource(db);
7. return resource;
8. }
9. protected CustomerResource locateCustomerResource(String db) {
10. ...
11. }
12.}
其中CustomerResource可能是:
Java代码
1. public class CustomerResource {
2. private Map<Integer, Customer> customerDB =
3. new ConcurrentHashMap<Integer, Customer>();
4. private AtomicInteger idCounter = new AtomicInteger();
5. @POST
6. @Consumes("application/xml")
7. public Response createCustomer(InputStream is) {
8. ...
9. }
10. @GET
11. @Path("{id}")
12. @Produces("application/xml")
13. public StreamingOutput getCustomer(@PathParam("id") int id) {
14. ...
15. }
16. @PUT
17. @Path("{id}")
18. @Consumes("application/xml")
19. public void updateCustomer(@PathParam("id") int id, InputStream is) {
20. ...
21. }
22.}
因为CustomerResource 并不打算做一个Service暴露,所以在类上没有添加@Path的annotation。
十、完全动态分发
所谓完全分发,就是实现类可以是任意类,例如上面的CustomerDatabaseResource的getDatabase()方法的实现可以改为:
Java代码
1. @Path("/customers")
2. public class CustomerDatabaseResource {
3. protected CustomerResource europe = new CustomerResource();
4. protected FirstLastCustomerResource northamerica =
5. new FirstLastCustomerResource();
6.
7. @Path("{database}-db")
8. public Object getDatabase(@PathParam("database") String db) {
9. if (db.equals("europe")) {
10. return europe;
11. }
12. else if (db.equals("northamerica")) {
13. return northamerica;
14. }
15. else return null;
16. }
17.}
这里返回值是一个Object,已经不再局限于CustomerResource类了。JAX-RS会检查这个实例,以决定怎么分发请求。