实现一个排斥性(exclude)过滤器
说到排斥性过滤器,大家会一头雾水,搞不明白这其中含义。何为排斥性(exclude)过滤器呢,其实是本人自己定义出来的,呵呵。
排斥性过滤器是相对于规范所定义的Filter而言的,Java EE 规范中的过滤器是对web.xml中所列出的url进行过滤,而排斥性过滤器则恰恰相反,不对这些web.xml中列出的url执行过滤,而是对除这些url外的url进行过滤逻辑操作。
作为一个多年的Java开发人员,在实际开发中遇到这种情况,这便是有此动机的原因。
下面就讲讲这个exclude filter的原理,其实很简单。在拦截所有请求时,我们检查这些请求的url是否在url列表之内,如果在,那么就不进行过滤逻辑,直接调用chain.doFilter(xxx);否则的话,我们就执行一些过滤逻辑操作,然后再chain.doFilter(xxx)。
其中,检查url分2种方式:精确匹配(equals)和模糊匹配(contains),精确匹配优先于模糊匹配
对于代码中的URI获取,可能要根据实际情况作些更改,代码中URI只是使用request.getRequestURI(),得到的不是完整的URL,可视实际情况做出调整。
AbstractExcludeFilter 类将不该被override的方法都设置为了final,developer应该实现唯一的一个abstract method filter(),并且需要在该方法内部适当位置调用 chain.doFilter(xx)。
请看实现代码:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.openthoughts.webtools.filters;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
* An abstract filter provided for developer to filter the URLs that are not in excluded URLs list.
*
* Usage:
* 1.Write subclass of this abstract filter by implementing abstract method 'filter'.
* 2.Config web.xml like this:
* <filter>
* <filter-name>yourExcludeFilter</filter-name>
* <filter-class>org.openthoughts.webtools.filters.YourCustomizedExcludeFilter</filter-class>
* <init-param>
* <param-name>exactMatchExcludedURLs</param-name>
* <param-value>/abc/,/abc/index.jsp,/abc/loginServlet</param-value>
* </init-param>
* <init-param>
* <param-name>approximateMatchExcludedURLs</param-name>
* <param-value>loginServlet,upgradeServlet</param-value>
* </init-param>
* </filter>
*
* <filter-mapping>
* <filter-name>yourExcludeFilter</filter-name>
* <url-pattern>/*</url-pattern>
*</filter-mapping>
* Note: exactMatchExcludedURLs means exactly match URLs that should not be filtered, i.e. request.getRequestURI().equals(url);
* approximateMatchExcludedURLs means approximately math URLs that should not be filtered, i.e. request.getRequestURI().contains(url)
* exactMatch is prior to approximateMatch, i.e. if exactMath = true, not check approximateMatch
*
* @author <a href="mailto:guangquanzhang@gmail.com">gavin.zhang</a>
*/
public abstract class AbstractExcludeFilter implements Filter {
private FilterConfig config;
private List<String> exactMatchExcludedURLs = new ArrayList<String>();
private List<String> approximateMatchExcludedURLs = new ArrayList<String>();
/**
* Init filter, and load all configuration.
* @param config
* @throws javax.servlet.ServletException
*/
final public void init(FilterConfig config) throws ServletException {
this.config = config;
this.loadConfiguration(config);
}
/**
* Do filter work according to exactMatch or approximateMatch,
* This method must not be overrided.
* @param request
* @param response
* @param chain
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
final public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
boolean is2BeFiltered = true;
String requestURI = ((HttpServletRequest) request).getRequestURI();
if (!this.exactMatchExcludedURLs.isEmpty()) {
for (String exactMatchExcludedURL : this.exactMatchExcludedURLs) {
if (requestURI.equals(exactMatchExcludedURL)) {
is2BeFiltered = false;
break;
}
}
}
if (!this.approximateMatchExcludedURLs.isEmpty() && is2BeFiltered) {
for (String approximateMatchExcludedURL : this.approximateMatchExcludedURLs) {
if (requestURI.indexOf(approximateMatchExcludedURL) != -1) {
is2BeFiltered = false;
break;
}
}
}
if (is2BeFiltered) {
this.filter(request, response, chain);
} else {
chain.doFilter(request, response);
}
}
/**
* Release all resources.
*/
final public void destroy() {
this.config = null;
this.exactMatchExcludedURLs = null;
this.approximateMatchExcludedURLs = null;
}
/**
* Do customized filter work according to exactMatch or approximateMatch,
* developer should implement this Abstract Method.
* @param request
* @param response
* @param chain
*/
public abstract void filter(ServletRequest request, ServletResponse response, FilterChain chain);
/**
* Load configuration from web.xml.
* @param config
*/
private void loadConfiguration(FilterConfig config) {
String exactMatchedURLString = config.getInitParameter("exactMatchExcludedURLs");
String approximateMatchedURLString = config.getInitParameter("approximateMatchExcludedURLs");
if(null != exactMatchedURLString) {
String[] tmps = exactMatchedURLString.split(",");
for (String tmp : tmps) {
tmp = tmp.trim();
if(tmp.length()>0) {
this.exactMatchExcludedURLs.add(tmp);
}
}
}
if(null != approximateMatchedURLString) {
String[] tmps = approximateMatchedURLString.split(",");
for (String tmp : tmps) {
tmp = tmp.trim();
if(tmp.length()>0) {
this.approximateMatchExcludedURLs.add(tmp);
}
}
}
}
}
By javafuns on May 1, 2008 at 19:19 ·
Views: 548 · Permalink · RSS
Categorized in: Design Patterns, Java · Tagged with: DesignPatterns, Java
Categorized in: Design Patterns, Java · Tagged with: DesignPatterns, Java


(