JettyでWebアプリケーションを動かす3つの方法

こんにちは、サイオステクノロジー武井です。今回は、JavaのアプリケーションサーバーJettyでWebアプリケーションを動作させる3つの方法をご紹介します。

Jettyってなに?

Java EEの仕様に準拠して作られたWebアプリケーションを動かすためのミドルウェアです。要はServletやJSPを動かすことができます。軽量で高速、また組み込みが行いやすいといった特徴があります。

JettyでWebアプリケーションを動かしてみよう!!

では、早速JettyでWebアプリケーションを動かしてみましょう。主に「アプリケーションへの組み込み」「本体と設定ファイルが一緒」「本体と設定ファイルが別々」の3つの方法があります。

アプリケーションへの組み込み

Javaアプリケーションの中に、アプリケーションサーバーであるJettyを組み込んでしまおうという方法です。Webアプリケーション単体でJettyも一緒に動くのでとても実行がラクチンです。

では、以下のような構成のファイルを作ります。毎度おなじみMaven標準のディレクトリ構成です。

プロジェクトのTopディレクトリ
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── Hello.java
        └── resources

 

では以降で上記のファイルの詳細を説明していきます。いつものpom.xmlですが、ポイントは<dependency>〜</dependency>の部分でjettyのライブラリを定義しています。これが組み込みでJettyを起動するために必要なライブラリです。

 <project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>helloworld</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.eclipse.jetty.aggregate</groupId>
      <artifactId>jetty-all</artifactId>
      <version>9.4.32.v20200930</version>  
      <type>pom</type>    
    </dependency>    
  </dependencies>
</project>

 

そしてHello.javaのコードは以下のとおりです。詳細はソースのなかにコメントしました。

package com.example;
 
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.https.HttpServletRequest;
import javax.servlet.https.HttpServletResponse;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;

// 必ずAbstract Handlerを継承する。
public class Hello extends AbstractHandler {

    public static void main(String[] args) throws Exception {
        // Listenするポート番号を指定する。
        Server server = new Server(1234);

        // ハンドラー(リクエストを実際に処理するメソッド)を指定する。
        server.setHandler(new Hello());

        // Jettyを開始する。
        server.start();
        server.join();
    }

    @Override
    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        // Hello World!とブラウザに出力する
        response.setContentType("text/html;charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);
        baseRequest.setHandled(true);
        response.getWriter().println("<h1>Hello World!</h1>");
    }
}

 

Hello.javaを実行して、https://[Jettyが稼働しているホスト名]:1234/にアクセスすると、「Hello World!」が表示されるはずです。

わざわざ別途、アプリケーションサーバーを用意しなくても、Webアプリケーションを実行できました。

本体と設定ファイルが同じ場所にある場合

では次に、先のようにアプリケーションに組み込むのではなく、Jettyを別途起動し、そこにwarを投入するという方法を実施したいと思います。

まず以下のURLからJetty本体をダウンロードします。

https://www.eclipse.org/jetty/download.html

上記からダウンロードして解凍してできがったものが、まさにJetty本体です。主要なディレクトリやファイル構成は以下のようになっています。

Topディレクトリ
├── etc
├── lib
├── modules
├── start.ini
├── start.jar
└── webapps

以下がファイルやディレクトリの詳細です。ちなみにJettyは「モジュール」という単位で機能が分割されています。「HTTPでアクセスできるようにするためのモジュール」「webappsディレクトリ以下にwarを置くと勝手に展開してWebアプリケーションとして展開してくれるモジュール」というような単位でモジュールがあり、Jettyはその基本的な機能か拡張機能まで全てモジュールと言う単位で管理しています。

名前 種類 内容
etc ディレクトリ Jetty本体の設定ファイルが格納されています。主にモジュール関連の設定ファイルがメインで、各モジュール本体のファイルの場所やモジュールのデフォルトの設定などが記載されているファイル群がたくさんあります。
lib ディレクトリ 主にモジュールの本体のjarが格納されています。
modules ディレクトリ モジュールごとの情報を記載したファイルが格納されています。それらのファイルには、モジュールの名称や、このモジュールを動かすために依存しているモジュール、モジュールの詳細が記載されているファイル(etc配下のXML)の場所などが、各モジュールごとに記載されています。
start.ini ファイル

Jettyの起動に関する設定が書いてあります。主に何のモジュールを呼び出すかの設定です。例えば、webappsディレクトリ配下に格納したwarをWebアプリケーションとして起動したい場合、deployモジュールを呼び出す設定をこのstart.iniに書かなければなりません。

webapps ディレクトリ

このディレクトリにwarを入れると勝手にjettyがwarを展開してくれて、Webアプリケーションとして起動してくれます。ただし、deployモジュールが必要になります。

 

上記の中でいくつか代表的なディレクトリやファイルを紹介していきます。

例えば、module配下にはrewrite.modというファイルがあり、これはURLの書き換えを行うモジュールで、その中身は以下のようになっております。[lib]のところには、このモジュールの本体のプログラムのパス、[xml]のところには、このモジュールの基本的な設定ファイルへのパスが書かれています。

# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup
-modules.html

[description]
Enables the jetty-rewrite handler.  Specific rewrite
rules must be added to either to etc/jetty-rewrite.xml or a custom xml/module

[provides]
rewrite

[depend]
server

[lib]
lib/jetty-rewrite-${jetty.version}.jar


etc/jetty-rewrite.xml

[ini-template]
## Whether to rewrite the request URI
# jetty.rewrite.rewriteRequestURI=true

## Whether to rewrite the path info
# jetty.rewrite.rewritePathInfo=false

