読者です 読者をやめる 読者になる 読者になる

( ꒪⌓꒪) ゆるよろ日記

( ゚∀゚)o彡°オパーイ!オパーイ! ( ;゚皿゚)ノシΣ フィンギィィーーッ!!!

scalaのWebフレームワーク liftで遊ぶ(4) - もっとこんにちわ世界

目次はこちら。
scalaのWebフレームワーク liftで遊ぶ 目次 - ゆろよろ日記


定番のHello Worldの次は…


やっぱりHello Worldです。
を見ながら、今度はformを追加してAjax的なことまで100%やっちゃうよ。


今回は、これまでのおさらい的な内容でっせ。
ではさっそく。

プロジェクト作成

今までのおさらいも兼ねて、新しくhellodrawnプロジェクトを作成する。


mavenのコマンドでゴー。

mvn archetype:generate -U -DarchetypeGroupId=net.liftweb -DarchetypeArtifactId=lift-archetype-blank -DarchetypeVersion=0.9 -DremoteRepositories=http://scala-tools.org/repo-releases -DgroupId=com.yuroyoro.lift.hellodarwin -DartifactId=hellodarwin

cd hellodrawn
mvn eclipse:eclipse

groupIdだけ変えてます。ついでにプロジェクトをEclipse用にしておく。
Eclipseにプロジェクトをインポートして準備完了だ。

静的ページ

src/main/webapp/helloStatic.html を作成。

<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
    <h1>Static HTML</h1>
    Hello world
  </body>
</html>

http://localhost:8080/helloStatic.htmlでこんにちわ。


SiteMapに登録。
src/main/scala/bootstrap/liftweb/Boot.scala

    // Build SiteMap
    val entries = Menu(Loc("Home", "/", "Home")) ::  
        Menu(Loc("Hello1.1", "/helloStatic", "Hello Static")) ::
        Nil 

ヘッダーを追加する


src/main/webapp/helloStatic2.html を作る。

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
        <meta name="description" content="" />
        <meta name="keywords" content="" />		
        <title>Hello Darwin</title>
    </head>
    <body>
        <h1>Static HTML 2</h1>
        Hello world
    </body>
</html>

Bootクラスも修正。

    val entries = Menu(Loc("Home", "/", "Home")) ::
      Menu(Loc("Hello1.1", "/helloStatic", "Hello Static")) ::
      Menu(Loc("Hello1.2", "/helloStatic2", "Hello Static2")) ::
      Nil

http://localhost:8080/helloStatic2でアクセスするとtitleが出る。って当たり前。

snippetを使ってメニュー追加する。

今度は、SiteMapのメニューと、エラーメッセージを出力できるようにする。

src/main/webapp/helloStatic3.htmlを作成する。

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
        <meta name="description" content="" />
        <meta name="keywords" content="" />
        <title>Hello Darwin</title>
        <lift:CSS.blueprint />
        <lift:CSS.fancyType />
        <script id="jquery" src="/classpath/jquery.js" type="text/javascript"/>
        <script id="json" src="/classpath/json.js" type="text/javascript"/>
    </head>
    <body>
        <h1>+/- Static HTML 3</h1>
        Hello world
    <lift:Menu.builder />
    <lift:msgs />
    </body>
</html>

いくつか知らないタグが出てきた。

    • Liftのjarに含まれているblue printというCSSを出力する
  • <script id="jquery" src="/classpath/jquery.js" type="text/javascript"/>
    • jqueryを使用するためのscriptタグ。LiftではJavascript frameworkとしてJQueryとjson.jsを利用するらしい。
    • LiftではURLが/classpath/から始まる場合、クラスパス上からリソースを検索するらしい。
    • 詳しくはnet.liftweb.http.ResourceServeを見ろってよ。
    • SiteMapに登録されているパスでメニューを出力する
    • エラーメッセージが設定されていれば出力する。

テンプレートの共有

要はレイアウトの話。

