3.4 ウェブアプリケーションを作ってみよう

ASTERIAには、ウェブサーバが内蔵されており、ウェブブラウザでASTERIAサーバにアクセスするとフローが起動され、その処理結果をブラウザで確認することができるようになっています。この仕組みを利用することで、ASTERIAの豊富なサービスコンポーネントの機能を利用して、データを扱うウェブアプリケーションを比較的簡単に構築することができます。

ここからはデータベースを検索するウェブアプリケーションを構築することを目的として、実習を進めていきましょう。

3.4.1 データベース参照アプリケーションの構築

まずは検索アプリケーションの基本パターンとして、データベースに入っているデータを全件表示するフローを作ってみましょう。

(1) 構築手順

「WebApp」というプロジェクトに、「WebSearch」というフローを作成します。

次にあげるサービスコンポーネントを配置し、上図のように接続してください。

Component Tab Description
(1) RDB(Get) Storage RDBからの読み込み
(2) Velocity Format Velocityによるデータ差込み
(3) EndResponse Control 終了(レスポンス)

Velocityについては後の「解説」で説明します。

必要なプロパティ設定は次のとおりです。

(1) RDB(Get)
Connection asbook
さらに、Fieldタブで「品目マスタ」テーブルを読み込むように設定します。 ここでは、品番のソート条件に「ASC」を指定しておきます。

(2) Velocity
TemplateFilename input_data/webSearchResult.vm
TemplateEncoding Windows-31J

これで基本フローは完成しました。

(2) 実行してみる

実行する前に、ウェブブラウザからこのフローにアクセスするために、このフローにURLに結びつけます。

そのために、ツールバーの「実行設定」のボタンをクリックして、実行設定の画面を表示します。

まず、実行設定するフローを選択します。ここでは、「WebApp.xfp」の「WebSearch」フローを選択してください。

そして、「URL / MethodName / Schedule」のテキストボックスをクリックして、URLを設定します。ここはデフォルトのままの「http://localhost:21380/guest/WebApp/WebSearch」で構いません。

設定が完了したら、OKボタンを押して、実行設定ダイアログを閉じます。

これで準備が完了しました。さっそく実行してみましょう。

ツールバーの「実行」ボタンをクリックして、実行画面を表示します。

ダイアログが表示されたら、「ブラウザから実行」というラジオボタンを選択して、実行ボタンをクリックしてください。

ウェブブラウザが起動されて、いま作ったフローの実行結果が表示されました。

(3) 解説

このフローでは、データベースから読み出したデータを、VelocityというJSP(Java Server Pages)によく似たテンプレート言語を用いて、テーブルに流し込んでいます。ここでは、その仕組みについて少し触れておきます。

今回用いたテンプレートファイル「searchResult.vm」をエディタで開いてみましょう。

<html>
<head>
<link rel='stylesheet' href='/guest/style.css' type='text/css'>
</head>
<body>

<h1>検索結果</h1>

#if ($in.records.size() == 0)
ヒットするデータがありませんでした
#else
<table border="1">
<tr>
  <th>品番</th>
  <th>品名</th>
  <th>単位</th>
  <th>単価</th>
</tr>
#foreach ($r in $in.records)
<tr>
  <td>$sys.escape($r.field(0))</td>
  <td>$sys.escape($r.field(1))</td>
  <td>$sys.escape($r.field(2))</td>
  <td align="right">$sys.formatDecimal($r.field(3),'###,###')</td>
</tr>
#end
</table>
#end

</body>
</html>

Velocityコンポーネントをダブルクリックすると、テキストエディタが開き、テンプレートファイルを参照・編集することもできます。

このテンプレートを見て、Velocityはレコードで入力されたデータでテーブルを埋めて返します。

Velocityテンプレート言語 (VTL) についての詳細は、VelocityコンポーネントのヘルプおよびApache Jakarta ProjectのVelocityユーザガイドを参照してください。

http://www.jajakarta.org/velocity/velocity-1.2/docs-ja/user-guide.html

以下に、よく使うマクロの例をあげておきます

$in.records 入力ストリーム中の全レコード
#foreach ($r in $in.records) 各レコードを$rに代入して、全レコード分繰り返す
$r.field(i) ($rがレコードなら)レコードのi番目のフィールド
$flow.var フロー変数「var」
$session.var セッション変数「var」
$sys.espace(str) 引数strに含まれる「<」、「>」、「&」、「"」をエスケープする (クロスサイトスクリプティング対策)
$sys.formatDecimal(num, format) 引数numの数値データを、引数formatの形式でフォーマットする

ウェブアプリケーションを構築するときに、データをHTMLページに差し込んで出力することがよくあります。 このとき、データに含まれる「<」、「>」、「&」、「"」をそれぞれ「&lt;」、「&gt;」、「&amp;」、「&quot;」にエスケープする対策が必要です。この対策を行わないと、悪意のある<script>タグなどをデータに埋め込まれたときに、ウェブブラウザで意図しないコードが実行されるセキュリティホールになってしまう可能性があります。これは、クロスサイトスクリプティング脆弱性というセキュリティホールです。