## Request attribute key under with the original path is stored
# jetty.rewrite.originalPathAttribute=requestedPath

 

次にstart.iniです。長いので一部省略しています。「–オプション名」のあとに起動のための設定を渡す形式になっています。一番最初にある「–exec」はその後に続く設定をJetty実行時の引数として渡します。「–module」は有効にしたいモジュールを渡します。いくらモジュールの設定をしても、ここで「–module」の後に指定しないと、そのモジュールは有効になりません。

#===========================================================
# Jetty Startup 
#
# Starting Jetty from this {jetty.home} is not recommended.
#
# A proper {jetty.base} directory should be configured, instead
# of making changes to this {jetty.home} directory.
#
# See documentation about {jetty.base} at
# https://www.eclipse.org/jetty/documentation/current/startup.html
#
# A demo-base directory has been provided as an example of
# this sort of setup.
#
# $ cd demo-base
# $ java -jar ../start.jar
#
#===========================================================

--exec
-Dorg.eclipse.jetty.annotations.AnnotationParser.LEVEL=OFF

# To disable the warning message, comment the following line
--module=home-base-warning

# --------------------------------------- 
# Module: ext
# Adds all jar files discovered in $JETTY_HOME/lib/ext
# and $JETTY_BASE/lib/ext to the servers classpath.
# --------------------------------------- 
--module=ext


# --------------------------------------- 
# Module: server
# Enables the core Jetty server on the classpath.
# --------------------------------------- 
--module=server
・・・以下略・・・

 

では先程のハロワを表示するWebアプリケーションを動かしてみましょう。

まず先程のハロワを以下のコマンドでビルドします。

$ mvn clean package

 

出来上がったwarをwebappsディレクトリに配置して、Jetty本体を解凍してできたディレクトリにて、以下のコマンドを実行します。

$ java -jar start.jar 

 

https://[Jettyが稼働しているホスト名]:8080/helloworld/helloにアクセスすると、「Hello World!」が表示されるはずです。

本体と設定ファイルが別々の場所にある場合

複数のWebアプリケーションを起動し、さらにそれらの起動設定や利用するモジュールも別々にしたい場合、「Jetty本体の場所」と「Jettyの設定ファイルがある場所」を別々にして起動することで実現が可能です。

早速実践してみたいと思います。まず今回の実践では、「Jetty本体の場所」と「Jettyの設定ファイルがある場所」を以下のような構成にしたいと思います。

  • Jetty本体の場所:/opt/jetty-home
  • Jettyの設定ファイルがある場所:/opt/jetty-base

さらにこの実践の環境ではJETTY_HOMEという環境変数にJetty本体の場所のパスが、そしてJETTY_BASEという環境変数にJettyの設定ファイルがある場所のパスが入っているものとします。Linuxの場合は以下のコマンドを実施すれば手っ取り早く環境変数にセットできます。

$ export JETTY_HOME=/opt/jetty-home
$ export JETTY_BASE=/opt/jetty-base 

 

最初は/opt/jetty-baseは空っぽです。設定ファイルをイチから作るのは大変なので、その設定ファイルの雛形を作るための便利なコマンドがあります。以下を実施して下さい。

$ cd /opt/jetty-base
$ java -jar $JETTY_HOME/start.jar --create-startd --add-to-start=https2,https2c,deploy,jsp

 

–create-startdオプションは、本体と設定ファイルが同じ場所にある場合で説明したJettyの起動ファイルの構成に関するオプションになります。デフォルトでは起動するための設定や、起動に必要なモジュールなどを全てstart.iniという単一のファイルに記述することになります。ただ、アプリケーションの規模が大きくなると、このstart.iniという単一のファイルに書いていくのはいささか保守性に欠けます。–create-startdというオプションをつけると、start.dというディレクトリ配下にモジュールごとに個別に設定ファイルを記載する構成になります。こっちのほうがなんかメンテしやすいですよね。

–add-to-startオプションは、このオプションに指定したモジュールの起動設定の雛形をstart.d配下に作ってくれます。–add-to-startオプションに指定したモジュールを説明しますと、https2,https2cはHTTPでリクエストを受け付けるために必要なモジュール(このような単純な処理でさえモジュールを指定しなければなりません)、deployはwebappsディレクトリ配下においたwarをWebアプリケーションとして起動するモジュール、jspはその名のとおりJSPが使えるようになるためのモジュールです。

具体的には先のコマンドで以下のようなディレクトリ構成が出来上がります。

/opt/jetty-base
├── etc
│   └── keystore
├── start.d
│   ├── deploy.ini
│   ├── https2c.ini
│   ├── https2.ini
│   └── jsp.ini
└── webapps

 

では、早速ハロワのWebアプリケーションを起動してみましょう。上記のwebappsディレクトリ配下に先程ビルドしたwarを配置して下さい。そして以下のコマンドを実行して下さい。

$ cd /opt/jetty-base
$ java -jar $JETTY_HOME/start.jar jetty.home=$JETTY_HOME jetty.base=$JETTY_BASE

jetty.homeにはJetty本体がある場所のパス、jetty.baseは今回作成したJettyの設定ファイルがある場所のパスを指定します。

これで、https://[Jettyが稼働しているホスト名]:8080/helloworld/helloにアクセスすると、「Hello World!」が表示されるはずです。

SSL通信やその他の機能などはモジュールを追加して設定すれば実現ができます。Jettyはモジュールが命です( ・ิω・ิ)

まとめ

Jettyについてその概略を説明しましたが、Tomcatとはまた大きく考え方や設定が異なります(モジュールなど)。これらのことについて簡単にまとめた資料がなかったので、今回作成した次第です。誰かのお役に立てれば幸いにございます。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

3人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です