1. ホーム
  2. servlets

[解決済み】サーブレットベースのアプリケーションで、設定リソースファイルをどこに置き、どのように読み込むか?

2022-04-06 09:36:05

質問

私のWebアプリケーションでは、次のような定義済みのユーザーセットにメールを送信する必要があります。 [email protected] を追加したいので、それを .properties ファイルを作成し、必要なときにそれにアクセスすることができます。これは正しい手順でしょうか、もしそうなら、このファイルをどこに置けばよいのでしょうか。私は、ソースとJSPファイルのための2つの別々のフォルダを持っているNetbeans IDEを使用しています。

解決方法は?

それはあなたの選択です。Javaウェブアプリケーションアーカイブ(WAR)には、基本的に3つの方法があります。


1. クラスパスに配置する

で読み込むことができるように ClassLoader#getResourceAsStream() をクラスパスと関連したパスで指定します。

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);

ここで foo.properties は、ウェブアプリケーションのデフォルトのクラスパスによってカバーされるルートの1つに配置されることが想定されています。 /WEB-INF/lib/WEB-INF/classes は、サーバーの /lib またはJDK/JREの /lib . プロパティファイルがウェブアプリケーションに固有のものである場合、最も良い方法は、プロパティファイルを /WEB-INF/classes . IDE で標準的な WAR プロジェクトを開発している場合は、このファイルを src フォルダー(プロジェクトのソースフォルダー)に格納します。Mavenプロジェクトを使用している場合、それを /main/resources フォルダーに格納されます。

また、デフォルトのクラスパスの外側に配置し、そのパスをアプリケーションサーバーのクラスパスに追加することも可能です。例えば、Tomcatでは、次のように設定できます。 shared.loader プロパティに Tomcat/conf/catalina.properties .

を配置した場合 foo.properties のようなJavaのパッケージ構造で、それを com.example であれば、以下のようにロードする必要があります。

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("com/example/foo.properties");
// ...

コンテキスト・クラス・ローダーのパスの先頭が / . のような相対クラス・ローダを使用している場合のみです。 SomeClass.class.getClassLoader() で開始する必要があります。 / .

ClassLoader classLoader = getClass().getClassLoader();
InputStream input = classLoader.getResourceAsStream("/com/example/foo.properties");
// ...

ただし、この場合、プロパティファイルの可視性は、当該クラスローダーに依存します。クラスをロードしたクラスローダーと同じクラスローダーからしか見えません。つまり、例えばクラスがwebappクラスローダーではなくサーバーコモンクラスローダーによってロードされ、プロパティファイルがwebapp自体の中にある場合、それは不可視となります。クラスパス内のどこにでもプロパティファイルを置くことができ、かつ、ウェブアプリケーションからサーバーが提供するものをオーバーライドできるようにするためには、コンテキストクラスローダーが最も安全な方法です。


2. ウェブコンテンツに配置する

で読み込むことができるように ServletContext#getResourceAsStream() を webcontent-relative path で指定します。

InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties");
// ...

に置くことを示しました。 /WEB-INF フォルダに保存されます。そうでなければ、どのウェブブラウザからもアクセスできるようになります。また ServletContext は、任意の HttpServlet クラスからアクセスできるのは、継承した GenericServlet#getServletContext() であり Filter によって FilterConfig#getServletContext() . サーブレットクラスでない場合、通常は単に @Inject .


3. ローカルディスクのファイルシステムに置く

を読み込むことができるように、通常の java.io の方法で、ローカルディスクのファイルシステムの絶対パスを指定します。

InputStream input = new FileInputStream("/absolute/path/to/foo.properties");
// ...

絶対パスを使用することの重要性に注意してください。相対的なローカル・ディスク・ファイル・システムのパスは、Java EE ウェブ・アプリケーションでは絶対に使用しないでください。以下の最初の "See also" のリンクも参照してください。


どれを選ぶ?

でメリット/デメリットを天秤にかけるだけ。 あなたの 保守性についての自分なりの意見です。

プロパティファイルが静的で、実行中に変更する必要がない場合は、WAR に保存しておくことができます。

毎回 WAR を再構築して再デプロイすることなく、Web アプリケーションの外部からプロパティファイルを編集できるようにしたい場合は、プロジェクトの外部のクラスパスに置きます (必要に応じて、ディレクトリをクラスパスに追加します)。

もし、Web アプリケーションの内部で Properties#store() メソッドを使用する場合は、Web アプリケーションの外側に配置してください。というように Properties#store() が必要です。 Writer の場合、ディスクファイルシステムパスを使用することはできません。このパスは、VMの引数やシステムプロパティとして、Webアプリケーションに渡すことができます。注意点として 決して 使用 getRealPath() . deploy フォルダ内のすべての変更は、元の WAR ファイルに反映されないという単純な理由で、再デプロイ時に失われてしまいます。

こちらもご覧ください。