Spring中的所有路径匹配问题总结

见:http://blog.csdn.net/haoyifen/article/details/52679576


关于Spring的路径, 问的最多的问题就是如何拦截所有以.do结尾的请求. 
大家都是在猜, 网上给出的答案五花八门, 比如: *do, /*do, /**do, /** 等..然而这些都是错的. 
正确答案是/**/*.do, 如果要拦截/api下的所有.do结尾的请求, 那么应该使用/api/**/*.do, 以此类推. 
我觉得这是一个很恶心的东西. 关于字符串匹配, 存在三个常用的规则: 正则, AntMatcher和通配符. 恶心的是这三者都使用了?和*, 而且意义各不同. 真是一件让程序员苦恼的事.

言归正传, Spring中无论是handler路径映射, 还是interceptor路径匹配, 还是sping.xml中加载配置文件时使用的”classpath*”, 都使用的是AntMathcer规则( 见PathMatcher文档), 实现类是org.springframework.util.AntPathMatcher. 这里是这个类的官方文档AntPathMatcher文档 
里面有这样的说明

匹配符 规则  
? 匹配一个字符  
* 匹配0或更多字符  
** 匹配path路径中的0个或更多目录  
{spring:[a-z]+} 匹配正则[a-z]+并作为一个路径变量, 赋值给变量spring  

注意在AntPathMatcher中, 有个路径分隔符的概念, 路径分隔符是不能被 ? 或单个 * 匹配的, 路径分隔符默认是 / , 在匹配类全限定名时, 设置成 . 其他规则不变.

以下是简单的介绍: (注意**可以匹配0个或更多的目录)

规则 简介 匹配 不匹配
/goods/t?st.jsp /goods路径下只相差一个字符的路径 /good/test.jsp /goods/text.jsp /goods/tast.jsp等 /goods/taast.jsp /google/tast.jsp等
/**/test.jsp 匹配任何以test.jsp结尾的路径 /test.jsp/goods/test.jsp /my/goods/test.jsp /my/favorite/goods/test.jsp等 /goods/abc.jsp等
/**/*.jsp 任何以jsp结尾的路径 /test.jsp /goods/test.jsp /my/goods/test.jsp等 /hello.html /my/hello.html等
/goods/** 匹配goods下的所有路径 /goods /goods/a.html /goods/a.jsp /goods/test/a.jsp等 非/goods/下的路径
/或/goods 只匹配/或/goods这一个路径,千万不要误认为是所有路径 只有/和/goods 其他任何路径
/** 匹配所有路径 /test/goods/test /test.html /test.jsp /goods/test.jsp /my/goods/test.jsp等

完整用法可见Sping的托管在github的测试代码AntPathMatcherTests.java

以下是我从中摘取的一部分. 可以不用看这个.

// 完全匹配
        assertTrue(pathMatcher.match("test", "test"));
        assertTrue(pathMatcher.match("/test", "/test"));
        //不匹配
        assertFalse(pathMatcher.match("/test.jpg", "test.jpg"));
        assertFalse(pathMatcher.match("test", "/test"));
// 使用?进行匹配, ?表示匹配一个字符
        assertTrue(pathMatcher.match("t?st", "test"));
        assertTrue(pathMatcher.match("??st", "test"));
        //不匹配
        assertFalse(pathMatcher.match("tes?", "tes"));
        assertFalse(pathMatcher.match("tes?", "testt"));
//使用*进行匹配, *匹配0    更多字符
        assertTrue(pathMatcher.match("*", "test"));
        assertTrue(pathMatcher.match("test*", "test"));
        assertTrue(pathMatcher.match("test*", "testTest"));
        assertTrue(pathMatcher.match("test/*", "test/Test"));
        assertTrue(pathMatcher.match("test/*", "test/t"));
        assertTrue(pathMatcher.match("*.*", "test."));
        assertTrue(pathMatcher.match("*.*", "test.test.test"));
        //以下不匹配
        assertFalse(pathMatcher.match("test*", "tst"));
        assertFalse(pathMatcher.match("test*", "tsttest"));
        assertFalse(pathMatcher.match("test*", "test/"));
        assertFalse(pathMatcher.match("test/*", "test"));
// 使用?和/一起匹配
        assertTrue(pathMatcher.match("/?", "/a"));
        assertTrue(pathMatcher.match("/?/a", "/a/a"));
        assertTrue(pathMatcher.match("/a/?", "/a/b"));
        assertTrue(pathMatcher.match("/??/a", "/aa/a"));
        assertTrue(pathMatcher.match("/a/??", "/a/bb"));
        assertTrue(pathMatcher.match("/?", "/a"));

// 使用**匹配, 匹配0个或更多目录
        assertTrue(pathMatcher.match("/**", "/testing/testing"));
        assertTrue(pathMatcher.match("/*/**", "/testing/testing"));
        assertTrue(pathMatcher.match("/**/*", "/testing/testing"));
        assertTrue(pathMatcher.match("/bla/**/bla", "/bla/testing/testing/bla"));
        assertTrue(pathMatcher.match("/bla/**/bla", "/bla/testing/testing/bla/bla"));

        assertTrue(pathMatcher.match("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing/"));
        assertTrue(pathMatcher.match("/*bla*/**/bla/*", "/XXXblaXXXX/testing/testing/bla/testing"));

        assertTrue(pathMatcher.match("*bla*/**/bla/**", "XXXblaXXXX/testing/testing/bla/testing/testing"));
        assertFalse(pathMatcher.match("*bla*/**/bla/*", "XXXblaXXXX/testing/testing/bla/testing/testing"));

        assertTrue(pathMatcher.match("/foo/bar/**", "/foo/bar")) ;

        assertTrue(pathMatcher.match("/{bla}.*", "/testing.html"));

你可能感兴趣的:(spring)