すでにsrc/main/webapp/templates-hidden/default.htmlにデフォルトのテンプレートがあるので、こんな感じに修正する。

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
        <meta name="description" content="" />
        <meta name="keywords" content="" />

        <title>Hello Darwin</title>
        <lift:CSS.blueprint />
        <lift:CSS.fancyType />
        <script id="jquery" src="/classpath/jquery.js" type="text/javascript"/>
        <script id="json" src="/classpath/json.js" type="text/javascript"/>
    </head>
    <body>
        <lift:bind name="content" />
        <lift:Menu.builder/>
        <lift:msgs/>
    </body>
</html>

src/main/webapp/helloStatic4.html も作る。

<lift:surround with="default" at="content">
    <h1>+/- Static HTML 4</h1>
    Hello world
</lift:surround>

で囲むとデフォルトのテンプレートが適用されることが確認できた。
:

  • with="default"
    • templates-hidden/default.html を使用する。template-hiddenフォルダ以下から[id].htmlでテンプレートを検索するらしい。
  • at="content"
    • テンプレート内のに出力するという指定。

例によって、SiteMapに登録してhttp://localhost:8080/helloStatic4で確認。OKです。

    val entries = Menu(Loc("Home", "/", "Home")) ::  
        Menu(Loc("Hello1.1", "/helloStatic", "Hello Static")) ::
        Menu(Loc("Hello1.2", "/helloStatic2", "Hello Static2")) ::
        Menu(Loc("Hello1.3", "/helloStatic3", "Hello Static3")) ::
        Menu(Loc("Hello1.4", "/helloStatic4", "Hello Static4")) ::
        Nil 

snippetを追加する。

静的なsnippet

固定値を出力だけのsnippetを作ってみる。

src/main/scala/com/yuroyoro/lift/hellodrawin/snippet/HelloSnippet.scalaを以下の内容で作成する。

package com.yuroyoro.lift.hellodarwin.snippet

class HelloSnippet {
  def show = <tt>Friends</tt>
}

以下の内容でsrc/main/webapp/helloSnippet.htmlを作成しておく。

<lift:surround with="default" at="content">
    <h1>Hello Snippet</h1>
    Hello <lift:snippet type="HelloSnippet:show" />
</lift:surround>

がsnippetからの出力で置き換えられる部分だ。

  • type="HelloSnippet:show"
    • HelloSnippetクラスのshowメソッドの出力を置き換えるという意味。
    • snippetはNodeSeqオブジェクトを返す必要がある。scalaXMLリテラルを使うと自動的にNodeSeqになる。

snippetクラスはどうやって検索されるか?

Bootクラスで、以下のようにpackageを設定しておくと、その配下の"snippet"パッケージからクラスを検索するようになっている。
この定義は、プロジェクトを作成したときにすでに追加されているので、新しいsnippetクラスをsinippetパッケージに追加すれば利用可能となる。

    // where to search snippet
    LiftRules.addToPackages("com.yuroyoro.lift.hellodarwin")     

SiteMapに登録して、http://localhost:8080/helloSnippetで動作確認。

    // Build SiteMap
    val entries = Menu(Loc("Home", "/", "Home")) ::  
        Menu(Loc("Hello1.1", "/helloStatic", "Hello Static")) ::
        Menu(Loc("Hello1.2", "/helloStatic2", "Hello Static2")) ::
        Menu(Loc("Hello1.3", "/helloStatic3", "Hello Static3")) ::
        Menu(Loc("Hello1.4", "/helloStatic4", "Hello Static4")) ::
        Menu(Loc("Hello2.1", "/helloSnippet", "Hello Snippet")) ::
        Nil 
動的なsnippet

今度は、出力内容が動的に変更されるsnippetを作成する。

先ほど作成したHelloSnippetクラスに、usernameというメソッドを追加する.

package com.yuroyoro.lift.hellodarwin.snippet

class HelloSnippet {
  def show = <tt>Friends</tt>
  
  def username = <tt>{System.getProperty("user.name")}</tt>

}

XMLリテラル内で{}で囲った部分にはscalaコードを書くことができる。perlrubyみたいな感じ。


追加したメソッドを利用するhtmlファイルを、src/main/webapp/helloSnippet2.htmlとして以下の内容で作成する。

SiteMapにも登録する。めんどくさいからもう省略する。

<lift:surround with="default" at="content">
    <h1>Hello Snippet2</h1>
    Hello <lift:snippet type="HelloSnippet:username" />
</lift:surround>