バージョンが上がると使用するコマンドが変わる印象のあるxsbt-web-pluginですが、特にソースコードの自動反映とかを忘れがちなので、今一度まとめてみることにしました。
xsbt-web-plugin
https://github.com/earldouglas/xsbt-web-plugin
xsbt-web-plugin 0.1の頃から考えると、これで3度目な気がします…。
使用する前庭の環境は、以下とします。
ソフトウェア名 | バージョン |
---|---|
Scala | 2.11.0 |
sbt | 0.13.2 |
xsbt-web-plugin | 0.9.0 |
Jetty* | 9.1.5.v20140505 |
Embedded Tomcat* | 7.0.53 |
*xsbt-web-pluginのコンテナ用。どちらかを使用します
また、sbtの設定はBasic Configurationとします。
build.sbtとplugins.sbtの設定
まず、plugins.sbtには以下の記述をしておきます。
project/plugins.sbt
addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "0.9.0")
続いて、build.sbt。
build.sbt
name := "hello-servlet" scalaVersion := "2.11.0" // xsbt-web-pluginの設定 seq(webSettings :_*) // WARファイル名から、バージョンの表記を省くための設定 artifactName in packageWar := { (scalaVersion: ScalaVersion, module: ModuleID, artifact: Artifact) => artifact.name + "." + artifact.extension } // 依存関係の設定
普段ならscalacOptionsとか書くところですが、今回はすべて端折りました。
依存関係の部分は、Jettyを使う場合は
val jettyVersion = "9.1.5.v20140505" libraryDependencies ++= Seq( "org.eclipse.jetty" % "jetty-webapp" % jettyVersion % "container", "org.eclipse.jetty" % "jetty-plus" % jettyVersion % "container", // JSPを使う場合は、以下を追加 "org.eclipse.jetty" % "jetty-jsp" % jettyVersion % "container", // Jetty 9は、Servlet 3.1の実装 "javax.servlet" % "javax.servlet-api" % "3.1.0" % "provided" )
Embedded Tomcatを使う場合は
val tomcatVersion = "7.0.53" libraryDependencies ++= Seq( "org.apache.tomcat.embed" % "tomcat-embed-core" % tomcatVersion % "container", "org.apache.tomcat.embed" % "tomcat-embed-logging-juli" % tomcatVersion % "container", "org.apache.tomcat.embed" % "tomcat-embed-jasper" % tomcatVersion % "container", // Tomcat 7は、Servlet 3.0の実装 "javax.servlet" % "javax.servlet-api" % "3.0.1" % "provided", // JSTLを使う場合 "javax.servlet" % "jstl" % "1.2" )
となります。xsbt-web-pluginはTomcat 8に対応していないので、Tomcat 7を使用しています。
なお、Tomcat 7はServlet 3.0の実装なので、厳密にはJetty 9と同じにならないですね…。xsbt-web-pluginのドキュメントは、Jettyを使っていてもServlet 3.0の指定になっていますが。
今回、JSP&JSTLを使用したのですが、そのケースにおいて必要なJARはそれぞれコメントで書いています。Jettyの場合はJSPを使うために「jetty-jsp」への依存関係が必要でJSTLの設定は特になくても動作しました。Embedded Tomcatの場合は、JSTLへの依存関係を別途追加する必要があります。
今更JSP?という話は、さておき…。
Servlet&JSPの作成
動かしてみるために、こんなServletと
src/main/scala/example/HelloServlet.scala
package example import java.io.IOException import javax.servlet.ServletException import javax.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse} class HelloServlet extends HttpServlet { @throws(classOf[IOException]) @throws(classOf[ServletException]) override protected def doGet(req: HttpServletRequest, res: HttpServletResponse): Unit = { val message = "Hello Servlet!" req.setAttribute("message", message) req .getRequestDispatcher("/WEB-INF/view/hello.jsp") .forward(req, res) } }
JSPを作成してみます。
src/main/webapp/WEB-INF/view/hello.jsp
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <title>Hello Servlet & JSP</title> </head> <body> <h1>はじめてのServlet & JSP</h1> <p><c:out value="${message}" /></p> </html>
そして、web.xml
src/main/webapp/WEB-INF/web.xml
<?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"> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>example.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
Servlet 3.0以上なら、アノテーション付ければweb.xml要らなくない?という話もあるかと思いますが、xsbt-web-pluginではうまく動かないようです。というか、認識しませんでした。
起動と停止
コンテナとなっている、JettyまたはTomcatの起動は以下のコマンドで、
> container:start
停止は以下のコマンドで行います。
> container:stop
Commands
https://github.com/earldouglas/xsbt-web-plugin/wiki/Commands
オートリロード
上記のリロードの手順が面倒、またはソースコードの変更を自動で判定して欲しい場合は、以下のようなコマンドを仕込みます。
> ~;container:start; container:reload /
もしくは
> ~;copyResources; auxCompile
もしくは
> ~;compile; container:reload /
など。
このうち、以下はTomcatではコンパイルはしてくれますが、動作中のWebアプリには反映されませんでした…。
> ~;copyResources; auxCompile
WARファイルを作る
packageコマンド
> package
または、packageWarコマンドで。
> packageWar
この時、アーティファクトやScalaのバージョンを入れたくない場合は、
// WARファイル名から、バージョンの表記を省くための設定 artifactName in packageWar := { (scalaVersion: ScalaVersion, module: ModuleID, artifact: Artifact) => artifact.name + "." + artifact.extension }
のように設定してくださいね。
最近まで使っていなかったのですが、使う理由ができた時にコマンドをいろいろ忘れていたので、これを機にまとめなおしです。