vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

Servlet + TomcatでWeb その1

カクカクシカジカで、Java(Servlet)を使ってWebサイトを作ってみることにしました。

ひとまず、これまでSinatraで作っていたものをJavaTomcatを使って置き換えてみます。

準備

  • Javaのインストール
    1. 「sudo add-apt-repository ppa:webupd8team/java」でリポジトリを追加
    2. 「sudo apt update」で更新後、「sudo apt install oracle-java8-installer」でインストール
  • Eclipse IDE for Java EE Developersを公式サイトからダウンロードして、任意の場所に展開する(日本語化したい場合はプラグインを入れておく)
  • Tomcat8.0を公式サイトからダウンロードして、任意の場所に展開する

EclipseTomcatをaptでインストールしないのは、最新バージョンを使いたいということと、EclipseからTomcatを使うときに一般ユーザーの権限では失敗するからです (この辺りの設定もするべきなのでしょうが、今回はスキップします)。

  • プロジェクトの作成 1. File>Projectから、新規プロジェクト作成のウィザードを開いて、 Web>Dynamic Web Projectを選択してNextをクリック 2. プロジェクト名は任意のものを、「Target runtime」でWebアプリを動かすためのRuntime(今回はTomcat)を選択 3. Step2でRuntimeがない場合、または新規追加したい場合は「New Runtime」をクリック
    Runtimeの追加
    4. 「Select the type of runtime environment」から追加したいRuntime(今回はTomcat)を選択してNextをクリック 5. 「Tomcat installation directory」で、インストールしたTomcatのディレクトリ直下を指定する 6. 「JRE」で、インストールしたjava(java-8-oracle)を選択して「Finish」をクリック
    ここまで
    7. Nextをクリックして、「Source folders on build path」は何も追加するものがなければそのままNextをクリック 8. 「Generate web.xml deployment descriptor」にチェックを入れて、web.xmlを自動で作成するようにして「Finish」をクリック

  • Servletの追加

    1. プロジェクト上で New>Other>Servletを選択してNextをクリック
    2. Java package」、「Class name」にそれぞれ任意の名前を入力してNextをクリック(今回は「Controller」「GetContents」にしました)

web.xml

Tomcatでは使用するServletのURLやTopドメインを開いたときに表示するページ(Welcome file)などを指定する、web.xmlを使用します。

プロジェクトの作成時に「Generate web.xml deployment descriptor」にチェックを入れている場合、 プロジェクトのディレクトリ>WebContents>WEB-INFにweb.xmlが作成されています(そうでない場合は自分で作成・追加します)。

welcome file

以下のようにファイル名を指定することで、Topドメインを開いた時に該当のファイルを表示できます。

< welcome-file-list >
  < welcome-file >mainpage.html< / welcome-file >
< / welcome-file-list >

Viewファイルを設置する

デフォルトではHTMLなどの(MVCにおける)Viewにあたるファイルを置きます。

こんな感じ

Eclipseで上記のHTMLを開くと、mainタグでアラートが出ていますが、特に気にしなくても良さそうです(HTML5のタグに対応していないようです)。

Serverの設定

デフォルトではEclipseの画面下部に表示される「Server」に何も表示されていない場合は、右クリック>New>Serverで、Tomcatを追加します。
今回は以下を指定しました。

上記を指定したあとNextをクリックして、「Available」に作成したプロジェクト名が表示されていたら、「Add>」をクリックして「Configured」に移動させます。

実行

とりあえず実行してみます。
Eclipseの画面上部にある「Debug」または「Run」ボタンをクリックして、サーバーを起動します(初回は右隣の▼から実行対象を選ぶ必要があるかもしれません)。

あとは「localhost:8080/jvTabTest」にアクセスすれば、Welcome fileで設定したmainpage.htmlが表示されるはずです。

JavascriptCSSのパスは、HTMLのパス(WebContent直下?)からの相対パスで指定できます。

Servletを使う

Sinatraでのapp.rb(この辺参照)のように、ユーザーがアクセスしたURLを振り分けて、何らかの処理をしたりページを表示するControllerを作成してみます。

上記で作成したServletは、プロジェクト>src>controllerにあります(Controllerは作成時に設定したJava package名です)。

デフォルトでは以下のような内容です

TabController.java

package controller;

import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/TabController")
public class TabController extends HttpServlet {
    private static final long serialVersionUID = 1L;
  public TabController() {
      super();
  }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // Getリクエストが送信されたら実行
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // Postリクエストが送信されたら実行
    }

}

@WebServletで設定したURL(ここでは「localhost:8080/jvTabTest/TabController」)にアクセスした時に、このServletが実行されます。

JavaScriptから「localhost:8080/jvTabTest/contents」にGetリクエストを投げたときに、HTMLのファイルを返すようにしたいので、以下のように変更します。

@WebServlet("/contents")

また、HTMLのファイルを返すメソッドはdoGet()に記述します。

ServletでHTMLファイルをロードし、中身を返す

※正直実用的ではない気がするのですが、メモとして残しておきます。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  // エンコーディングの指定.
  request.setCharacterEncoding("UTF-8");

  // JavaScriptから「cnt=0」のように渡されるパラメータを取得.
  Enumeration names = request.getParameterNames();
  String strContent = "";
  String strGotResult = "";
  if (names.hasMoreElements()){
    strContent = (String)request.getParameter(names.nextElement());
    // 取得したパラメータから、HTMLファイルのパスを取得する.
    String strCntFilePath = this.getServletContext().getRealPath("/contents/" + strContent + ".html");
    // 取得したパスからファイルを取得する.
    File file = new File(strCntFilePath);

    char data[] = new char[3000];
    FileReader filereader = new FileReader(file);
    // ファイルの内容を読み込む.
    int charscount = filereader.read(data);
    strGotResult = new String(data,0,charscount);
    // ファイルリーダーを閉じる
    filereader.close();
  }
  // 戻り値の内容をHTMLに設定して、読み込んだ内容を返す.
  response.setContentType("text/html");
  response.getWriter().write(strGotResult);
}

内容はコメントの通りなのですが、読み込んだHTMLファイルに手を加えるわけでもないため、ファイルをServletでは読み込まず、 そのままHTMLとして渡す方法がないか、と思案中です。

  • JavaScriptから直接HTMLファイルを取得できるのですが、ファイルのパスを直接読み込まない方が良いかと思い、別の方法を探っています。
  • HTMLではなくJavaの文字列型としてファイルの中身をもたせれば解決はしますが、メンテナンスなどを考えるとこれも不便かなと。

次回に続きます。

参考

Javaのインストール

Tomcat, web.xml

Servletからのファイルロード