[Java] サーブレット環境で現在の実行ディレクトリを取得する方法


Devlopment note / Java    作成日付 : 2020/02/27 03:00:00   修正日付 : 2020/02/27 03:00:00

こんにちは。明月です。


この投稿はJavaのサーブレット環境で現在の実行ディレクトリを取得する方法に関する説明です。


プログラムを作成する時に現在のディレクトリを知る時があります。特にEclipse環境で実行する時にはコンパイルして実行させる場所 を探しにくいので開発する時に困る時があります。

例えば、環境ファイルを読み込む時やプロジェクト仕様として各種ファイルやテンプレートを読み込む時に必要です。


その時にローカルディレクトリを探す方法は2つあります。


実行しているクラスのファイルの場所で探す方法です。

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// Urlの「/Where」の場合に呼出す。
@WebServlet("/Where")
public class Where extends HttpServlet {
  // メソッドGET方式で接続する時に呼出す関数。
  protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
    // WebResponseから応答bodyのストリームを受け取る。
    PrintWriter writer = response.getWriter();
    // 出力する。
    writer.append("This file directory is ...   ");
    // 現在、実行されている(Where.class)クラスの位置を探す。
    URL url = Thread.currentThread()
                    .getContextClassLoader()
                    .getResource(this.getClass().getName() + ".class");
    // 出力する。
    writer.append(url.getPath());	
  }	
  // メソッドPOST方式で接続する時に呼出す関数。
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    // メソッドGET方式と同じ処理になる。
    doGet(request, response);	
  }	
}


Threadクラスで現在に動いているスレッドのクラスの場所を探すと現在の実行パスを探すのが出来ます。

上の関数の処理では問題ないですが、Lambda式やマルチスレッドなどで呼出すと結果が可笑しくなる可能性があります。その時に「Thread.currentThread().getContextClassLoader()」ではなく、「this.getClass().getClassLoader()」を呼出して取得ができます。

でも全てLoaderを通って取得するから、マルチスレッドなら正確に取得出来ない可能性はあります。(可能性といってもすごく低いです。)


我々はサーブレットを作っているのでサーブレットのcontextを利用して取得する方法もあります。

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// Urlの「/Where」の場合に呼出す。
@WebServlet("/Where")
public class Where extends HttpServlet {
  // メソッドGET方式で接続する時に呼出す関数。
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    // WebResponseから応答bodyのストリームを受け取る。
    PrintWriter writer = response.getWriter();
    // 出力する。
    writer.append("This project directory is ...   ");
    // servletContextから現在の実行しているパスを取得する。
    String path = getServletContext().getRealPath("/");
    // 出力する。
    writer.append(path);
  }
  // メソッドPOST方式で接続する時に呼出す関数。
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    // メソッドGET方式と同じ処理になる。
    doGet(request, response);
  }
}


上の場合はcontextインスタンスから取得するものなので、マルチスレッドやLambda式で間違って取得する問題はありません。

でも、サーブレットクラス(HttpServletを継承したクラス)だけ取得ができることなので一般クラスで現在パスを取得するようには上のLoaderを通って取得する方法しかないです。


私の場合はWebServerを起動する時にインスタンス初期化する方法で「static」タイプの変数に実行パスを格納して使うことでよく使います。

link - [Java] Java servletでインスタンスを初期する方法


ここまでJavaのサーブレット環境で現在の実行ディレクトリを取得する方法に関する説明でした。


ご不明なところや間違いところがあればコメントしてください。

最新投稿