Skip to content

Instantly share code, notes, and snippets.

@tanishiking
Created May 28, 2017 00:41
Show Gist options
  • Save tanishiking/7c0e0a13c741af59d85ad85234ae6906 to your computer and use it in GitHub Desktop.
Save tanishiking/7c0e0a13c741af59d85ad85234ae6906 to your computer and use it in GitHub Desktop.

目的

Scalatraのもやもや下部分をはらす

  • ScalatraBootstrap ってなんやねん
  • WEB-INF/web.xml とは...

はじめに

Servlet

Servletとはサーバ上でWebページなどを動的に生成したりデータ処理を行うために、Javaで作成されたプログラム及びその仕様。(pythonのwsgi/Perlのpsgi的な) このServletを実装した(?)ScalaでのWAFの一つがScalatra

以下ではサーブレットは、Servletにより実装されたWebアプリケーションプログラムという意味で用いることにする サーブレットは、サーブレットコンテナと呼ばれるWebサーバーで動く

サーブレットコンテナ

サーブレットの基礎知識 サーブレットコンテナはサーブレットを実行/制御するための実行環境Javaプログラム

  • サーブレットのオブジェクトを生成して、メモリにロードしインスタンス化
  • サーブレットのinit() メソッドを一回だけ呼び出してサーブレット固有の値を定めることができる
  • クライアントからのHTTPリクエストに応じてリクエストごとにスレッドを割り当てて、サーブレットのservice() メソッドを呼び出し
    • リクエストやレスポンスは HttpServletRequestHttpServletResponse というオブジェクトに包んでやりとりする
  • サーブレットコンテナは、サーブレットのインスタンスを一つだけ作る。
  • サーブレットコンテナはマルチスレッド、あらかじめスレッドをいくつか作っておき、リクエストをスレッドに捌かせる。各スレッドはHTTPリクエストからHttpServletRequestを作り、サーブレットインスタンスのメソッドを呼び出す

HttpServlet

はじめてのServlet

  • サーブレットプログラムは通常 javax.servlet.servlet.HttpServlet を継承して作る
  • HttpServlet は抽象クラス、以下の順番のライフサイクルを送る
    • public void init(ServletConfig config) throws ServletException
    • protected void service(HttpServletRequest req, HttpServletResponse resp)
    • destroy()
      • サーブレットコンテナのリソースが少なくなり、一定時間Servletプログラムにアクセスがない場合や、サーブレットコンテナを終了する場合などにサーブレットコンテナからdestroyメソッドが呼び出される。

クライアントからのデータ取得

HttpServletRequest

上記で述べた ScalatraBase 内で処理を行なっていく。 ScalatraBase では org.scalatra.servlet.ServletApiImplicits._ がインポートされている。ServletApiImplicitsHttpServletRequestRichRequestというラッパーに変換するimplicit conversionをもつ。

ちなみに HttpServletRequest は以下のようなメソッドをもつ

クライアントへのデータ返信

HttpServletResponse

HttpServletRequest と同様に、HttpServletResponseRichResponseに変換される

リスナー(ServletContext)

ServletContextオブジェクト関連のイベントが発生した際に呼び出されるリスナー

  • ServletContextListener
    • サーブレットコンテキスト(Webアプリケーション)が起動するときや破棄されるときに呼び出される。そのため、Servletプログラムの初期化処理をしたい場合や、終了処理をしたい場合に使用します。
    • ScalatraではScalatraListenerで実装
      • contextInitialized(ServletContextEvent sce): Webアプリケーションが初期化処理をはじめたこと通知を受けて動作
        • ScalatraListener.configureCycleClassにより指定した LifeCycle を継承したクラスがロードされ、その init() メソッドが呼び出される
        • これがscalatraでおまじない的に実装されられる class ScalatraBootstrap extends LifeCycle
      • contextDestroyed(ServletContextEvent sce)
  • ServletContextAttributeListener
    • 特に使われてない

context.mount

LifeCycle の中で ServletContextRichServletContext に暗黙変換する context.mount はhandlerをURLのpathにマウントさせる

web.xml の設定

リスナーを利用する場合、リスナーインターフェースを実装したリスナークラス(scalatraではScalatraListener)をweb.xmlに指定する必要がある。

src/scala/ScalatraBootstrap.scala があって、だいたいこうなってる

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0">

  <!--
    This listener loads a class in the default package called ScalatraBootstrap.
    That class should implement org.scalatra.LifeCycle.  Your app can be
    configured in Scala code there.
  -->
  <listener>
    <listener-class>org.scalatra.servlet.ScalatraListener</listener-class>
  </listener>
</web-app>

これにより、ScalatraListener.contextInitialized により ScalatraBootstrap.init が呼び出される 正直、ScalatraListenerがScalatraBootstrapをロードするコードがよくわかってない

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment