Result処理
Struts 2のViewは、URIリクエストから実行されたActionクラスの処理結果や状態を出力するレイヤーです。デフォルトでは、JSPファイルをテンプレートとして、HTMLが生成されます。またHTMLだけでなく、プレーンなテキストであったり、画像データなどのバイナリデータを指定することもできます。
リクエストからレスポンスまでの処理フロー

Result Type
ちょっとこれまでのサンプルコードをふりかえってみましょう。URIリクエストから実行されるActionクラスのメソッドでは、処理結果を"success"などの文字列で返すようにしていました。この結果の文字列を受けて、どのような処理をさせるかは、struts.xml の<result>タグで設定しています。例えば次のように指定すると、結果が"success"のときにindex.jspを用いた出力となります。
<result name="success">/index.jsp</result>
実はこれは既定値を利用した書き方で、タグを省略しないで書くと、次のようになります。
<result name="success" type="dispatcher">
<param name="location">/index.jsp</param>
</result>
type属性で処理のタイプを指定し、<param>タグでその処理のパラメータを指定します。このtype属性で指定している"dispatcher"の実体は、struts-default.xmlにて設定されているorg.apache.struts2.dispatcher.ServletDispatcherResultクラスです。JSPファイルを解釈して、 HTMLを生成する処理を行います。
<result>タグのtype属性(Result Type)を変更することで、処理を切り替えることができます。Struts 2で用意されているResult Typeは次の表の通りです。これは、本連載の第3回目でも少しふれていますが、さらに詳しく見ていくことにしましょう。
Result Type一覧
| Result Type | 概要 | 種別 |
| chain | 別のActionクラスを呼び出す | 遷移 |
| redirect | 指定したURLにリダイレクトする | |
| redirectAction | 指定したActionにリダイレクトする | |
| dispatcher | JSPファイルをテンプレートとしてHTML を生成する(デフォルト) | データ生成 |
| freemarker | 汎用テンプレートエンジンのFreeMarkerを使用してHTMLを生成する | |
| velocity | 汎用テンプレートエンジンのVelocityを使用してHTMLを生成する | |
| xslt | XSLTを使用してHTML(XML)を生成する | |
| httpheader | HTTPのステータスヘッダだけを生成する | |
| stream | バイナリデータをそのままクライアントに返す。ファイルのダウンロード等に利用する | |
| plainText | プレーンテキストとして、そのままクライアントに返す | |
| tiles | Tilesフレームワークを利用してHTMLを生成する | |
| jasper | オープンソースの帳票ライブラリJasperReport利用したレスポンスを生成する |
chainとリダイレクトとの違い
Result Typeは大別すると、HTMLなどデータを生成するタイプと、他のActionを呼び出したりリダイレクトを行ったりする遷移タイプに分かれます。HTMLを生成するタイプは後述することにして、まずは、遷移するタイプを説明しましょう。
Result Typeの「redirect」と「redirectAction」は、いわゆるHTTPリダイレクトを行うものです。つまり、<param>タグのlocationで指定したURIに、クライアントからあらたにリクエストが発生する形になります。
例えば、次のように記述すると、"success"の場合、sample.jspへリダイレクトします。
<result name="success" type="redirect">
<param name="location">sample.jsp</param>
</result>
ここで気をつけたいのは、この処理は、デフォルトの処理であるjspファイルを利用したHTMLを生成する動作とは異なるということです。この例では、単にsample.jspへ遷移するだけであり、sample.jspでは、遷移元のリクエストで生成されたActionクラスのオブジェクトを参照することはできません。別のリクエストになっているため、元のオブジェクトは破棄され、あらたなActionクラスのオブジェクトが生成されているのです。遷移先でもデータが必要であれば、パラメータとして値を設定する必要があります。
「redirect」の処理フロー

「redirectAction」の動作も同じで、別のActionへの遷移は、それぞれ別のリクエストにより実現されることになります。
「redirectAction」の処理フロー

これらのリダイレクトを行うResult Typeと似て非なるのが、「chain」というResult Typeです。「chain」は、リダイレクトではなく、同じリクエスト内の処理として別のActionを呼び出します。このとき、Actionクラスのプロパティを、遷移先のActionクラスに自動でコピーする仕組みがあり、リクエストのパラメータなどが引き継がれることになります(同じ名前のアクセッサメソッドが呼び出されます)。
「chain」の処理フロー

