JAX-RS入门 三 :细节

、若希望一个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会检查这个实例,以决定怎么分发请求。

你可能感兴趣的:(Web,server,jboss,JAX-RS)