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
クラスのオブジェクトが生成されているのです。遷移先でもデータが必要であれば、パラメータとして値を設定する必要があります。
「redirectAction」の動作も同じで、別のActionへの遷移は、それぞれ別のリクエストにより実現されることになります。
これらのリダイレクトを行うResult Typeと似て非なるのが、連載第3回目のサンプルに使用した「chain」というResult Typeです。「chain」は、リダイレクトではなく、同じリクエスト内の処理として別のActionを呼び出します。このとき、Action
クラスのプロパティを、遷移先のAction
クラスに自動でコピーする仕組みがあり、リクエストのパラメータなどが引き継がれることになります(同じ名前のアクセッサメソッドが呼び出されます)。
このような「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";
}
}