便利なコードパーツ集!

やまろうのプログラミングTips

Java

[Java] XMLドリブンのフィルターフレームワークを作ろう!

投稿日:

2003/12

「XMLドリブンのフィルターフレームワーク」とはなんぞや?ということですが、
ServletコンテナのServletフィルタや、StrutsのActionクラスみたく、
XMLファイルを読み込んで、その情報を元にクラスを呼び出して、
引数で渡されたオブジェクトを加工して次のフィルタ(Action)に渡していく
っていうもののことです。そういう観点で見るとServletフィルタやActionクラスは
ServletRequest または HttpServletRequest、
ServletResponse または HttpServletResponse
にフィルタをかけるクラスだということが出来ます。

そこで、今回は、Mapオブジェクトに対してフィルタをかけるフレームワークを
作ってみたいと思います。なぜHttpServletRequestではなくMapにしたかと
いうと、コマンドラインで実行したいからです。まずはコマンドライン版で
作って、必要なら引数をHttpServletRequestに修正すればいいってことで。
というか、最近のフレームワークはServletコンテナ上じゃなくても
動くコンポーネントを作らせようという流れがあるのでむしろ、Mapのが
良いのかもしれません。

それじゃソース行ってみよう!(そのままコンパイル出来るように
すべて同一パッケージ、パッケージスコープのクラスにしてあります。)

package filter;

import java.util.*;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import javax.xml.parsers.*;

class FilterExecuter {
  /** コンフィグ情報 */
  private static Map configMap = getConfig();

  /**
   * 引数nameをキーにコンフィグファイルの内容を取り出し、フィルターを呼び出す。
   * @param name コンフィグファイルのfiltersタグのname属性
   * @param map フィルタリングするMapオブジェクト
   */
  public static void execute(String name, Map map) {
    try {
      String[] classNames = (String[]) configMap.get(name);
      for (int i = 0; i < classNames.length; i++) {
        MapFilter filter = 
          (MapFilter)Class.forName(classNames[i]).newInstance();
        filter.doFilter(map);
      }
    }
    catch (Exception ex) {
      throw new RuntimeException(ex);
    }
  }

  /**
   * コンフィグファイルを読み込み解析してMapオブジェクトに格納し返す。
   * @return コンフィグ情報
   */
  private static Map getConfig() {
    Map map = new HashMap();
    try {
      DocumentBuilderFactory factory
          = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = factory.newDocumentBuilder();
      Document doc = builder.parse("filter-config.xml");
      Element docElem = doc.getDocumentElement();
      NodeList filtersList = docElem.getElementsByTagName("filters");
      for (int i = 0; i < filtersList.getLength(); i++) {
        Element filters = (Element) filtersList.item(i);
        String name = filters.getAttribute("name");
        NodeList filterList = filters.getElementsByTagName("filter");
        ArrayList list = new ArrayList();
        for (int j = 0; j < filterList.getLength(); j++) {
          Element filter = (Element) filterList.item(j);
          String type = filter.getAttribute("type");
          list.add(type);
        }
        String[] types = new String[list.size()];
        list.toArray(types);
        map.put(name, types);
      }
    }
    catch (Exception ex) {
      throw new RuntimeException(ex);
    }
    return map;
  }
}


interface MapFilter {
  /**
   * 引数mapをフィルタリングする。
   * @param map フィルタリングするMapオブジェクト
   */
  public void doFilter(Map map);
}

class SampleFilter implements MapFilter {
  /**
   * 引数mapにハッシュキー"theData"で登録されてる
   * オブジェクトを"女"ではさむ。ウハウハなフィルタ。
   * @param map フィルタリングするMapオブジェクト
   */
  public void doFilter(Map map) {
    String data = (String)map.get("theData");
    data = "女" + data + "女";
    map.put("theData",data);
  }
}

/**
 * 動作確認用クラス
 */
class Main {
  public static void main(String[] args) {
    HashMap m = new HashMap();
    m.put("theData", "やまろう");
    FilterExecuter.execute("filters1", m);         //(1)
    System.out.println(m.get("theData"));

    HashMap m2 = new HashMap();
    m2.put("theData", "キムタク");
    FilterExecuter.execute("filters2", m2);        //(2)
    System.out.println(m2.get("theData"));
  }
}

実行してみましょう!
1.コンフィグファイルを用意(filter-config.xmlという名前で保存)
[filter-config.xml]

<?xml version="1.0" encoding="ISO-8859-1" ?>
<filter-config>
<filters name="filters1">
<filter type="filter.SampleFilter" />
<filter type="filter.SampleFilter" />
<filter type="filter.SampleFilter" />
</filters>
<filters name="filters2">
<filter type="filter.SampleFilter" />
<filter type="filter.SampleFilter" />
</filters>
</filter-config>

2.コンパイル & 実行
このメルマガを適当なファイル名(FilterFramework.java)で
保存して、
>javac -d . *.java

>java filter.Main
女女女やまろう女女女
女女キムタク女女

実行結果の1行目は
(1)でfilters1を指定してるのでSampleFilterが3回実行されて
やまろうが女の子6人に囲まれてます。実際そんなことないけど(シュン)。

実行結果の2行目は
(2)でfilters2を指定してるのでSampleFilterが2回実行されて
キムタクが女の子4人に囲まれてます。キムタク人気ねぇー!?

あほプログラムですみません。でも、Servletフィルタもこれと同じよう
なしくみで動いているんだと思います。内面を見てってことよ!

いかがだったでしょうか?今回のプログラムを応用すれば、Strutsのような
フレームワークも作れるはずです。僕もいつかフレームワークを作ってみたい
と思っているのですが、アイデアがまだ浮かんでないんですよねー。どうせ作るなら
他に類を見ない斬新なものにしたいですからねぇ。

んじゃ
やまろう

スポンサーリンク

-Java

Copyright© やまろうのプログラミングTips , 2022 AllRights Reserved Powered by AFFINGER4.