如何以编程方式确定JAX-RS资源路径?

时间:2013-01-31 09:40:56

标签: java url jax-rs

假设我有一组JAX-RS定位器和子定位器,如下所示:

@Path("/users")
public class UserListResource {
   @Path("/{id}")
   public UserResource getCustomer(@PathParam("id") int id) {
      // Find and return user object
   }
}

public class UserResource {
  @GET
  public String get() {...}
}

例如,ID为UserResource的{​​{1}}对象的路径为5。在我的系统中,我有几种不同的资源。

现在的问题是:服务器如何找出给定资源的路径?我可以通过一些JAX-RS API以编程方式执行此操作,还是必须实现使用反射的代码? (我知道如何做后者,但更喜欢其他方法。)

  • 当我需要知道路径时,我根本没有请求对象。例如,我有一个定时器,它执行一些后台处理,然后更改域模型中的某些实体,然后通知所有客户端有关已更改的实体(包括其路径)。
  • 我知道在请求范围内,我可以注入一个提供此功能的"/users/5"对象,但我需要事先知道路径(告知客户不一定通过JAX-RS资源)。
  • 我不想在其他地方重复路径信息,我也不想为每种资源类型设置一组路径片段常量(在这种情况下为UriInfo和{{1} })。

4 个答案:

答案 0 :(得分:2)

在我阅读您的问题时,您需要构建一个只知道资源类和id参数的URI。

可以使用UriBuilder类完成,如:

UriBuilder builder=UriBuilder.fromResource(UserListResource.class);
URI uri=builder.path(UserListResource.class,"getCustomer").build(5);

它在引擎盖下使用反射,因此重构并不容易,但目前只有它可用。

答案 1 :(得分:1)

总的来说,请注意应用程序的体系结构听起来很奇怪。很难指出,但你问的问题模式正在引发一些关于你如何处理这个问题的危险信号。请注意,如果您正在寻求为您的应用程序创建一个RESTful API,您可能需要停止,请稍微退一步,并重新考虑您要执行的操作。

明确问题......

  

现在的问题是:服务器如何找出给定资源的路径?我可以通过一些JAX-RS API以编程方式执行此操作,还是必须实现使用反射的代码? (我知道如何做后者,但更喜欢其他方法。)

服务器知道路径,因为它始终由用户提供,并用于浏览组成应用程序的资源类集合。如果您需要针对特定​​呼叫的UriInfo实例,则应将其作为特定呼叫的一部分进行注入:

@GET
public String get(@Context UriInfo info) {...}

外部上下文中所需的任何信息(例如,资源的ID是什么)最好在构造期间传递。您可以再次从URL中重新分析它(可从UriInfo获得),但这可能是错误的方法。

否则,如果你做的事情要复杂得多,那么你需要在问题中更加具体。

  
      
  • 当我需要知道路径时,我根本没有请求对象。例如,我有一个定时器,它执行一些后台处理,然后更改域模型中的某些实体,然后通知所有客户端有关已更改的实体(包括其路径)。
  •   
  • 我知道在请求范围内,我可以注入一个提供此功能的UriInfo对象,但我需要事先知道路径(告知客户不一定通过JAX-RS资源)。
  •   

您如何通知客户?通常没有机制将消息从服​​务器推送到客户端,并且客户端通常是防火墙,因此他们无法直接托管服务。

理论上,您可以将(显式地,通过URL)将每个资源与其自己的RSS源关联,如果客户可以监听,则可以选择。您无法强迫客户倾听,但您可以选择这样做。如果你走这条路线,你不需要提前知道UriInfo“,因为位置信息将在关键时刻出现(即在资源创建时),之后你只是指某事你可以控制的。

但这只是一种方法,它增加了很多复杂性;只有在对您的申请至关重要时才会这样做。让客户不时进行民意调查往往更简单。 (请注意,某些类型的修改本质上是非常具有破坏性的;尤其是更改ID或删除资源。不要指望事情能够顺利处理。)

  
      
  • 我不想在其他地方重复路径信息,我也不想为每种资源类型设置一组路径片段常量(在本例中为“/users”和“{ {1}}“)。
  •   

坚韧。在多个地方重复信息,,只要您从单个来源中一​​致地绘制信息,这是一种常见做法。它实际上没有任何问题。

答案 2 :(得分:0)

正如我理解你的问题,你想知道请求进入的路径,但在它到达你的资源之前;您是否愿意使用Servlet过滤器?

仅在2.0

中支持JAX-RS特定过滤器

答案 3 :(得分:0)

为了记录:在我发布问题之后,我更多地考虑了我们的架构并得出结论,发送URLS并不像我想象的那么有用。应用程序必须知道有关应用程序结构的一些详细信息:

  • 继续上面的示例:即使客户端不知道单个用户的URL模式,也必须假设有一个用户列表并知道其URL;它还具有硬编码知识,用于编辑用户等的对话框。

总而言之,尝试告诉客户端(大多数)所需的URL并不值得。相反,我们决定使用自定义API定义文件,其中包含有关资源内容及其URL方案的数据。此文件用于生成以下内容:

  • 具有正确JAX-RS注释的服务器端资源类
  • 其他开发人员编写
  • 的URL方案规范文档
  • 我们自己客户的类(包括URL知道,例如ID为5的用户有URL ...),因此我们不必担心客户端和服务器之间的不一致。

这种方法具有以下优点:

  • 服务器需要从注释中找出URL消失,因为客户端现在可以在收到包含对象ID的通知后自行完成此操作。
  • 我们不必担心客户端和服务器之间的不一致,因为所有信息都来自单一来源。
  • 我们在版本控制下有一个API定义源,可用于验证与旧版本的向后兼容性。

注意: 我可能不会声称生成的API对RESTful Web服务的概念保持“忠实”,但它适用于我们,它借用“实际”REST架构风格的元素应该使API比传统的更清晰,更容易学习合同优先的网络服务。