web-dev-qa-db-ja.com

Jersey 2のResourceConfigクラスとは何ですか?

私は次のようなもので始まる多くのジャージーのチュートリアルを見てきました

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

ResourceConfigクラスが正確に何であるかを説明せずに。それでは、ドキュメント、使用法などはどこにありますか? 「jersey resourceconfig」のグーグル検索では、公式ドキュメントは生成されません。

このクラスとその使用法に関する私の質問のいくつかは次のとおりです。

  • ResourceConfigのサブクラス内でできることは何ですか?
  • ResourceConfigのサブクラスを登録して、それを見つけられるようにするか、ジャージーによって自動的に検出されるようにする必要がありますか
  • サブクラスが自動的に検出された場合、ResourceConfigのサブクラスが複数あるとどうなりますか?
  • ResourceConfigの目的はweb.xmlファイルと同じですか?もしそうなら、私がプロジェクトに両方を持っていたらどうなりますか?そのうちの1つが他より優先されますか?
45
Chin

標準JAX-RSは、構成クラスとして Application を使用します。 ResourceConfigextendsApplication

Jersey(JAX-RS)を構成するには、主に3つの異なる方法(サーブレットコンテナ内)があります。

  1. Web.xmlのみで
  2. Web.xmlの両方でApplication/ResourceConfigクラス
  3. Application/ResourceConfigアノテーションが付けられた@ApplicationPathクラスのみ。

Web.xmlのみで

標準のJAX-RSの方法でアプリケーションを構成することは可能ですが、以下は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はサーブレットコンテナで実行されるため、Jerseyアプリケーションがサーブレットとして実行されるのは正しいことです。着信要求を処理するJerseyサーブレットはServletContainerです。したがって、ここでは<servlet-class>として宣言します。また、<init-param>クラスを構成して、@Pathクラスと@ProviderクラスをスキャンするパッケージをJerseyに登録して、それらを登録できるようにします。

ボンネットの下で、Jerseyは実際にResourceConfigインスタンスを作成します。これは、アプリケーションの構成に使用されるためです。次に、パッケージスキャンで検出したすべてのクラスを登録します。

Web.xmlとApplication/ResourceConfigの両方を使用

ApplicationまたはResourceConfigサブクラスを使用してアプリケーションをプログラムで構成する場合、上記のweb.xmlを1回変更するだけで構成できます。 init-paramを設定してパッケージをスキャンする代わりに、init-paramを使用してApplication/ResourceConfigサブクラスを宣言します。

<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");
    }
}

ここでは、init-paramjavax.ws.rs.ApplicationResourceConfigサブクラスの完全修飾名で構成します。また、どのパッケージをスキャンするかをJerseyに伝えるinit-paramを使用する代わりに、ResourceConfigの便利なメソッドpackages()を使用します。

メソッドregister()およびproperty()を使用して、リソースとプロバイダーを登録し、Jerseyプロパティを構成することもできます。 property()メソッドを使用すると、init-paramとして設定できるものはすべて、property()メソッドを使用して設定することもできます。たとえば、packages()を呼び出す代わりに、

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

Application/ResourceConfigのみで

Web.xmlがない場合、Jerseyにはサーブレットマッピングを提供する方法が必要です。これは@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-mapping>
    <servlet-name>JerseyApplication</servlet-name>
    <url-pattern>/services/*</url-pattern>
</servlet-mapping>

構成にJavaコードのみを使用する場合、Jerseyが構成クラスを検出するための何らかの方法が必要です。これは、 ServletContanerInitializer を使用して行われます。これはサーブレット3.0仕様で導入されたものであるため、以前のサーブレットコンテナでは「Javaのみ」の構成を使用できません。

基本的に、イニシャライザの実装者は、どのクラスを探すかをサーブレットコンテナに伝えることができ、サーブレットコンテナはそれらのクラスをイニシャライザonStartup()メソッドに渡します。 Jerseyの初期化子の実装では、Applicationクラスおよび@ApplicationPathアノテーションが付けられたクラスを検索するようにJerseyを構成します。詳細については この投稿 をご覧ください。そのため、サーブレットコンテナがアプリケーションを起動すると、Jerseyの初期化子はApplication/ResourceConfigクラスに渡されます。

ResourceConfigのサブクラス内でできること

javadoc を見てください。そのほとんどはクラスの登録です。他に必要なことはあまりありません。使用する主なメソッドは、register()packages()、およびproperty()メソッドです。 register()メソッドを使用すると、リソースとプロバイダーのクラスとインスタンスを手動で手動で登録できます。前述のpackages()メソッドは、Jerseyに@Pathクラスと@Providerクラスをスキャンして登録するパッケージをリストします。 property()メソッドを使用すると、いくつかの 設定可能なプロパティ を設定できます 1

ResourceConfigは単なる便利なクラスです。 Applicationを拡張しているため、標準のApplicationクラスを使用することもできます。

@ApplicationPath("/services")
public class JerseyApplication extends Application {
    @Override
    public Set<Class<?>> getClasses() {
        final Set<Class<?>> classes = new HashSet<>();
        classes.add(MyResource.class);
        return classes;
    }
    @Override
    public Set<Object> getSingletons() {
        final Set<Object> singletons = new HashSet<>();
        singletons.add(new MyProvider());
        return 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を使用すると、

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

より便利であることに加えて、Jerseyがアプリケーションを構成するのに役立ついくつかの機能もあります。

SE環境

上記の例はすべて、インストールされたサーバー環境で実行していることを前提としています。 Tomcat。ただし、組み込みサーバーを実行し、mainメソッドからアプリを起動するSE環境でアプリを実行することもできます。情報を検索するときにこれらの例を見ることがあるので、どのように見えるかを示したいので、あなたがこれに遭遇しても驚かないで、セットアップとどう違うかを知ってください。

だから時々あなたは次のような例を見るでしょう

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

ここで起きている可能性が最も高いのは、この例がGrizzlyなどの組み込みサーバーを使用していることです。サーバーを起動する残りのコードは次のようなものです

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を拡張するのではなく、単にインスタンス化するだけです。私たちがやったとしても違いはありません

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をインスタンス化するスタンドアロンアプリの構成を示したが、サーブレットコンテナーでアプリを実行しており、ResourceConfigを拡張する以前の構成を使用しているとします。さて、あなたは違いが何であり、どのような変更を加える必要があるかを知っています。私は人々がこの違いを理解していなかったので、本当に奇妙なことをするのを見てきました。たとえば、誰かがリソースクラス内でResourceConfigをインスタンス化するのを見ました。そのため、この余分な部分を追加しました。あなたは同じ間違いをしないでください。


脚注

1.さまざまな設定可能なプロパティがあります。 ServerProperties へのリンクは、単なる一般的なプロパティです。特定の機能に関連するさまざまなプロパティもあります。ドキュメントでは、その機能に関連するドキュメントのセクションでこれらのプロパティに言及する必要があります。 all構成可能なプロパティの完全なリストについては、すべての Jersey定数 を見て、文字列が値はjersey.configで始まります。 web.xmlを使用している場合、文字列値をinit-paramparam-nameとして使用します。 Java config(ResourceConfig)を使用している場合、property(ServerProperties.SOME_CONF, value)を呼び出します。

127
Paul Samsotha