• 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. }  

    注:请不要试图重写HttpMethod annotation。

    、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}")。

    但是可以用@MatrixParam annotation来取得Matrix Param的值,例如:@MatrixParam("color")

    、Subresource Locators 

    Subresources Locators是指一个指定了@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会检查这个实例,以决定怎么分发请求。

     
    我喜欢程序员,他们单纯、固执、容易体会到成就感;面对压力,能够挑灯夜战不眠不休;面对困难,能够迎难而上挑战自我。他 们也会感到困惑与傍徨,但每个程序员的心中都有一个比尔盖茨或是乔布斯的梦想“用智慧开创属于自己的事业”。我想说的是,其 实我是一个程序员
  • 相关阅读:
    Markdown基本语法
    Linux之更好的使用Bash
    博客园-使用的模板
    井字棋的最优策略竟是先占角!
    Highcharts入门+Highcharts基础教程,【非常值得学习的资料】
    Python4周 入职培训的过程
    Linux系统入门学习:在CentOS上安装phpMyAdmin
    WeCenter程序安装
    js正则表达式语法
    Sublime text2如何设置快捷键让编写的HTML文件在浏览器预览?
  • 原文地址:https://www.cnblogs.com/kms1989/p/5822970.html
Copyright © 2020-2023  润新知