2007 年 4 月 14 日 23 時 58 分

Command: Chain of Responsibility の基盤


このアーカイブは同期化されません。 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 とは関係なく、
自由に使うことができる汎用のライブラリであるため、
他のアプリケーションでも利用することができる。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.