当前位置: 首页 > 面试题库 >

在基于JAX-RS的实现中轻松进行REST资源版本控制?

微生毅
2023-03-14
问题内容

REST资源版本控制的最佳做法是将版本信息放入HTTP请求的Accept / Content-Type标头中,而URI保持不变。

这是对REST API的示例请求/响应,用于检索系统信息:

==>
GET /api/system-info HTTP/1.1
Accept: application/vnd.COMPANY.systeminfo-v1+json

<==
HTTP/1.1 200 OK
Content-Type: application/vnd.COMPANY.systeminfo-v1+json
{
  “session-count”: 19
}

请注意,版本是在MIME类型中指定的。

这是版本2的另一个请求/响应:

==>
GET /api/system-info HTTP/1.1
Accept: application/vnd.COMPANY.systeminfo-v2+json

<==
HTTP/1.1 200 OK
Content-Type: application/vnd.COMPANY.systeminfo-v2+json
{
  “uptime”: 234564300,
  “session-count”: 19
}

有关更多说明和示例,请参见http://barelyenough.org/blog/tag/rest-
versioning/

是否可以在基于Java的JAX-RS的实现中轻松实现这种方法,例如Jersey或Apache CXF?

目标是拥有多个具有相同@Path值的@Resource类,但是根据MIME类型中指定的实际版本来服务请求?

我研究了JAX-
RS的整体知识,特别是Jersey的内容,没有找到任何支持。泽西岛没有机会用相同的路径注册两个资源。需要实现对WebApplicationImpl类的替换以支持该替换。

你能建议点什么吗?

注意:同一资源的多个版本需要同时可用。 新版本可能会引入不兼容的更改。


问题答案:

JAX-RS通过Accept标头将其分配给以@Produces注释的方法。因此,如果您希望JAX-
RS进行调度,则需要利用此机制。如果没有任何额外的工作,则必须为要支持的每种媒体类型创建一个方法(和提供程序)。

没有什么可以阻止您使用几种基于媒体类型的方法来全部调用一个通用方法来完成这项工作的,但是每次添加新的媒体类型时,您都必须对其进行更新并添加代码

一种想法是添加一个过滤器,以“规范化”您的Accept标头,专门用于分派。也就是说,可能是您:

Accept: application/vnd.COMPANY.systeminfo-v1+json

并将其转换为:

Accept: application/vnd.COMPANY.systeminfo+json

同时,您提取版本信息以供以后使用(也许在请求中,或者在其他临时机制中)。

然后,JAX-RS将分派到处理“ application / vnd.COMPANY.systeminfo + json”的单个方法。

然后,该方法使用“带外”版本控制信息来处理处理中的详细信息(例如,选择适当的类以通过OSGi加载)。

接下来,然后使用适当的MessageBodyWriter创建一个Provider。JAX-RS将为application /
vnd.COMPANY.systeminfo +
json媒体类型选择提供程序。由MBW决定实际的媒体类型(再次基于该版本信息)并创建正确的输出格式(同样,也许分派到正确的OSGi加载类)。

我不知道MBW是否可以覆盖Content-Type标头。如果没有,那么您可以委托较早的过滤器在出路时为您重写该部分。

这有点令人费解,但是如果您想利用JAX-RS调度,而不是为每种类型的媒体类型创建方法,那么这是可行的方法。

编辑以回应评论:

是的,从本质上讲,您希望JAX-RS基于Path和Accept类型将其分派到适当的类。JAX-
RS不太可能开箱即用,因为这是一个边缘情况。我没有看过任何JAX-RS的实现,但是您可以通过在基础结构级别上调整其中一个来完成您想要的事情。

可能的另一种侵入性较小的方法是使用来自Apache世界的古老技巧,并简单地创建一个过滤器,该过滤器根据Accept标头重写您的路径。

因此,当系统得到:

GET /resource
Accept: application/vnd.COMPANY.systeminfo-v1+json

您将其重写为:

GET /resource-v1
Accept: application/vnd.COMPANY.systeminfo-v1+json

然后,在您的JAX-RS类中:

@Path("resource-v1")
@Produces("application/vnd.COMPANY.systeminfo-v1+json")
public class ResourceV1 {
    ...
}

因此,您的客户端获得了正确的视图,但是JAX-
RS正确地调度了您的类。唯一的另一个问题是,如果您的类看的话,它们将看到修改后的Path,而不是原始路径(但是,如果您愿意,您的过滤器可以将该请求中的内容作为参考)。

它不是理想的,但是(大部分)是免费的。

这是一个现有的过滤器,可能会做您想做的事情,如果没有,它可能会启发您自己做。



 类似资料:
  • 问题内容: 在常规的Web应用程序中,我可以为各种路径(例如,身份验证,授权,错误,日志记录等)分配一系列过滤器。 好处是我编写servlet时专注于核心功能,而不必担心基础结构方面。我可以编写正交的,跨领域的过滤器以进行身份​​验证,授权等。然后,可以将它们编织到web.xml中。查看web.xml足以确保我的应用程序中没有漏洞。 在JAX-RS或Jersey中有可能吗?如果没有,我最好的选择是

  • 为了测试,我尝试下面的代码过滤包含用户的url参数,但是它没有在未经授权的情况下中止请求。最重要的是,我需要以这样的方式来实现它,即只有更新和删除需要用各自的用户名和密码来授权。其他我只是不想过滤的东西。我有一个user类,它具有username和password(加密)属性。因此,如果url包含Users/{userID}的PUT或delete方法,我希望它使用特定用户的用户名和密码进行验证。我

  • 问题内容: 根据文档, “客户端是管理客户端通信基础结构的重量级对象。初始化和处理客户端实例可能是一项相当昂贵的操作。因此,建议在应用程序中仅构造少量的客户端实例。” 好的,我试图将客户端本身和WebTarget实例缓存在一个静态变量中,在多线程环境中调用someMethod(): 但是有时(并非总是)我会例外: 无效使用BasicClientConnManager:连接仍被分配。在分配另一个之前

  • service.java: sqlDataProvider.java: 如果在Glassfish服务器中部署此servlet并执行请求,将引发以下异常: 亲切地问候帕斯卡

  • 本章呈现 JAX-RS 核心概念-资源和子资源的概述。 JAX-RS 2.0 的 JavaDoc 文档 可以在这里 找到。 JAX-RS 2.0 规范草案可以在这里 找到。

  • 问题内容: 我一直在尝试使用NetBeans Ide创建一个简单的Restful WebService。 我的Java EE版本是:Java EE 7 Web。 我创建了一个新的Java Web应用程序,设置此ContexPath: 。 现在,运行我的应用程序,浏览器在以下位置显示我的页面: 因此,一切正常。 然后,我尝试使用RESTful Web服务向导创建一个简单的Restful资源。 因此,