抱怨我没有实施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服务的确切模式。
要注册
MessageBodyReader和MessageBodyWriter实现的正确文件是什么?
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和上使用它。



