Jerseyの設定1(web.xmlとかApplicationクラスとか)
Jerseyの設定がバージョンによって違うが、webにある情報が色々混在していたりバージョンが不明だったりするので整理。
DeltaSpikeといいJerseyといい、結局は公式ドキュメントを読み込まないといけなくなる。英語力無いのが辛いところ。
Chapter 4. Application Deployment and Runtime Environments
環境
- Jersey2.22.1
- Java8
- Tomcat8
- Eclipse Luna(4.4.2)
テスト用プロジェクト
EclipseでJersey(JAX-RS)を始める - Qiita
こちらを参考にプロジェクトを作成。
Servlet2.5
自動作成されるpom.xmlやweb.xmlは、Servlet2.5(以上)の設定になっている様子。
Servlet2.5はTomcat6になるので今更使うことはないが軽く整理。
Servlet3.xは次回。
web.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- This web.xml file is not required when using Servlet 3.0 container, see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html --> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>mypackage.test</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/webapi/*</url-pattern> </servlet-mapping> </web-app>
プロジェクト作成して自動生成されたweb.xml。サーブレットとしてJerseyを動かす設定になっている。
もしサーブレットフィルタとして動かす場合は、filter関連のタグを使う。
<filter> <filter-name>Jersey Web Application</filter-name> <filter-class>org.glassfish.jersey.filter.ServletContainer</filter-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>mypackage.test</param-value> </init-param> <load-on-startup>1</load-on-startup> </filter> <filter-mapping> <filter-name>Jersey Web Application</filter-name> <url-pattern>/webapi/*</url-pattern> </filter-mapping>
<url-pattern>/webapi/*</url-pattern>はWebリソースを提供するパスを指定する。
この場合、Eclipseプロジェクトがtestとして作っているので、各リソースへは「http://localhost:8080/test/webapi/・・・」というURLになる。
param-nameで指定しているjersey.config.server.provider.packagesはリソースクラスの読み込み先を指定する。
param-valueで指定したパッケージ内のクラスがスキャンされる。デフォルトではサブパッケージもスキャン対象。コンマ区切りで複数指定可。
サブパッケージをスキャン対象にしたくない場合は、recursiveをfalseにする。
<init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>mypackage.test</param-value> </init-param> <init-param> <param-name>jersey.config.server.provider.scanning.recursive</param-name> <param-value>false</param-value> </init-param>
リソースクラスを個別に指定することもでき、その場合はjersey.config.server.provider.classnamesを使う。
<init-param> <param-name>jersey.config.server.provider.classnames</param-name> <param-value>mypackage.test.MyResource</param-value> </init-param>
こちらもコンマ区切りで複数クラス指定可。
packagesとclassnamesは両方指定可能のようなので、通常はpackagesを使用して特殊なものだけclassnamesを使う、という使い方になるはず。
(普通はpackagesだけで収まるようにすると思うけど)
pom.xml
dependenciesだけ抜き出し
<dependencies> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> <!-- use the following artifactId if you don't need servlet 2.x compatibility --> <!-- artifactId>jersey-container-servlet</artifactId --> </dependency> <!-- uncomment this to get JSON support <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-moxy</artifactId> </dependency> --> </dependencies>
コメントアウトされている通り、servlet2.x に適合させる必要がなければ
余談:moxyの方はJerseyデフォルトのJSONバインドモジュール。JSONリクエストをPOJOで受け取りたいとか、POJOを戻り値にしたい(JSON変換されてレスポンス)、という時に使う。
javax.ws.rs.core.Application
ここまではリソースクラスの読み込み先などをweb.xmlで設定していたが、実はこれは簡易版(?)で本来はjavax.ws.rs.core.Applicationを継承したクラスを作成して、そのクラスで設定をするものらしい。
たぶんApplicationクラスを作成するのはJAX-RSの仕様で、Jerseyを使うのであればorg.glassfish.jersey.servlet.ServletContainerがそのあたりを吸収してweb.xmlで書けるようにしてくれている、のかな?
とりあえずApplicationクラスを作成。
public class MyApplication extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> s = new HashSet<Class<?>>(); s.add(MyResource.class); return s; } }
リソースクラスのclassを設定する。つまり上述のweb.xmlでclassnamesを使っているようなもの。
これは面倒なので、JerseyではApplicationを拡張(extends)したResourceConfigクラスが用意されている。
public class MyApplication extends ResourceConfig { public MyApplication() { packages("mypackage.test;mypackage.test2"); property(ServerProperties.PROVIDER_SCANNING_RECURSIVE, false); } }
ResourceConfigだとパッケージ指定ができて、セミコロン区切りで複数指定もできる。
Jersey独自設定はResourceConfigを使うことになるので、Jersey使うのであればResourceConfigを最初から使っておけばいい。
PROVIDER_SCANNING_RECURSIVEは名前で分かる通り、上記web.xmlで指定していたjersey.config.server.provider.scanning.recursiveに該当する。
Application(or ResourceConfig)を使う場合、web.xmlはApplicationを読み込むだけの設定になる。
<servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>mypackage.test.MyApplication</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/webapi/*</url-pattern> </servlet-mapping>
公式ドキュメントにもわざわざ注釈があるが、param-nameに指定する値は「javax.ws.rs.Application」である。
作成したApplicationクラスの親クラスは「javax.ws.rs.core.Application」なのでcore 1つ分違う。ややこしい。
web.xmlをコピペした人はハマらない、注意深い人ほどハマる、たぶん。
Servlet2.5の方が意外と長くなったので、Servlet3.0の方は分けて書く。