ログ日記

作業ログと日記とメモ

LiftでWebアプリ(2): Lift を更にデザイナーフレンドリーにする

HTMLを分離するところまで。


LiftはHTMLにロジックが入らないからデザイナーでも分かりやすいかと言うと、そんなわけない。
ヘッダをXHTMLで宣言しておいて中身はHTMLだというソースも見たことがある。
プログラマーが更新するHTMLとデザイナーが更新するHTMLを分けたい。


サーバーの設定が大いに絡んでくるが、これも一つの案として。
以前書いたもののまとめ直し。
サーバーGlassFish、OSはDebian squeeze。

更新用ユーザーの作成

Scalaとまったく関係ないが一応書いとく。


ユーザーを追加し、FTPサーバーをインストール。

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でログインしてファイルを更新できるようになった。