如果想測試Filter,可以繼承FilterTestCase, 這個類別可以使用一些由容器管理的物件,request、 response、config、filterChain可以分別取得HttpServletRequestWrapper、 HttpServletResponseWrapper、org.apache.cactus.server.FilterConfigWrapper (繼承自FilterConfig)與FilterChain物件。
直接來看個實例, 假設要撰寫一個可以過濾字元的Filter, 其中字元過濾清單可以由一個文字檔案設定。例如:
< <
> >
文字檔案會放在Web應用程式之中,並可在web.xml中設定Filter初始參數來告知檔案的路徑,你的Filter可能設計如 下:
package cc.openhome;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.*;
import javax.servlet.http.*;
public class CharacterFilter implements Filter {
private Map<String, String> escapeMap;
private class CharacterRequestWrapper extends HttpServletRequestWrapper {
CharacterRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
return doEscape(this.getRequest().getParameter(name));
}
private String doEscape(String parameter) {
if(parameter == null) {
return null;
}
String result = parameter;
for(String origin : escapeMap.keySet()) {
String escape = escapeMap.get(origin);
result = result.replaceAll(origin, escape);
}
return result;
}
}
public void init(FilterConfig filterConfig)
throws ServletException {
BufferedReader reader = null;
try {
String escapeListFile = filterConfig
.getInitParameter("ESCAPE_LIST");
reader = new BufferedReader(
new InputStreamReader(
filterConfig.getServletContext()
.getResourceAsStream(escapeListFile)));
String input = null;
escapeMap = new HashMap<String, String>();
while ((input = reader.readLine()) != null) {
String[] tokens = input.split("\t");
escapeMap.put(tokens[0], tokens[1]);
}
} catch (IOException ex) {
Logger.getLogger(CharacterFilter.class.getName())
.log(Level.SEVERE, null, ex);
}
finally {
try {
reader.close();
} catch (IOException ex) {
Logger.getLogger(CharacterFilter.class.getName())
.log(Level.SEVERE, null, ex);
}
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest requestWrapper =
new CharacterRequestWrapper((HttpServletRequest) request);
chain.doFilter(requestWrapper, response);
}
public Map<String, String> getEscapeMap() {
return escapeMap;
}
public void destroy() {
}
}
如果要對這個Filter進行測試,可以繼承FilterTestCase, 在這邊要測試的對象有兩個,一個是CharacterFilter的init()是否能正確載入文字檔案,生成過濾用的Map物件,另一個是測試 CharacterFilter的doFilter()後續元件,是否取得的請求參數都是經過濾的結果。以下是個測試案例的示範:
package test.cc.openhome;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.cactus.FilterTestCase;
import org.apache.cactus.WebRequest;
import cc.openhome.CharacterFilter;
public class CharacterFilterTest extends FilterTestCase {
static {
System.setProperty(
"cactus.contextURL", "http://localhost:8080/CactusExample");
}
private CharacterFilter filter;
@Override
protected void setUp() throws Exception {
config.setInitParameter("ESCAPE_LIST", "/WEB-INF/escapelist.txt");
filter = new CharacterFilter();
filter.init(config);
}
public void testInit() throws Exception {
Map<String, String> expected = new HashMap<String, String>();
expected.put("<","<");
expected.put(">",">");
Map<String, String> result = filter.getEscapeMap();
assertEquals(expected, result);
}
public void beginDoFilter(WebRequest req) {
req.addParameter("param", "<test>test</test>");
}
public void testDoFilter() throws Exception {
final String[] result = new String[1];
FilterChain chain = new FilterChain() {
@Override
public void doFilter(ServletRequest req, ServletResponse resp)
throws IOException, ServletException {
result[0] = req.getParameter("param");
}
};
filter.doFilter(request, response, chain);
assertEquals("<test>test</test>", result[0]);
}
}
FilterTestCase 預設會請求/FilterRedirector,這要 對應一個作為Redirect proxy的Filter,你要於 web.xml中如下設定:
...
<filter>
<filter-name>FilterRedirector</filter-name>
<filter-class>org.apache.cactus.server.FilterTestRedirector</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterRedirector</filter-name>
<url-pattern>/FilterRedirector</url-pattern>
</filter-mapping>
...