SpringMVC的路径匹配规则是依照Ant的来的.

实际上不只是SpringMVC,整个Spring框架的路径解析都是按照Ant的风格来的.

在Spring中的具体实现,详情参见 org.springframework.util.AntPathMatcher.

具体规则如下(来自Spring AntPathMatcher源码注释):

 * {@link PathMatcher} implementation for Ant-style path patterns.** <p>Part of this mapping code has been kindly borrowed from <a href="http://ant.apache.org">Apache Ant</a>.** <p>The mapping matches URLs using the following rules:<br>* <ul>* <li>{@code ?} matches one character</li>* <li>{@code *} matches zero or more characters</li>* <li>{@code **} matches zero or more <em>directories</em> in a path</li>* <li>{@code {spring:[a-z]+}} matches the regexp {@code [a-z]+} as a path variable named "spring"</li>* </ul>** <h3>Examples</h3>* <ul>* <li>{@code com/t?st.jsp} &mdash; matches {@code com/test.jsp} but also* {@code com/tast.jsp} or {@code com/txst.jsp}</li>* <li>{@code com/*.jsp} &mdash; matches all {@code .jsp} files in the* {@code com} directory</li>* <li><code>com/**/test.jsp</code> &mdash; matches all {@code test.jsp}* files underneath the {@code com} path</li>* <li><code>org/springframework/**/*.jsp</code> &mdash; matches all* {@code .jsp} files underneath the {@code org/springframework} path</li>* <li><code>org/**/servlet/bla.jsp</code> &mdash; matches* {@code org/springframework/servlet/bla.jsp} but also* {@code org/springframework/testing/servlet/bla.jsp} and {@code org/servlet/bla.jsp}</li>* <li>{@code com/{filename:\\w+}.jsp} will match {@code com/test.jsp} and assign the value {@code test}* to the {@code filename} variable</li>* </ul>** <p><strong>Note:</strong> a pattern and a path must both be absolute or must* both be relative in order for the two to match. Therefore it is recommended* that users of this implementation to sanitize patterns in order to prefix* them with "/" as it makes sense in the context in which they're used.

换成人话就是:

  • ? 匹配1个字符
  • * 匹配0个或多个字符
  • ** 匹配路径中的0个或多个目录
  • {spring:[a-z]+} 将正则表达式[a-z]+匹配到的值,赋值给名为 spring 的路径变量.(PS:必须是完全匹配才行,在SpringMVC中只有完全匹配才会进入controller层的方法)

一个一个的分析.

符号 ?

和其它几个不一样的是,? 要求必须为一个字符,并且不能是代表路径分隔符的/.

@RequestMapping("/index?")
@ResponseBody
public String index(){System.out.println("11");return "11";
}

结果:

index           false 404错误(必须要有一个字符)
index/          false 404错误(不能为"/")
indexab         false 404错误(不能是多个字符)
indexa          true  输出 11

符号 *

*,虽然可以匹配多个任意的字符,但是,如果你以为 * 可以替代 ** 那就错了,* 代表的多个任意字符组成的字符串不能是个 目录 或者说 路径.也就是说,* 并不能拿来替代 **.

示例代码:

@RequestMapping("/index*")
@ResponseBody
public String index(){System.out.println("11");return "11";
}

结果:

index           true  输出 11(可以为0字符)
index/          true  输出 11(可以为"/")
indexa          true  输出 11(可以为1个字符)
indexabc        true  输出 11(可以为多个字符)
index/a         false 404错误("/a"是一个路径)

符号 **

0个或多个目录.** 代表的字符串本身不一定要包含 /

@RequestMapping("/index/**/a")
@ResponseBody
public String index(){System.out.println();return "11";
}

结果:

index/a         true  输出 11(可以为0个目录)
index/x/a       true  输出 11(可以为一个目录)
index/x/z/c/a   true  输出 11(可以为多个目录)

符号 {spring:[a-z]+}

其它的关于 AntPathMatcher 的文章里,对 {spring:[a-z]+} 的匹配大多是只字未提.这里补充下.

示例代码:

@RequestMapping("/index/{username:[a-b]+}")
@ResponseBody
public String index(@PathVariable("username") String username){System.out.println(username);return username;
}

结果:

index/ab        true  输出 ab
index/abbaaa    true  输出 abbaaa
index/a         false 404错误
index/ac        false 404错误

附录(完整测试用例)

节选自 AntPathMatcherTests.不得不说 Spring 的测试用例写的实在是太完善了.

// test exact matching
assertTrue(pathMatcher.match("test", "test"));
assertTrue(pathMatcher.match("/test", "/test"));
assertTrue(pathMatcher.match("http://example.org", "http://example.org")); // SPR-14141
assertFalse(pathMatcher.match("/test.jpg", "test.jpg"));
assertFalse(pathMatcher.match("test", "/test"));
assertFalse(pathMatcher.match("/test", "test"));// test matching with ?'s
assertTrue(pathMatcher.match("t?st", "test"));
assertTrue(pathMatcher.match("??st", "test"));
assertTrue(pathMatcher.match("tes?", "test"));
assertTrue(pathMatcher.match("te??", "test"));
assertTrue(pathMatcher.match("?es?", "test"));
assertFalse(pathMatcher.match("tes?", "tes"));
assertFalse(pathMatcher.match("tes?", "testt"));
assertFalse(pathMatcher.match("tes?", "tsst"));// test matching with *'s
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/*", "test/"));
assertTrue(pathMatcher.match("*test*", "AnothertestTest"));
assertTrue(pathMatcher.match("*test", "Anothertest"));
assertTrue(pathMatcher.match("*.*", "test."));
assertTrue(pathMatcher.match("*.*", "test.test"));
assertTrue(pathMatcher.match("*.*", "test.test.test"));
assertTrue(pathMatcher.match("test*aaa", "testblaaaa"));
assertFalse(pathMatcher.match("test*", "tst"));
assertFalse(pathMatcher.match("test*", "tsttest"));
assertFalse(pathMatcher.match("test*", "test/"));
assertFalse(pathMatcher.match("test*", "test/t"));
assertFalse(pathMatcher.match("test/*", "test"));
assertFalse(pathMatcher.match("*test*", "tsttst"));
assertFalse(pathMatcher.match("*test", "tsttst"));
assertFalse(pathMatcher.match("*.*", "tsttst"));
assertFalse(pathMatcher.match("test*aaa", "test"));
assertFalse(pathMatcher.match("test*aaa", "testblaaab"));// test matching with ?'s and /'s
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"));// test matching with **'s
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("/**/test", "/bla/bla/test"));
assertTrue(pathMatcher.match("/bla/**/**/bla", "/bla/bla/bla/bla/bla/bla"));
assertTrue(pathMatcher.match("/bla*bla/test", "/blaXXXbla/test"));
assertTrue(pathMatcher.match("/*bla/test", "/XXXbla/test"));
assertFalse(pathMatcher.match("/bla*bla/test", "/blaXXXbl/test"));
assertFalse(pathMatcher.match("/*bla/test", "XXXblab/test"));
assertFalse(pathMatcher.match("/*bla/test", "XXXbl/test"));assertFalse(pathMatcher.match("/????", "/bala/bla"));
assertFalse(pathMatcher.match("/**/*bla", "/bla/bla/bla/bbb"));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"));
assertTrue(pathMatcher.match("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing.jpg"));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"));assertFalse(pathMatcher.match("/x/x/**/bla", "/x/x/x/"));assertTrue(pathMatcher.match("/foo/bar/**", "/foo/bar")) ;assertTrue(pathMatcher.match("", ""));assertTrue(pathMatcher.match("/{bla}.*", "/testing.html"));    

转载于:https://www.cnblogs.com/hypnotizer/p/7085399.html

SpringMVC路径匹配规则AntPathMatcher(转)相关推荐

  1. Go 学习笔记(53)— Go 标准库之 path(判断绝对路径、拆分目录和文件、组合路径、返回路径目录、获取路径最后文件名、获取文件扩展名、路径匹配规则)

    1. 概述说明 import "path" path 实现了对斜杠分隔的路径的实用操作函数. 2. 主要函数 2.1 func IsAbs func IsAbs(path stri ...

  2. Go 学习笔记(52)— Go 标准库之 path/filepath(判断绝对路径、拆分目录和文件、组合路径、返回路径目录、获取路径最后文件名、获取文件扩展名、路径匹配规则、递归遍历目录)

    1. 概述说明 import "path/filepath" filepath 包实现了兼容各操作系统的文件路径的实用操作函数. 2. 主要函数 2.1 func IsAbs fu ...

  3. nginx负载带/不带localion后面的路径匹配规则

    nginx中localion后面'/'的截取规则分为两类,为proxy_pass的ip:port后面是否还有目录. 类型一:proxy_pass代理地址端口后无任何目录 location /test1 ...

  4. Spring路径匹配器AntPathMatcher

    文章目录 PathMatcher接口 使用场景 接口方法 AntPathMatcher类 匹配规则 主要方法 1. isPattern 2. match 3. matchStart 4. extrac ...

  5. url-pattern的匹配规则

    一.url-pattern的三种写法 1.精确匹配.以"/"开头,加上servlet名称 /ad 2.路径匹配.以"/"开头,加上通配符"*" ...

  6. servlet的url-pattern匹配规则

    目录 1 url-pattern匹配规则说明 2 四种匹配规则优先顺序 2.1 精确匹配 2.2 路径匹配 2.3 扩展名匹配 2.4 缺省匹配 3 需要注意的问题 3.1 路径匹配和扩展名匹配无法同 ...

  7. tomcat首页welcome-file-list设置与url-pattern匹配规则

    一.welcome-file-list 1. <welcome-file-list>标签下可以设置多个首页<welcome-file>,容器启动后会在根目录下依次查找匹配的物理 ...

  8. nginx的优先匹配规则

    nginx的优先匹配规则 以=开头表示精确匹配 如 A 中只匹配根目录结尾的请求,后面不能带任何字符串. ^~ 开头表示uri以某个常规字符串开头,不是正则匹配 ~ 开头表示区分大小写的正则匹配; ~ ...

  9. Java中intentfiler_【Android - 组件】之IntentFilter的匹配规则

    我们知道,Activity的启动模式分为两种,分别是显式启动和隐式启动.显式启动需要明确的指定被启动的对象的组件信息,包括包名和类名:而隐式启动需要 Intent 能够匹配目标组件的 IntentFi ...

最新文章

  1. 第五十一条:当心字符串的连接性能
  2. Scala可变集合:Queue增加和移除元素
  3. Python加密—HMACSHA1 加密
  4. python解释器有哪几种_Python解释器种类以及特点?
  5. 调整PowerDesigner各种字体大小
  6. 【推荐】程序员/设计师能用上的 75 份速查表
  7. Javascript 强制浏览器渲染Dom文档
  8. 06Matplotlib数据可视化--6.1绘图基础
  9. 你最喜欢哪款游戏的界面风格,为什么?
  10. MySQL学习(二、简单查询和多行、单行函数)
  11. 数据分析项目分析之风控建模!!
  12. HP大中华区总裁孙振耀退休十五天后九大感言
  13. 正则表达式的进阶用法——预查与分组
  14. 请不用条件转移指令JG,JGE,JL,JLE等指令实现如下程序片段的功能
  15. PyTorch深度学习(B站刘二大爷)第九讲 多分类问题
  16. 静脉炎的症状是什么?
  17. 安卓模拟器设置网速和延迟
  18. 2021011206贾天乐实验二
  19. 【Python】批量修改照片文件名为拍摄日期
  20. BERT微调(SQuAD v1.1)

热门文章

  1. SpringToolsSuite (STS)或Eclipse安装gradle
  2. [pytorch、学习] - 4.6 GPU计算
  3. [pytorch、学习] - 3.13 丢弃法
  4. 前端安全之token
  5. 轻量社交APP系统ThinkSNS 简 权威发布 限时惠购
  6. Nginx系列二:(Nginx Rewrite 规则、Nginx 防盗链、Nginx 动静分离、Nginx+keepalived 实现高可用)...
  7. 关于F5的一些基础话题
  8. 晶科电力打造山东省最大物流港分布式光伏项目
  9. SQLite轻量级数据库,操作数据常用语句
  10. POJ 1042 Gone Fishing【枚举+贪心】