1. ホーム
  2. jersey

[解決済み] Jersey 2のResourceConfigクラスとは一体何でしょうか?

2023-06-08 15:20:12

質問

ジャージーのチュートリアルで、次のような書き出しのものをよく見かけます。

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

が具体的にどのようなものかを説明することなく ResourceConfig クラスが何であるかは説明されていません。では、そのドキュメントや使用方法などはどこで見つけることができるのでしょうか?ググってみても、公式のドキュメントは出てきません。

このクラスとその使用法に関する私の質問のいくつかを紹介します。

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

どのように解決するのですか?

標準的なJAX-RSでは Application を設定クラスとして使用します。 ResourceConfig が拡張されます。 Application .

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> を設定し、Jersey にどのパッケージをスキャンするのかを伝えています。 @Path@Provider クラスを登録できるようにします。

フードの下で、Jersey は実際に ResourceConfig のインスタンスを作成します。それはアプリケーションを構成するために使用するものだからです。そして、パッケージスキャンによって発見されたすべてのクラスを登録します。

web.xml と Application/ResourceConfig

プログラムによってアプリケーションを設定する場合 Application または ResourceConfig のサブクラスを作成する場合、上記の web.xml をひとつ変更するだけで、それが可能になります。パッケージをスキャンするために 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-param javax.ws.rs.Application の完全修飾名で ResourceConfig というサブクラスの完全修飾名を指定します。そして、その代わりに init-param を使う代わりに、便利なメソッドである packages()ResourceConfig .

また、メソッド 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はservlet-mappingを提供する方法を必要とします。私たちはこれを @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 . これは Servlet 3.0 仕様で導入されたもので、それ以前のサーブレットコンテナでは "Java only" の設定を使用することはできません。

基本的に何が起こるかというと、イニシャライザの実装者はサーブレットコンテナにどのクラスを探せばいいかを伝えることができ、サーブレットコンテナはそれらのクラスをイニシャライザに渡します。 onStartup() というメソッドがあります。Jerseyのイニシャライザーの実装では、Jerseyはこのメソッドが Application でアノテーションされたクラスと @ApplicationPath . 参照 この記事 を参照してください。そのため、サーブレットコンテナがアプリケーションを起動するとき、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 {

    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 では、単に

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

より便利であることはさておき、Jersey がアプリケーションを設定するのに役立ついくつかのことが、フードの下にあります。

SE環境

上記のすべての例は、Tomcat などのインストールされたサーバー環境で実行することを前提としています。しかし、アプリを SE 環境で実行することもできます。この場合、組み込みサーバーを実行し、アプリを main メソッドからアプリを起動します。情報を検索していると、このような例を目にすることがあります。そこで、このような例に出会っても驚かないように、また自分の設定とどう違うかを知ってもらうために、どのようなものかを紹介したいと思います。

そのため、次のような例を見ることがあります。

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 は、いくつかの一般的なプロパティに過ぎません。また、特定の機能に関連した異なるプロパティもあります。ドキュメントでは、その機能に関連するセクションでこれらのプロパティに言及する必要があります。の完全なリストについては のすべての 設定可能なプロパティの完全なリストについては、すべての ジャージーの定数 で始まる文字列を探します。 jersey.config . web.xml を使用している場合は、文字列の値を init-param param-name . Java のコンフィグを使用している場合 ( ResourceConfig ) を使っている場合は property(ServerProperties.SOME_CONF, value)