blog1.mammb.com からの続きで、簡単な Hello Scalatra をしてみます。
Scalatra とは
web micro-framework とされている通り、非常にコンパクトな Web フレームワークです。
以下のような Sinatra 風の DSL が利用できます(Scala + Sinatra = Scalatra)。
get("/") { <h1>Hello, {params("name")}</h1> }
Play と異なり、サーブレットコンテナ上で動作します。
HTTP リクエストのルーティング機能を主として提供しています。
build.gradle
Scala は 2.11系を使うので、scalatra_2.11
を依存に追加します。
また今回はスタンドアロンで動かすので jetty-webapp
と、モジュールが分割して提供されるようになった scala-xml
も追加します。
build.gradle は以下のようになります。
apply plugin: 'scala' apply plugin:'application' repositories { jcenter() } dependencies { compile 'org.scala-lang:scala-library:2.11.6' compile 'org.scala-lang:scala-xml:2.11.0-M4' compile 'org.scalatra:scalatra_2.11:2.4.0.RC1' compile 'org.eclipse.jetty:jetty-webapp:9.3.0.RC1' testCompile 'junit:junit:4.12' testCompile 'org.scalatest:scalatest_2.11:2.2.4' testRuntime 'org.scala-lang.modules:scala-xml_2.11:1.0.3' } mainClassName = 'JettyLauncher'
メインクラスとして JettyLauncher
を定義しています。これは後ででてきます。
プロジェクト構成
簡単のため全部ルートパッケージに入れます。 以下のような構成になります。
└── src ├── main │ ├── scala │ │ ├── JettyLauncher.scala │ │ ├── ScalatraBootstrap.scala │ │ └── HelloServlet.scala │ └── webapp │ └── WEB-INF │ └── web.xml └── test └── scala
各ソースを作成していきましょう。
web.xml
最初に web.xml
を作成します。
mkdir -p src/main/webapp/WEB-INF && touch src/main/webapp/WEB-INF/web.xml
Scalatra 2.3 以降から Servlet 3.1 に対応しています。 中身は以下のようになります。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <listener> <listener-class>org.scalatra.servlet.ScalatraListener</listener-class> </listener> </web-app>
listener として ScalatraListener
を登録するだけのシンプルなものです。
HelloServlet
サーブレット用のクラスを作成します。
touch src/main/scala/HelloServlet.scala
ScalatraServlet
を継承した HelloServlet
とします。
import org.scalatra.ScalatraServlet class HelloServlet extends ScalatraServlet { get("/") { <html> <body> <h1>Hello, world!</h1> Say <a href="hello-scalate">hello to Scalate</a>. </body> </html> } }
Sinatra 風 DSL で GETリクエストを受けた場合に HTML を返却するだけです。
ScalatraBootstrap
ScalatraBootstrap を作成します。 通常このクラスはパッケージルートに配備します。
touch src/main/scala/ScalatraBootstrap.scala
中身は LifeCycle を継承したクラスとなります。
import org.scalatra._ import javax.servlet.ServletContext class ScalatraBootstrap extends LifeCycle { override def init(context: ServletContext) { context.mount(new HelloServlet, "/*") } }
このクラスで先ほど作成した HelloServlet のインスタンスを ServletContext
へマウントしています。
web アプリケーションとして必要なものはこれで終わりで、war をコンテナに配備すれば動きます。
JettyLauncher
今回はスタンドアロンアプリケーションとして動かすために、Jetty のランチャオブジェクトを作成します。
touch src/main/scala/JettyLauncher.scala
Jetty の設定と起動を行います。
import org.eclipse.jetty.server.Server import org.eclipse.jetty.servlet.{DefaultServlet, ServletContextHandler} import org.eclipse.jetty.webapp.WebAppContext import org.scalatra.servlet.ScalatraListener object JettyLauncher { def main(args: Array[String]) { val port = if(System.getenv("PORT") != null) System.getenv("PORT").toInt else 8090 val server = new Server(port) val context = new WebAppContext() context setContextPath "/" context.setResourceBase("src/main/webapp") context.addEventListener(new ScalatraListener) context.addServlet(classOf[DefaultServlet], "/") server.setHandler(context) server.start server.join } }
実行
application プラグインの run タスクを実行します。
gradlew run
ブラウザでアクセスすれば以下のようになります。
この後は?
scalatra の examples を見るのが手っ取り早いです。
次回は Scalate いってみます。