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

注册MessageBodyReader和MessageBodyWriter实现的适当位置是什么?

叶光华
2023-03-14
问题内容

我已经实现的javax WS RS API
MessageBodyReader用于com.ca.tas.crypto.cmp.client.GeneralPKIMessageJaxRsReaderMessageBodyWriterorg.bouncycastle.asn1.cmp.PKIMessage这样我就可以在轻松的使用类型CMP过HTTP
REST API。现在,要注册我创建的META- INF/services/javax.ws.rs.ext.Providers文件的类型并将类名放在此处。一切正常,我可以使用API​​进行REST调用,但以下情况除外:

  • IntelliJ IDEA(或我已安装到其中的插件之一)抱怨

注册的扩展名应实现javax.ws.rs.ext.Providers

在文件的两行上。根据我在Internet上某处找到的资源,我认为添加@Provider@Produces("application/pkixcmp")注释就足够了。

  • 我注意到FasterXML Jackson具有META-INF/services/javax.ws.rs.ext.MessageBodyReaderMETA-INF/services/javax.ws.rs.ext.MessageBodyWriter文件,并且这些文件似乎也注册了一个实现接口的类。

所以我的问题是:

  • 抱怨我没有实施IntelliJ IDEA是正确还是错误javax.ws.rs.ext.Providers

  • 要注册MessageBodyReaderMessageBodyWriter实现的正确文件是什么?

  • 什么能启发我这一点的权威性文件?


问题答案:

抱怨我没有实施IntelliJ IDEA是正确还是错误javax.ws.rs.ext.Providers

中的文件META- INF/services是我们可以通过使用来创建可扩展应用程序的一部分ServiceLoader。它的工作方式是文件名应该是
合同 的名称,文件的内容应该是该合同的 实现
列表。然后,ServiceLoader它将看到文件并收集所有实现。因此,使用ServiceLoader,我们可以做到

ServiceLoader<MessageBodyReader> readersLoader
        = ServiceLoader.load(MessageBodyReader.class);

根据传递给load方法的类,Java将搜索文件

META-INF/services/javax.ws.rs.ext.MessageBodyReader

并查看该文件的内容以查找应加载的所有实现。

因此,根据该信息,您可以看到IntelliJ 在抱怨中
正确的,因为您的阅读器和书写器没有正确实现javax.ws.rs.ext.Providers

我应该指出的一件事是,我不认为ServiceLoader直接使用该类是因为它要求服务实现具有无参数构造函数。但这是用于META服务的确切模式。

要注册MessageBodyReaderMessageBodyWriter实现的正确文件是什么?

META-INF/services文件的使用不是JAX-RS规范的一部分。这是一个实现细节,将专用于JAX-
RS实现,尽管这种模式使用了很多。您通常会看到可重用库(例如您提到的1的Jackson库)中正在使用的文件。

如果提供者将成为我们应用程序的一部分,那么可以使用更通用的方式进行注册。

  • @Provider你提到的注释是一个标记注释,以检测应注册的提供程序类。启用扫描后,运行时将扫描带有注释的类@Provider,然后它将在应用程序中注册它们。

当我们谈论扫描时,有两种不同的方式:类路径扫描和包扫描。在JAX-
RS应用程序中,通过使用Application注释一个空类来启用类路径扫描@ApplicationPath

    @ApplicationPath("/api/*")
public class ApplicationConfig extends Application {}

这足以配置JAX-RS应用程序2。将启用类路径扫描,它将扫描整个类路径以查找所有带注释的类@Path@Provider并注册这些类。

软件包 扫描是特定于Jersey实施的内容。我们可以这样配置我们的应用程序

    @ApplicationPath("api")
public class ApplicationConfig extends ResourceConfig {
    public ApplicationConfig() {
        package("the.package.to.scan");
    }
}

在这里,我们告诉Jersey扫描the.package.to.scan软件包@Path并查找@Provider要在应用程序中注册的类。

  • 注册我们的提供程序的另一种方法是显式注册他们。在Application子类中,您将覆盖它们getClasses()getSingletons()将它们分别注册为类或对象。
        @ApplicationPath("/api/*")
    public class ApplicationConfig extends Application {
        private final Set<Class<?>> classes = new HashSet<>();
        private final Set<Object> singletons = new HashSet<>();

        public ApplicationConfig() {
            classes.add(MyMessageBodyReader.class);
            singletons.add(new MyMessageBodyReader());
        }

        @Override
        public Set<Class<?>> getClasses() {
            return this.classes;
        }

        @Override
        public Set<Object> getSingletons() {
            return this.singletons;
        }
    }

