Web.xmlとは異なる方法でフィルターを変更/構成する機能が欲しい。 2つのフィルターの静的構成を次に示します。 1つのフィルターを静的に構成し、そのフィルターが追加のフィルターをロードできるようにしたいのですが。既にこれを持っているlibを知っている人がいるかどうかを知りたかっただけです。
サーブレットAPI 2.5の使用
<web-app>
...
<filter>
<filter-name>MyFilter1</filter-name>
<filter-class>com.me.MyFilter1</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
<filter>
<filter-name>MyFilter2</filter-name>
<filter-class>com.me.MyFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
</web-app>
実行時にフィルターが設定されるGuiceFilterを使用して、Guiceでこれを実行しました。
コンテナが既に行っているのと同じ仕事をするだけです。つまり 責任のチェーン 設計パターンの車輪を再発明します。これは、サーブレットフィルターで使用されているカバーの下にあります。
_public class GodFilter implements Filter {
private Map<Pattern, Filter> filters = new LinkedHashMap<Pattern, Filter>();
@Override
public void init(FilterConfig config) throws ServletException {
Filter1 filter1 = new Filter1();
filter1.init(config);
filters.put(new Pattern("/foo/*"), filter1);
Filter2 filter2 = new Filter2();
filter2.init(config);
filters.put(new Pattern("*.bar"), filter2);
// ...
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest hsr = (HttpServletRequest) request;
String path = hsr.getRequestURI().substring(hsr.getContextPath().length());
GodFilterChain godChain = new GodFilterChain(chain);
for (Entry<Pattern, Filter> entry : filters.entrySet()) {
if (entry.getKey().matches(path)) {
godChain.addFilter(entry.getValue());
}
}
godChain.doFilter(request, response);
}
@Override
public void destroy() {
for (Filter filter : filters.values()) {
filter.destroy();
}
}
}
_
これらの小さなヘルパークラス(必要に応じて、上記のGodFilter
のネストされたクラス_private static
_を作成できます):
_public class Pattern {
private int position;
private String url;
public Pattern(String url) {
this.position = url.startsWith("*") ? 1
: url.endsWith("*") ? -1
: 0;
this.url = url.replaceAll("/?\\*", "");
}
public boolean matches(String path) {
return (position == -1) ? path.startsWith(url)
: (position == 1) ? path.endsWith(url)
: path.equals(url);
}
}
_
そして
_public class GodFilterChain implements FilterChain {
private FilterChain chain;
private List<Filter> filters = new ArrayList<Filter>();
private Iterator<Filter> iterator;
public GodFilterChain(FilterChain chain) {
this.chain = chain;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if (iterator == null) {
iterator = filters.iterator();
}
if (iterator.hasNext()) {
iterator.next().doFilter(request, response, this);
} else {
chain.doFilter(request, response);
}
}
public void addFilter(Filter filter) {
if (iterator != null) {
throw new IllegalStateException();
}
filters.add(filter);
}
}
_
必要に応じて、可能なすべてのフィルターをXML構成ファイルにフィードして、構成を簡単にすることもできます。リフレクションを使用して、GodFilter
のinit()
にフィルターを作成できます。
ああ、気にしない、それは_web.xml
_とコンテナがすでにしていることです...
サーブレット3.0には@WebFilter
フィルターを定義する注釈。 web.xmlで宣言する必要はもうありません。
ただし、フィルターからのフィルターのロードはサポートされていません。自分で実装することもできます。それは「単なる」責任の連鎖パターンですが、なぜそうするのでしょうか?
3.0より前のサーブレット仕様でも、簡単な手順で実現できます。
参照:Xstreamはシリアライザーにも同じ種類のパターンを使用しますが、サーブレット/フィルターでは使用しません。 :)