Jersey 2 中的 ResourceConfig 类到底是什么? [英] What exactly is the ResourceConfig class in Jersey 2?

查看:22
本文介绍了Jersey 2 中的 ResourceConfig 类到底是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看过很多以类似开头的 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):

  1. 只有 web.xml
  2. 同时使用 web.xml 一个 Application/ResourceConfig
  3. 只有一个 Application/ResourceConfig 类用 @ApplicationPath 注释.
  1. With only web.xml
  2. With both web.xml and an Application/ResourceConfig class
  3. 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,我们只使用 ResourceConfigpackages()代码>.

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

如果没有 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.

看看 javadoc.它主要只是注册课程.你不需要做太多其他事情.您将使用的主要方法是 register()packages()property() 方法.register() 方法允许您手动注册资源和提供者的类和实例.前面讨论过的 packages() 方法列出了您希望 Jersey 扫描 @Path@Provider 类并注册的包他们给你.property() 方法允许你设置一些 可配置属性 1.

Just look at the javadoc. Its mostly just registration of classes. Not much else you need to do with it. The main methods you will be using are the register(), packages(), and property() methods. The register() method lets you manually register classes and instances of resources and providers manually. The packages() method, discussed earlier, lists the package(s) you want Jersey to scan for @Path and @Provider classes and register them for you. And the property() method allows you to set some configurable properties 1.

ResourceConfig 只是一个便利类.请记住,它扩展了 Application,因此我们甚至可以使用标准的 Application

The ResourceConfig is just a convenience class. Remember, it extends Application, so we could even use the standard Application class

@ApplicationPath("/services")
public class JerseyApplication extends Application {

    private final Set<Class<?>> classes;
    private final Set<Object> singletons;

    public JerseyApplication() {
        // configure in constructor as Jersey
        // may call the getXxx methods multiple times

        this.classes = new HashSet<>();
        this.classes.add(MyResource.class);

        this.singletons = new HashSet<>();
        this.singletons.add(new MyProvider());
    }

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

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

    @Override
    public Map<String, Object> getProperties() {
        final Map<String, Object> properties = new HashMap<>();
        properties.put("jersey.config.server.provider.packages",
                       "com.mypackage.to.scan");
        return properties;
    }
}

有了 ResourceConfig,我们就可以做到

With a ResourceConfig, we would just do

public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
        register(MyResource.class);
        register(new MyProvider());
        packages("com.mypackages.to.scan");
    }
}

除了更方便之外,还有一些事情可以帮助 Jersey 配置应用程序.

Aside from being more convenient, there are also a few thing under the hood that help Jersey configure the application.

以上所有示例都假设您在已安装的服务器环境中运行,例如雄猫.但您也可以在 SE 环境中运行应用程序,在其中运行嵌入式服务器并从 main 方法启动应用程序.您有时会在四处搜索信息时看到这些示例,所以我想展示一下它们的外观,这样如果您遇到这种情况,您不会感到惊讶,并且知道它与您的设置有何不同.

All the examples above assume you are running in an installed server environment, e.g. Tomcat. But you can also run the app in an SE environment, where you run an embedded server and start the app from a main method. You will sometimes see these examples when searching around for info, so I want to show what that looks like, so that if you ever do come across this, you are not surprised and know how it differs from your setup.

所以有时你会看到这样的例子

So sometimes you will see an example like

ResourceConfig config = new ResourceConfig();
config.packages("com.my.package");
config.register(SomeFeature.class);
config.property(SOME_PROP, someValue);

这里最有可能发生的情况是该示例使用了嵌入式服务器,例如 Grizzly.启动服务器的其余代码可能类似于

What is most likely happening here is that the example is using an embedded server, like Grizzly. The rest of the code to start the server might be something like

public static void main(String[] args) {
    ResourceConfig config = new ResourceConfig();
    config.packages("com.my.package");
    config.register(SomeFeature.class);
    config.property(SOME_PROP, someValue);

    String baseUri = "http://localhost:8080/api/";
    HttpServer server = GrizzlyHttpServerFactory
            .createHttpServer(URI.create(baseUri), config);
    server.start();
}

所以在这个例子中,有一个独立的服务器正在启动,并且 ResourceConfig 用于配置 Jersey.此处与之前示例的不同之处在于,在此示例中,我们没有扩展 ResourceConfig,而只是将其实例化.如果我们这样做也不会有什么不同

So in this example, there is a standalone server being started and the ResourceConfig is used to configure Jersey. The different here and from previous examples is that in this example, we are not extending the ResourceConfig, but instead just instantiating it. It wouldn't be any different if we were to do

public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        packages("com.my.package");
        register(SomeFeature.class);
        property(SOME_PROP, someValue);
    }
}

HttpServer server = GrizzlyHttpServerFactory
            .createHttpServer(URI.create(baseUri), new JerseyConfig());

假设您正在阅读一些教程,它显示了一个独立应用程序的配置,他们在其中实例化了 ResourceConfig.但是您在已安装的 servlet 容器中运行您的应用程序,并且一直在使用您扩展 ResourceConfig 的早期配置.那么现在您知道区别是什么以及您需要进行哪些更改.我见过人们做一些非常奇怪的事情,因为他们不理解这种差异.例如,我看到有人在资源类中实例化 ResourceConfig.所以这就是我添加这个额外的小片段的原因;所以你不会犯同样的错误.

Say you were going through some tutorial and it showed a configuration for a standalone app where they instantiate the ResourceConfig. But you are running your app in an installed servlet container and have been using the earlier configuration where you are extending the ResourceConfig. Well now you know what the difference is and what changes you need to make. I've seen people do some really weird stuff because they didn't understand this difference. For example I saw someone instantiating a ResourceConfig inside a resource class. So this is why I added this extra little piece; so you don't make the same mistake.

<子>1.有许多不同的可配置属性.ServerProperties 只是一些通用属性.还有与特定功能相关的不同属性.文档应在与该功能相关的文档部分中提及这些属性.有关所有可配置属性的完整列表,您可以查看所有 Jersey 常量 并查找字符串值以 jersey.config 开头的那些.如果您使用的是 web.xml,那么您将使用字符串值作为 init-param param-name.如果您使用的是 Java 配置 (ResourceConfig),那么您将调用 property(ServerProperties.SOME_CONF, value)

1. There are a number of different configurable properties. The link to the ServerProperties are just some general properties. There are also different properties related to specific features. The documentation should mention these properties in the section of the docs related to that feature. For a complete list of all configurable properties, you can look at all the Jersey constants and look for the ones where the string value starts with jersey.config. If you are using a web.xml, then you would use the string value as the init-param param-name. If you are using Java config (ResourceConfig), then you would call property(ServerProperties.SOME_CONF, value)

这篇关于Jersey 2 中的 ResourceConfig 类到底是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