、若希望一个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的实现:

  1. @Target({ElementType.METHOD})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @HttpMethod(HttpMethod.GET)
  4. public @interface GET {
  5. }

其中HttpMethod的实现为:

  1. @Target({ElementType.ANNOTATION_TYPE})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface HttpMethod {
  5. /**
  6. * HTTP GET method
  7. */
  8. public static final String GET="GET";
  9. /**
  10. * HTTP POST method
  11. */
  12. public static final String POST="POST";
  13. /**
  14. * HTTP PUT method
  15. */
  16. public static final String PUT="PUT";
  17. /**
  18. * HTTP DELETE method
  19. */
  20. public static final String DELETE="DELETE";
  21. /**
  22. * HTTP HEAD method
  23. */
  24. public static final String HEAD="HEAD";
  25. /**
  26. * HTTP OPTIONS method
  27. */
  28. public static final String OPTIONS="OPTIONS";
  29. /**
  30. * Specifies the name of a HTTP method. E.g. "GET".
  31. */
  32. String value();
  33. }

因此,可以如下自定义新的http 请求方法:

  1. @Target({ElementType.METHOD})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @HttpMethod("LOCK")
  4. public @interface LOCK {
  5. }

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

、Path的优先级规则

  • 首先检查匹配的字符的个数,匹配的个数越多越优先
  • 其次检查内嵌的模板表达式的个数,个数越多越优先
  • 最后是非缺省模板表达式的个数;缺省模板即未定义正则表达式的模板

例如以下顺利:

  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对象,这个对象知道怎么去分发剩余的请求。

例如:

  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可能是:

  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()方法的实现可以改为:

  1. @Path("/customers")
  2. public class CustomerDatabaseResource {
  3. protected CustomerResource europe = new CustomerResource();
  4. protected FirstLastCustomerResource northamerica =
  5. new FirstLastCustomerResource();
  6. @Path("{database}-db")
  7. public Object getDatabase(@PathParam("database") String db) {
  8. if (db.equals("europe")) {
  9. return europe;
  10. }
  11. else if (db.equals("northamerica")) {
  12. return northamerica;
  13. }
  14. else return null;
  15. }
  16. }

这里返回值是一个Object,已经不再局限于CustomerResource类了。JAX-RS会检查这个实例,以决定怎么分发请求。

 

JAX-RS入门 三 :细节的更多相关文章

  1. 脑残式网络编程入门(三):HTTP协议必知必会的一些知识

    本文原作者:“竹千代”,原文由“玉刚说”写作平台提供写作赞助,原文版权归“玉刚说”微信公众号所有,即时通讯网收录时有改动. 1.前言 无论是即时通讯应用还是传统的信息系统,Http协议都是我们最常打交 ...

  2. 转 Python爬虫入门三之Urllib库的基本使用

    静觅 » Python爬虫入门三之Urllib库的基本使用 1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器 ...

  3. redis入门(三)

    目录 redis入门(三) 目录 前言 事务 原理 Lua脚本 安装 脚本命令 集群搭建工具 redis-trib.rb redis官方集群搭建 集群横向扩展 故障转移 redis管理 参考文档 re ...

  4. 【原创】NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战

    前言 本文将演示一个iOS客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo.服务端将分别用MINA2和Netty4进行实现,而通信时服务端你只需选其一就行了.同 ...

  5. Swift语法基础入门三(函数, 闭包)

    Swift语法基础入门三(函数, 闭包) 函数: 函数是用来完成特定任务的独立的代码块.你给一个函数起一个合适的名字,用来标识函数做什么,并且当函数需要执行的时候,这个名字会被用于“调用”函数 格式: ...

  6. Thinkphp入门三—框架模板、变量(47)

    原文:Thinkphp入门三-框架模板.变量(47) [在控制器调用模板] display()   调用当前操作名称的模板 display(‘名字’)  调用指定名字的模板文件 控制器调用模板四种方式 ...

  7. DevExpress XtraReports 入门三 创建 Master-Detail(主/从) 报表

    原文:DevExpress XtraReports 入门三 创建 Master-Detail(主/从) 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用 ...

  8. 微服务(入门三):netcore ocelot api网关结合consul服务发现

    简介 api网关是提供给外部调用的统一入口,类似于dns,所有的请求统一先到api网关,由api网关进行指定内网链接. ocelot是基于netcore开发的开源API网关项目,功能强大,使用方便,它 ...

  9. 3.Python爬虫入门三之Urllib和Urllib2库的基本使用

    1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器解释才呈现出来的,实质它是一段HTML代码,加 JS.CSS ...

  10. C#基础入门 三

    C#基础入门 三 类 类使用class关键字进行声明,前面加一个访问修饰符,public class car{} 访问修饰符:修师傅可以用来修饰类和类成员等,控制它们的可见度 修饰符关键字分别为:pu ...

随机推荐

  1. Spark Streaming揭秘 Day8 RDD生命周期研究

    Spark Streaming揭秘 Day8 RDD生命周期研究 今天让我们进一步深入SparkStreaming中RDD的运行机制.从完整的生命周期角度来说,有三个问题是需要解决的: RDD到底是怎 ...

  2. WPF简单的口算案例

    前几天在博客园,看到有博友利用Winform做了一个口算案例,于是我想把它移植在WPF程序中.Winform程序:http://www.cnblogs.com/ImYZF/p/3345452.html ...

  3. sql表连接left join,right join,inner join三者之间的区别

    sql表连接left join,right join,inner join区别 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 (以左表数据为基准,不足补为NULL) ...

  4. Lua基础之Function

    概述:1.定义和调用 2.多返回值3.可变参数 原文地址 http://blog.csdn.net/dingkun520wy/article/details/50275387 1.定义和调用 函数,在 ...

  5. Xcode常用快捷键及代码格式刷(缩进)方法-b

    Xcode版本:4.5.1 一.总结的常用命令: 隐藏xcode command+h 退出xcode command+q 关闭窗口 command+w 关闭所有窗口 command+option+w ...

  6. MongoDB的C#驱动基本使用

    转载:http://www.cnblogs.com/wilber2013/p/4175825.html MongoDB的官方C#驱动可以通过 这个链接 得到.链接提供了.msi和.zip两种方式获取驱 ...

  7. 一个好用且方便的FastCgi C++库 - FastCgi++

    不知道你是不是曾经发愁过使用FastCgi库来使用C++开发Fastcgi程序繁琐而且会与C++ STL代码产生冲突的地方,或者你还是习惯了cout而不是pringf,那这篇文章就可以了解到一个使用的 ...

  8. TCP/IP长连接和短连接

    http://www.cnblogs.com/bigwalnut/articles/2129070.html TCP/IP通信程序设计的丰富多样性 刚接触TCP/IP通信设计的人根据范例可以很快编出一 ...

  9. CSS 命名规范及标题供参考与学习

    一.CSS 命名规范   XHTML-CSS写作建议 所有的xhtml代码小写 属性的值一定要用双引号("")括起来,且一定要有值 每个标签都要有开始和结束,且要有正确的层次 空元 ...

  10. 【BZOJ 2300】 2300: [HAOI2011]防线修建 (动态凸包+set)

    2300: [HAOI2011]防线修建 Description 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上 ...