このような「chain」の処理は、Action間にまたがる処理のため、他のResult Typeと違って、前回説明したインターセプターとして実装されています。
なお、実は「chain」は利用を推奨されていません。データをひきつれてActionを遷移すると、いわゆるスパゲッティコードになる恐れがあるためです。処理の流れや構造が把握しにくいアプリケーションにならないよう、「chain」の使用には十分な検討が必要です。
Struts 2では、Actionクラスはできるだけシンプルに設計することが望ましいとされています。Actionクラスは、あくまでWebページからの窓口とし、主要な処理は別のクラスとして実装する構造(デザインパターンのFacadeパターンにあたる)が、アプリケーションの構造として推奨されています。
このような構造では、セッション単位のデータをページ間にまたがって保持する方法が気になるところですが、このあたりはまた回をあらためて解説することにします。
データを生成するResult Type
このタイプのResult Typeは、デフォルトの「dispatcher」をはじめとした、HTMLやバイナリデータを生成するものです。ここでは、いくつか個別にとりあげてみます。
httpheader
「httpheader」は少し変わっていて、レスポンスにコンテンツがなく、HTMLのヘッダーだけをクライアントに返すResult Typeです。例えば、struts.xmlに次のように記述すると、ページがみつからない場合におなじみの404コードを返すことができます。
<result name="success" type="httpheader">
<param name="status">404</param>
<param name="headers.test1">custom header1</param>
<param name="headers.test2">custom header2</param>
</result>
<param>タグで、独自のヘッダー文字列を設定することもできます。このサンプルの場合、実際のレスポンスヘッダーは次のようになります。
HTTP/1.x 404 Not Found
Server: Apache-Coyote/1.1
test1: custom header1
test2: custom header2
Content-Type: text/html;charset=utf-8
Content-Length: 977
plaintext
プレーンなテキストをクライアントに返すResult Typeです。ソースファイルの表示など、テキストをそのまま表示させたい場合に用いるもので、次のように指定します。
<result name="success" type="plaintext">
<param name="location">/sample.txt</param>
<param name="charSet">UTF-8</param>
</result>
パラメータのlocationでファイルパス名、charSetで、文字コードの種別を記述します。
stream
「stream」は、java.io.InputStreamクラスを用いたバイト列のデータをクライアントに返します。画像ファイルやPDFファイルなどを動的に生成してダウンロードする場合などに便利に使えます。例えば、次のstruts.xmlの設定例では、sample.pngという画像ファイルをダウンロードデータとして指定しています。
<action name="SampleAction" method="download" class="SampleAction">
<result name="success" type="stream">
<param name="contentType">application/octet-streamg</param>
<param name="contentDisposition">attachment; filename="sample.png"</param>
</result>
</action>
<param>タグには、HTTPレスポンスヘッダに応じたパラメータを指定します。このサンプルでは、pngファイルをブラウザに表示させるのではなく、ダウンロードデータとするために、ContentTypeとContentDispositionに値を設定しています。このふたつ以外のパラータでは、特にデフォルト値を変えなくても動作します。
なお、「stream」では、設定ファイルだけでなく、Actionクラスにも前述したInputStreamクラスを使ったコードが必要です。
まずActionクラスには、InputStreamを返すプロパティを定義します。デフォルトでは、inputStreamという名前でゲッターを参照しますので、getInputStreamメソッドを定義し、フィールドのinputStreamを返すようにします。そして、ダウンロードの処理としては、FileInputStreamクラスを使ってファイルを読む込むようにし、inputStreamに設定します。
public class SampleAction {
private InputStream inputStream;
public InputStream getInputStream() {
return inputStream;
}
// ダウンロードActionメソッド
public String download() throws Exception {
this.inputStream = new FileInputStream("sample.png");
return "success";
}
}
Struts Tag
最終的にHTMLを表示するViewレイヤーでは、Actionクラスのデータやセッションで保持する情報にアクセスすることが不可欠です。Struts 2では、カスタムタグ(Struts Tag)を用いて、そのようなデータを扱うことになります。
またStruts Tagには、それ以外にも、フォームなどのユーザーインターフェイスのタグ(UIタグ)や、条件判定を行うタグ、さらにはJavaScriptが組み込まれたAjax機能のタグもあります。
3つのテンプレートエンジン
Struts 2では、JSPに加え、「freemarker」や「velocity」といった3つのテンプレートエンジンに対応しており、Struts Tagも3つのテンプレートで使用することができます。Struts Tagは、基本的にViewの実装とは切り離されており、テンプレートの文法によって若干書式が異なるだけで、同じように使えます。
なお、JSPの標準的なカスタムタグであるJSTLもサポートしていますが、EL式には対応していません。そのため、EL式固有の表記を使用することはできませんので、OGNL式で記述する必要があります。
以下、Struts Tagsを表にまとめています。タグの個別の詳細については、Struts 2のドキュメントを参照してください。
UIタグ
UIタグは、その名の通りユーザーがデータを操作するタグで、checkboxやselectといった通常のHTMLタグを拡張したものが中心です。UIタグの特徴的な機能の一つに「テーマ」機能があります。FreeMarkerのテンプレート機能を組み合わせて、コントロールを「テーマ」に従ってレンダリングすることができる機能です。
UIタグ一覧(ファームタグ)
| タグ名 | 説明 |
| checkbox | <input type="checkbox">と同じ |
| combobox | コンボボックス(テキストボックス+プルダウンメニュー) |
| form | HTMLタグと同じ |
| hidden | <input type="hidden">と同じ |
| password | <input type="password"> と同じ |
| select | HTMLタグと同じ |
| textarea | HTMLタグと同じ |
| radio | <input type="radio">と同じ |
| reset | <input type="reset">と同じ |
| submit | <input type="submit">と同じ |
| textfield | <input type="text">と同じ |
| head | HEADタグ内でthemeの指定などを行う時に使用 |
| optiontransferselect | 2つのセレクトボックスで連携処理を行う |
| optgroup | セレクトボックスのグループ分け表示 |
| token | Submitのダブルクリック防止用 |
| updownselect | セレクトボックスの要素を上下移動させる |
| doubleselect | 連携動作する2つのセレクトボックス |
| file | ファイルアップロード用 |
| checkboxlist | 複数のチェックボックスを作成 |
| label | 文字列表示 |
UIタグ一覧(Form以外のUIタグ)
| タグ名 | 説明 |
| actionerror | エラー表示用のメッセージ |
| actionmessage | Actionオブジェクトのメッセージ表示 |
| component | テンプレート定義用 |
| div | HTMLのタグと同じ |
| fielderror | 入力エラーを表示 |
UIタグ一覧(Ajaxタグ)
| タグ名 | 説明 |
| a | XMLHttpRequestを呼び出す |
| autocompleter | 入力補完機能 |
| bind | イベント待ち処理 |
| datetimepicker | カレンダーを表示した日付選択 |
| div | XMLHttpRequestを呼び出す |
| tree | ツリー構造の表示 |
| treenode | |
| tabbedpanel | タブ形式のページ表示 |
ただ、標準のxhtmlテーマは、コントロールをTableタグで配備したりするので、昨今のWebレイアウトには合わない部分も少なくないでしょう。テンプレートを自作したりして、テーマをカスタマイズすることはできますが、テンプレートの変更は面倒な場合が多くて不便です。もう一つの方法として、Tilesプラグインの利用を検討した方がよいかもしれません。「Tiles」とは、複数のJSPファイルを1枚のWebページに合成する機能です。Webページのヘッダーやフッターなど、共通して使う部分を独立して定義することができます。
その他UIタグには、Ajaxタグなど便利そうなものもありますが、かゆいところに手が届かないものも多く、状況に応じて利用することが肝要です。
汎用タグ
汎用タグは、Struts 2のドキュメントの分類では、制御タグとデータタグに分かれています。
汎用タグ一覧(制御タグ)
| タグ名 | 説明 |
| if | 条件判定を行う |
| elseIf | |
| else | |
| append | 複数の要素リストを連結する |
| generator | iteratorタグで処理できる要素を生成する |
| iterator | 要素リストから、ひとつずつ要素を取り出す |
| merge | 複数の要素リストを合成する |
| sort | 要素をソートする |
| subset | 要素リストの一部分を切り出す |
汎用タグ一覧(データタグ)
| タグ名 | 説明 |
| a | HTMLのタグと同じ |
| action | Actionを呼び出す |
| bean | JavaBeansの生成 |
| date | 日付表示 |
| debug | Value Stack(内部データ)の表示 |
| i18n | メッセージリソースの変換 |
| include | JSPファイルなどの呼び出し |
| param | struts.xmlの<param>タグを読み出す |
| property | オブジェクトのプロパティを参照する |
| push | Value Stack(内部データ)にデータを格納 |
| set | 変数に値をセットする |
| text | 国際化に対応した文字列表示 |
| url | URLの生成 |
制御タグは、結果として返すHTMLにはまったく現れないタグです。条件判定を行ったり、内部のデータを操作するものです。
データタグには、変数の表示など何らかの結果をレスポンスのHTMLで利用するもの、Actionを呼び出したりするものがあります。
0 件のコメント:
コメントを投稿