このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
Struts のコアは、RequestProcessor というクラスである。
Struts 1.3.5 においては、このクラスは拡張され、
org.apache.struts.chain パッケージにある、
ComposableRequestProcessor がその実態を担当している。
Struts で行われる処理は、小さな単位に分割され、
それらは個々のコマンドクラスとして実装されている。
ComposableRequestProcessor は上記クラスを管理しており、
デザインパターンの Chain of Responsibility を元に、
コマンドを順番に呼び出すことで処理を行っている。
Struts が依存しているライブラリに、
commons-chain-1.1.jar が含まれているのだが、
commons-chain は、設定ファイルによるフローの定義と、
Chain of Responsibility の基盤実装を提供している。
Struts は commons-chain を使うことで、
ComposableRequestProcessor を実装しているのだ。
Struts の処理の流れは、設定ファイルにて定義されており、
ライブラリ struts-core-1.3.5.jar の中に含まれている。
(org.apache.struts.chain.chain-config.xml)
この流れの中に、ユーザ定義のコマンドを組み込むことで、
任意の処理をさせることが可能となるのである。
では、要求文字エンコーディングを UTF-8 にするための
独自のコマンドを作ってみよう。
org.apache.commons.chain.Command を実装すれば良い。
========== UTF8RequestCommand.java ==========
package jp.loafer.test.commands;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.apache.struts.chain.contexts.ServletActionContext;
public class UTF8RequestCommand implements Command {
public UTF8RequestCommand() {
}
public boolean execute(Context context) throws Exception {
ServletActionContext c = (ServletActionContext)context;
HttpServletRequest request = c.getRequest();
// 入力エンコーディングが不明なら UTF-8 にする
String encoding = request.getCharacterEncoding();
if (encoding == null || encoding.length() == 0) {
request.setCharacterEncoding("UTF-8");
}
// 処理を続行
return CONTINUE_PROCESSING;
}
}
========== end of UTF8RequestCommand.java ==========
一昨日作った UTF8RequestFilter に似ているな。
Command インタフェースは単純である。
持つのは、execute メソッド 1 つだけだ。
execute が呼び出されることで、処理を実行するわけだ。
execute の持つ引数は Context インタフェース 1 つのみ。
Context は、状態(ステート)を表しており、
この状態は、コマンドの実行によって変更される。
この Context、extends Map されているだけの簡単なものだ。
commons-chain は汎用化しているため、
具体的な実装などは一切含んでいないのである。
Struts 上で扱われる場合は、Context を実装した、
ServletActionContext クラスのインスタンスが渡される。
なので、最初に ServletActionContext にキャストした後、
getRequest() を呼び出して HttpServletRequest を取得、
そして、文字エンコーディングを変更するという流れとなる。
Command インタフェースは、基本的に前処理用途である。
戻り値として CONTINUE_PROCESSING (false) を返せば、
続きの処理(本来の処理)に制御を移すことができ、
戻り値として PROCESSING_COMPLETE (true) を返せば、
その場で処理が完了し、後続のコマンドは呼び出されない。
後処理が必要であれば、Command を拡張した、
Filter インタフェースを使えば良い。
commons-chain には他にも色々なクラスが定義されている。
commons-chain は直接 Struts とは関係なく、
自由に使うことができる汎用のライブラリであるため、
他のアプリケーションでも利用することができる。