请注意,一旦您覆盖了这两种方法中的任何一个并返回了一个非空集,则将自动禁用类路径扫描,并且您将需要手动注册所有内容。

如果您使用的是Jersey实现,则还有一些我们可以显式注册资源和提供程序的Jersey特定方法。有关此内容的更多讨论,请参见Jersey
2中的ResourceConfig类到底是什么?。

  • 我可以想到的另一种注册提供商的方法是使用功能。我们可以使用香草Feature,也可以使用DynamicFeature

使用Feature,我们在整个应用程序中注册提供商

        // We should register the feature with our application
    public class MyFeature implements Feature {
        @Override
        public boolean configure(FeatureContext context) {
             context.register(MyMessageBodyReader.class);
        }
    }

使用a,DynamicFeature我们可以选择使用特定的资源方法或资源类注册提供程序。有关动态绑定,请参阅Jersey文档中的更多内容。应该注意的是,动态绑定更多地用于过滤器和拦截器(在通常的意义上,提供者),而不是实体提供者(MessageBodyReader
/ Writers)。

  • 可能还有其他注册提供程序的方法,但是上面提到的一种方法是您可以看到它在应用程序中完成的主要方法。

什么能启发我这一点的权威性文件?

我不确定任何文档中有多少关于META-INF /服务文件的信息。但是显式注册和类路径扫描,您可能会在JAX-
RS规范或Jersey文档中找到

1-应该注意的是,仅仅因为文件存在,并不意味着它将被使用。是否关心是否使用JAX-
RS取决于它。例如,Jersey不会在MessageBodyReader和上使用它。



 类似资料:
  • 我已经实现了 Javax WS RS ,用于网站 和,用于以便我可以通过 HTTP REST API 轻松使用 CMP 中的类型。现在,为了注册这些类型,我创建了文件,并将类名放在那里。一切正常,我可以使用API进行REST调用,除了: > IntelliJ IDEA(或我安装到其中的一个插件)抱怨说 注册扩展应实现 javax.ws.rs.ext.提供程序 在文件的两行上。根据我在互联网上找到的

  • 问题内容: 什么是RMI注册表?它有什么作用? 问题答案: 本质上,RMI注册表是服务器注册其提供的服务的场所,也是客户端查询这些服务的场所。请参阅Java RMI简介 。摘抄: 图1显示了使用RMI时客户端建立的连接。首先,客户端必须联系RMI注册中心,并请求服务名称。开发人员B不知道RMI服务的确切位置,但是他知道足够联系开发人员A的注册表。这将使他指向他要致电的服务方向。

  • 您好,我想将gcm添加到我的应用程序中。我的应用程序是一个新闻应用程序。用户可以在注册后查看新闻。应用程序询问用户兴趣(经济、运动、汽车等)并保存它们。我想从php和mysql向用户发送消息作为通知。我必须决定将哪些新闻发送给哪些用户。所以我需要注册证。 是Android设备号吗?还是Android设备谷歌账号和Android设备号的组合 还是Android设备google帐户和Android设备

  • 此外,如果已经注册了回调URI,那么单独注册JS起源将完成什么工作。与回调URI注册不同,OAuth2.0规范中没有提到这一点,而是Google选择实现的。 谢谢你的帮助!

  • 问题内容: 我有一个使用hibernate 3.1和JPA批注的应用程序。它有一些带有byte []属性的对象(大小为1k-200k)。它使用JPA @Lob批注,并且hibernate 3.1可以在所有主要数据库上读取它们,这似乎隐藏了JDBC Blob供应商的特性(应该这样做)。 当我们发现hibernate3.5 破坏了(并且不会修复) postgresql中的这个注释组合时(没有解决方法)

  • 我想设置一个由多个步骤组成的用户注册。每个步骤将以条的形式突出显示。深灰色条将是完成的步骤,浅灰色条将是需要完成的步骤。似乎想不出这样做的方法。请建议。 我们可以在myfitnesspal注册中看到这一点。我在下图的红色框中突出显示了这一点。