LiftでWebアプリ(2): Lift を更にデザイナーフレンドリーにする
HTMLを分離するところまで。
LiftはHTMLにロジックが入らないからデザイナーでも分かりやすいかと言うと、そんなわけない。
ヘッダをXHTMLで宣言しておいて中身はHTMLだというソースも見たことがある。
プログラマーが更新するHTMLとデザイナーが更新するHTMLを分けたい。
サーバーの設定が大いに絡んでくるが、これも一つの案として。
以前書いたもののまとめ直し。
サーバーはGlassFish、OSはDebian squeeze。
更新用ユーザーの作成
Scalaとまったく関係ないが一応書いとく。
adduser app-cart aptitude install vsftpd # chrootを有効にする # /etc/vsftpd.conf を編集 local_enable=YES chroot_local_user=YES chroot_list_enable=YES chroot_list_file=/etc/ftpusers /etc/init.d/vsftpd reload
サーバーや設定はお好みで。
アプリケーションの設定
Boot.scala に
LiftRules.templateCache = Full(NoCache)
を追加してHTMLキャッシュを使わないようにする。
Run Modeがdevelopmentの場合はHTMLはキャッシュされないので、動作確認は後で。
DoctypeがXHTMLまたはHTML5のどちらかっていうのが厳しい場合はHTML4のDoctype出力を書く。
val docType4 = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">""" val props4 = (r: Req) => new Html5Properties(r.userAgent).setDocType(() => Full(docType4)) .setHtmlOutputHeader(() => Full(docType4 + "\n")) : HtmlProperties LiftRules.htmlProperties.default.set(props4)
ここではハードコーディングしているが、汎用的にするならdefault.htmlの一行目から取ってくるなどする。
次にHTMLのディレクトリを分ける。
cd src/main/webapp/ mkdir public mv images index.html static public/
全てpublicディレクトリへ。
このままだとURLにもpublicが必要になるのでUrlRewriteFilterを使ってURLを書き換え。
pom.xml
<dependency> <groupId>org.tuckey</groupId> <artifactId>urlrewritefilter</artifactId> <version>3.2.0</version> </dependency>
import changesと右上に出るのでクリックする。sbt updateも実行する。
WEB-INF/urlrewrite.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN" "http://tuckey.org/res/dtds/urlrewrite3.0.dtd"> <urlrewrite> <rule match-type="regex"> <from>^(/public/|/classpath/|/ajax_request/)(.*)$</from> <to last="true">$1$2</to> </rule> <rule match-type="regex"> <from>^(.*)$</from> <to last="true">/public$1</to> </rule> </urlrewrite>
全てをpublicディレクトリへ転送。publicディレクトリ、その他Liftが自動で生成するパスは省く。
web.xml を変更。
<web-app> <filter> <filter-name>UrlRewriteFilter</filter-name> <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class> </filter> <filter> <filter-name>LiftFilter</filter-name> <display-name>Lift Filter</display-name> <description>The Filter that intercepts lift calls</description> <filter-class>net.liftweb.http.LiftFilter</filter-class> </filter> <filter-mapping> <filter-name>UrlRewriteFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>LiftFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>
public以下のテンプレートを読み込むためにSiteMapも変更する必要が出てきたので Boot.scala を編集する。
def sitemap() = SiteMap( Menu(Loc("TopIndex", Link(List("public", "index"), true, "/index.html"), "Home")) , Menu(Loc("Static", Link(List("public", "static"), true, "/static/index.html"), "Static Content")))
List("public", "index")は実際のパス、"/index.html"はリンク。.html は無くても動くのでお好みで。
この状態だと /user_mgt/login などが動かないが、これは後で考える。
たぶん元々用意されているユーザー操作系ページは使わないと思う。
デザイナーがロールオーバー込みのアイコン画像などを作るだろうからSiteMapからメニュー生成も基本使わない。よってstaticフラグをtrueにして、htmlがあればメニューに関係なくそれを表示するようにしている。
GlassFishの設定と動作確認
管理画面で「設定」→「server-config(利用している設定)」→「JVM 設定」の「JVM オプション」タブの項目に -Drun.mode=production を追加して再起動する。
シンボリックリンクが動くように、WEB-INF/sun-web.xml を作成する。
<?xml version="1.0" encoding="UTF-8"?> <sun-web-app> <property name="allowLinking" value="true"/> </sun-web-app>
sbt package したものを管理画面からデプロイする。
type "dispatcher" must be declared
のエラーが出た場合はweb.xmlのdoctypeを削除する。
「設定」→「server-config(利用している設定)」→「仮想サーバー」→「(利用しているサーバー)」のデフォルトWebモジュールを選択する。
cd glassfish/domains/domain1/applications/cart_2.8.1-1.0/ mv public ~app-cart/ chown -R app-cart:app-cart ~app-cart/public/ sudo -u appserv ln -s ~app-cart/public . # appserv は GlassFish実行ユーザー
ここまで出来たらブラウザで確認する。
su app-cart を実行し、~/public以下のHTMLを変更して更新が反映されるか確認する。
これでFTPからapp-cartでログインしてファイルを更新できるようになった。