この問題への対策として、Velocityコンポーネントを利用してHTMLページを作る場合には、$sys.escape関数を使って、データ文字列をエスケープするようにしてください。そうすれば、クロスサイトスクリプティング脆弱性に対して安全なウェブアプリケーションを構築することができます。

以下のページに、詳しい解説があるので参照してください。

http://www.atmarkit.co.jp/fsecurity/special/30xss/xss01.html

3.4.2 検索機能の追加

ここまでで、データベースに格納されているデータをテーブルで出力するウェブアプリケーションが構築できました。 つづいて、このアプリケーションに検索機能を追加していきます。

(1) 構築手順

先ほど作ったフローにMapperコンポーネントを追加して、上のようなフローに変更します。

Component Tab Description
(1) Mapper Control データのマッピング
(2) RDB(Get) Storage RDBからの読み込み
(3) Velocity Format Velocityによるデータ差込み
(4) EndResponse Control 終了(レスポンス)
Mapperのプロパティを以下のように変更してください。

(1) Mapper
StreamPassThrough True

StartコンポーネントのArgumentタブに、「key」をString型で追加します。これで、ウェブブラウザでフローを起動するときに、パラメータを受け取れるようにしました。

Argumentについては後の「解説」で説明します。

RDB(Get)コンポーネントのSQLParameterタブに、「key」をString型で追加します。

続いて、RDB(Get)コンポーネントのFieldタブの「品名」のConditionに「like '%$key$%'」と指定します。

Conditionについても後の「解説」で説明します。

最後に、Mapperを上のようにマッピングします。これにより、ウェブブラウザから渡されたパラメータ(検索文字列)が、SQL Parameterを通じて動的にSQL文へ反映されるようになります。

これで、検索機能の追加が完了しました。

(2) 実行してみる

それでは、さっそく実行してみましょう。

http://localhost:21380/guest/search.html」にウェブブラウザでアクセスすると、上の画面が表示されます。この画面は、あらかじめ用意された検索用画面です。検索を実行すると、いま修正した「WebSearch」フローが実行されるように設定されています。

ソースファイルは [HOME]/htdocs/search.html にあります。

検索フォームに「ノート」と入力し、「クエリ送信」ボタンを押して検索を実行してください。

ウェブブラウザからASTERIAサーバに検索キーが送信され、「WebSearch」フローが実行されて品名に「ノート」を含む商品が検索されていることが確認できます。

(3) 解説

フローは、HTTP経由で起動されたときに渡されたパラメータを、StartコンポーネントのArgumentとして受け取ることができます。HTMLフォームからウェブサーバにデータを送信する方法には、「GET」と「POST」の2つの方法がありますが、どちらの方法を使ってもASTERIAでは同じように受け取ることができます。

今回の実習では、HTMLフォームの入力から「key」というパラメータをArgument「key」で受け取っています。この仕組みを利用することで、ユーザがHTMLフォームに入力したデータを受信することができるわけです。

「GET」と「POST」のどちらを使うかは、HTMLフォームの method属性で指定します。 以下の例では「POST」を指定しています。

<form method="post" action="/guest/WebApp/WebSearch">
<input type="text" size="30" name="key">
<input type="submit">
</form>

HTMLフォームで「GET」と「POST」のどちらを使うかという選択の基準は、以下を参考にしてください。

  • GET
    • 入力されたデータはURLの一部として送信される
    • つまり、入力データの一部がウェブブラウザのアドレスバーに表示される
    • パスワードや個人情報など、秘匿性の高いデータの送信には利用しないほうがよい
    • 255バイトを超える長いデータを送信できない
  • POST
    • 入力されたデータはURLとは別に送信される
    • つまり、入力データがウェブブラウザのアドレスバーに表示されることはない
    • 秘匿性の高いデータの送信に利用すべき
    • 255バイトを超える長いデータを送信できる

つまり、特別な理由がない限りは「POST」を利用しておいたほうが安全と言えます。

なお、「GET」と「POST」の違いについては、以下のページに解説がありますので、参考にしてください。

http://www.futomi.com/lecture/form/

RDB(Get)コンポーネントは、SQLParameterタブに「key」を追加することで、Fieldタブで「品名」のCondition式に「like '%$key$%'」の「$key$」という部分へのパラメータの差し込みができるようになっています。今回の場合には、ユーザが入力した「ノート」という値が差し込まれ、「like '%ノート%'」という条件でSQL文が発行されたというわけです。つまり、発行されたSQLは次のようになります。

SELECT 品番,品名,単位,単価 FROM 品目マスタ WHERE 品名 like '%ノート%'

このSQLを実行した結果、「品名」フィールドに「ノート」を含むレコードが結果的に出力されました。

なお、SQLのLIKE演算子でのワイルドカードを使う検索方法については、以下のページに解説がありますので、興味がある方は参照してください。

http://www.atmarkit.co.jp/fnetwork/rensai/sql01/sql1.html

以上で、データベースを検索するウェブアプリケーションを構築が完了しました。これでウェブアプリケーションを構築する手順をつかんでいただけたかと思います。この内容を踏まえて、さまざまなコンポーネントを組み合わせた、より高度なウェブアプリケーションの構築に、ぜひチャレンジしてみてください。