Java
SparkFramework

Sparkのリクエスト受付時の流れ

はじめに

SparkFrameworkに関する情報です。

基本的な情報は下記を見てください。

http://sparkjava.com/

Requestを受信したときのシーケンス

Sparkがリクエストを受け付けたときの処理のシーケンス図を作りました。
ソースを読んでいて色々わかったこともあので、メモを残します。

Sparkのイメージ

実際のシーケンス図の前に、公式ページに載っている内容から想定するシーケンス図を張っておきます。

spark_frame.png

実際のシーケンス

spark_request.png

わかったこと

Routeインスタンス

利用者が独自に実装するクラスとして、Route、Filter、ExceptionHandlerがありますが、
これらは最初にSparkに設定したインスタンスを利用し続けます。

従ってスレッドセーフな作りにする必要があります。

URLに複数マッチしたときの挙動

Route、Filter、ExceptionHandlerのそれぞれによってマッチ処理に違いがあるため、注意が必要です。

Route

Routeは1番最初にマッチしたものが実行されます。
評価は定義された順に行われます。

実行例は下記のとおりです。

サンプルプログラム

public static void main(String[] args) {
  get("/hello", (request, response) -> "hello");
  get("*", (request, response) -> "*");
}

上記のプログラムに対し、http://localhost:4567/hello にアクセスしたときの表示結果は下記のとおりです。

hello

Filter

beforeFilter、afterFilter、afterAfterFilterは、マッチしたものすべてが実行されます。
実行順序は定義された順になります。

サンプルプログラム

public static void main(String[] args) {

  before((request, response) -> {
    System.out.println("before 1");
  });

  before("/hello", (request, response) -> {
    System.out.println("before 2");
  });

  get("/hello", (request, response) -> "hello");
    System.out.println("hello");
    return "hello";
  });

  after((request, response) -> {
    System.out.println("after 1");
  });

  after("/hello", (request, response) -> {
    System.out.println("after 2");
  });

  afterAfter((request, response) -> {
    System.out.println("afterAfter 1");
  });

  afterAfter("/hello", (request, response) -> {
    System.out.println("afterAfter 2");
  });
}

上記のプログラムに対し、http://localhost:4567/hello にアクセスするとコンソールには下記が表示されます。

before 1
before 2
after 1
after 2
afterAfter 1
afterAfter 2

ExceptionHander

ExceptionHanderは、定義されたExceptionに一番近いもののみ実行されます。

サンプルプログラム

public static void main(String[] args) {

  get("/hello", (request, response) -> {
    if (true) {
      throw new RuntimeException();
    }
    return "hello";
  });

  exception(Exception.class, (exception, request, response) -> {
    System.out.println("Exception");
  });

  exception(RuntimeException.class, (exception, request, response) -> {
    System.out.println("RuntimeException");
  });
}

上記のプログラムに対し、http://localhost:4567/hello にアクセスするとコンソールには下記が表示されます。

RuntimeException

haltメソッドが利用できる箇所

haltメソッドを呼び出すと、HaltExceptionがthrowされます。
仕様なのか考慮もれなのかわかりませんが、HaltExceptionが処理される場所は限られており、
有効でない場所があります。

haltメソッドが有効なのは下記です。

BeforeFilter、AfterFilter、Route

下記は利用しても、想定通りの動きはしません。

AfterAfterFilter、ExceptionHandler