Jersey 2 中的 ResourceConfig 类到底是什么?到底是什么、Jersey、ResourceConfig

2023-09-06 10:43:27 作者:那就再见

我看过很多以类似开头的 Jersey 教程

I have seen a lot of Jersey tutorials that starts with something like

@ApplicationPath("services")
public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        packages("com.abc.jersey.services");
    }
}

没有解释 ResourceConfig 类到底是什么.那么我在哪里可以找到它的文档、用法等呢?谷歌搜索jersey resourceconfig"不会产生任何官方文档.

without explaining what exactly the ResourceConfig class is. So where can I find its documentation, usage, etc.? Googling for "jersey resourceconfig" does not yield any official doc.

我对这个类及其用法的一些问题是:

Some of my questions about this class and its usage are:

我可以在 ResourceConfig 的子类中做些什么?我是否需要在某处注册 ResourceConfig 的子类以便可以找到它,或者它会被 Jersey 自动检测到?如果自动检测到子类,如果我有多个 ResourceConfig 子类会怎样?ResourceConfig的用途和web.xml文件的用途一样吗?如果是这样,如果我在我的项目中同时拥有这两者会发生什么?其中一个是否优先于另一个? What things can I do inside the subclass of ResourceConfig? Do I need to register the subclass of ResourceConfig somewhere so that it can be found or is it automatically detected by Jersey? If the subclass is automatically detected what happens if I have multiple subclasses of ResourceConfig? Is the purpose of ResourceConfig the same as the web.xml file? If so what happens if I have both in my project? Does one of them take precedence over the other?

推荐答案

标准 JAX-RS 使用 Application 作为它的配置类.ResourceConfig 扩展 Application.

Standard JAX-RS uses an Application as its configuration class. ResourceConfig extends Application.

有三种主要方式(在 servlet 容器中)来配置 Jersey (JAX-RS):

There are three main ways (in a servlet container) to configure Jersey (JAX-RS):

只有 web.xml同时使用 web.xml 和一个 Application/ResourceConfig 类只有一个 Application/ResourceConfig 类用 @ApplicationPath 注释. With only web.xml With both web.xml and an Application/ResourceConfig class With only an Application/ResourceConfig class annotated with @ApplicationPath.

只有 web.xml

可以以标准的 JAX-RS 方式配置应用程序,但以下是特定于 Jersey 的

With only web.xml

It is possible to configure the application in a standard JAX-RS way, but the following is specific to Jersey

<web-app>
    <servlet>
        <servlet-name>jersey-servlet</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.mypackage.to.scan</param-value>
        </init-param>
    </servlet>
    ...
    <servlet-mapping>
        <servlet-name>jersey-servlet</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
    ...
</web-app>

由于 Jersey 在 servlet 容器中运行,因此 Jersey 应用程序作为 servlet 运行是正确的.处理传入请求的 Jersey Servlet 是 ServletContainer.所以在这里我们将它声明为 <servlet-class>.我们还配置了一个 <init-param> 告诉 Jersey 为我们的 @Path@Provider 类扫描哪些包,所以它可以注册.

Since Jersey runs in a servlet container, it is only right that the Jersey application runs as a servlet. The Jersey Servlet that handles incoming requests is the ServletContainer. So here we declare it as the <servlet-class>. We also configure an <init-param> telling Jersey which package(s) to scan for our @Path and @Provider classes so it can register them.

在底层,Jersey 实际上会创建一个 ResourceConfig 实例,因为它是用来配置应用程序的.然后它将注册它通过包扫描发现的所有类.

Under the hood, Jersey will actually create a ResourceConfig instance, as that's what it uses to configure the application. Then it will register all the classes that it discovers through the package scan.

如果我们想使用 ApplicationResourceConfig 子类以编程方式配置我们的应用程序,我们可以对上述 web.xml 进行一次更改.我们没有设置 init-param 来扫描包,而是使用 init-param 来声明我们的 Application/ResourceConfig 子类.

If we want to programmatically configure our application with an Application or ResourceConfig subclass, we can do so with one change to the above web.xml. Instead of setting an init-param to scan for packages, we use an init-param to declare our Application/ResourceConfig subclass.

<servlet>
    <servlet-name>jersey-servlet</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.example.JerseyApplication</param-value>
    </init-param>
    <servlet-mapping>
        <servlet-name>jersey-servlet</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
</servlet>

package com.example;

public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        packages("com.abc.jersey.services");
    }
}

在这里,我们使用 ResourceConfig 子类的完全限定名称配置 init-param javax.ws.rs.Application.而不是使用告诉 Jersey 扫描哪个包的 init-param,我们只使用 ResourceConfig.

Here, we configure the init-param javax.ws.rs.Application with the fully qualified name of our ResourceConfig subclass. And instead of using the init-param that tells Jersey which package(s) to scan, we just use the convenience method packages() of the ResourceConfig.

我们还可以使用方法 register()property() 来注册资源和提供者,以及配置 Jersey 属性.使用 property() 方法,可以配置为 init-param 的任何内容也可以使用 property() 方法进行配置.例如,我们可以调用 packages(),而不是调用

We could also use the methods register() and property() to register resources and providers, and to configure Jersey properties. With the property() method, anything that can be configured as an init-param, can also be configured using the property() method. For instance instead of calling packages(), we could do

public JerseyApplication() {
    property("jersey.config.server.provider.packages",
             "com.mypackage.to.scan");
}

只有 Application/ResourceConfig

5G NR CSI RS介绍 3 CSI测量上报的配置和触发机制

如果没有 web.xml,Jersey 需要一种方法来提供 servlet 映射.我们使用 @ApplicationPath 注释来做到这一点.

// 'services', '/services', or '/services/*'
// is all the same. Jersey will change it to be '/services/*'
@ApplicationPath("services")
public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        packages("com.abc.jersey.services");
    }
}

这里用@ApplicationPath,就像我们在web.xml中配置servlet映射

Here with the @ApplicationPath, it's just like if we configured the servlet mapping in the web.xml

<servlet-mapping>
    <servlet-name>JerseyApplication</servlet-name>
    <url-pattern>/services/*</url-pattern>
</servlet-mapping>

当仅使用 Java 代码进行配置时,Jersey 需要通过某种方式发现我们的配置类.这是通过使用 ServletContanerInitializer.这是 Servlet 3.0 规范中引入的东西,所以我们不能使用仅 Java".早期 servlet 容器中的配置.

When using only Java code for configuration, there needs to be some way for Jersey to discover our configuration class. This is done with the use of a ServletContanerInitializer. This is something that was introduced in the Servlet 3.0 Specification, so we cannot use "Java only" configuration in earlier servlet containers.

基本上,初始化程序的实现者可以告诉 servlet 容器要查找哪些类,然后 servlet 容器会将这些类传递给初始化程序的 onStartup() 方法.在 Jersey 的初始化器实现中,Jersey 将其配置为查找 Application 类和使用 @ApplicationPath 注释的类.请参阅这篇文章了解更多说明.所以当 servlet 容器启动应用程序时,Jersey 的初始化程序将通过我们的 Application/ResourceConfig 类.

Basically what happens is that the implementor of the initializer can tell the servlet container what classes to look for, and the servlet container will pass those classes to the initializer onStartup() method. In Jersey's implementation of the initializer, Jersey configures it to look for Application classes and classes annotated with @ApplicationPath. See this post for further explanation. So when the servlet container starts the application, Jersey's initializer will get passed our Application/ResourceConfig class.

看看