自定义的Filter里没有excludePath,所以自己写了一个。开始写的时候还把注意力放在路径分隔符 “ / ” 上,后来发现完全没必要。站在更抽象的层次上看无非都是字符串而已。
测试数据:
"https://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_6172758863756121562%22%7D&n_type=0&p_from=1"
匹配模式:
"http*://*.baidu.com/*/landingsuper*"
代码如下:
public static boolean matching(String reg, String input) {
if ("/*".equals(reg))
return true;
//按 * 切割字符串
String[] reg_split = reg.split("\\*");
int index = 0, reg_len = reg_split.length;
//b代表匹配模式的最后一个字符是否是 '*' ,因为在split方法下最后一个 * 会被舍弃
boolean b = reg.charAt(reg.length() - 1) == '*' ? true : false;
while (input.length() > 0) {
//如果匹配到最后一段,比如这里reg的landingsuper
if (index == reg_len) {
if (b)//如果reg最后一位是 * ,代表通配,后面的就不用管了,返回true
return true;
else //后面没有通配符 * ,但是input长度还没有变成0 (此时input = context=%7B%22nid%22%3...),显然不匹配
return false;
}
String r = reg_split[index++];
int indexOf = input.indexOf(r);
if (indexOf == -1)
return false;
//前面匹配成功的就可以不用管了,截取掉直接从新地方开始
input = input.substring(indexOf + r.length());
}
return true;
}
main函数测试:
public static void main(String[] args) {
String uri = "https://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_6172758863756121562%22%7D&n_type=0&p_from=1";
String reg = "http*://*.baidu.com/*/landingsuper*";
long nanoTime = System.nanoTime();
boolean b = matching(reg, uri);
long nanoTime2 = System.nanoTime();
System.err.println(b);
System.err.println((nanoTime2 - nanoTime) / 1000.0 + "us");
}
打印结果:
true
367.013us
注意:可以看到该算法时间复杂度并不高,367微妙是在初始化各种参数,然后还要对匹配模式(reg)字符串切割的情况下测得的。而实际上在Filter中像reg("http*://*.baidu.com/*/landingsuper*")这样的匹配模式是在服务器启动的时候一起初始化并且切割好了的,运行的时候直接使用就行,而且使用频繁的代码块编译器会做优化,所以实际上消耗的时间应该会更少