说明:本文章的内容转载至:https://my.oschina.net/happyBKs/blog/412714 如有侵权的地方,请联系本人,本人将会立即删除!
在一些场景中,请求的url可能是符合一定模式的多个值,这时候需要使用Ant 风格通配符来进行限定。
Ant 风格资源地址支持 3 种匹配符:
说明一下: _?通配符前面都多加了下划线–?:匹配文件名中的一个字符
– *:匹配文件名中的任意字符
– 两个星花: ** 匹配多层路径
@RequestMapping 还支持 Ant 风格的 URL:
– /user/*/createUser: 匹配
/user/aaa/createUser、 /user/bbb/createUser 等 URL
– /user/**/createUser: 匹配
/user/createUser、 /user/aaa/bbb/createUser 等 URL
– /user/createUser??: 匹配
/user/createUseraa、 /user/createUserbb 等 URL
(本文出自http://my.oschina.net/u/1156339/blog/412714)
这个似乎没什么难的,现在我们来看看一些例子。这些例子分成几组,分别说明当通配符的url请求满足多个控制器方法的RequestMapping条件时,会映射到哪一个方法上?
请求页面如下:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> 1 rq3/**/ or rq3/**/hhh<br/> <a href="c3/rq3/aaa/bbb/hhh">c3/rq3/aaa/bbb/hhh</a><br/> <br/> 2 rq4/*/bbb or rq4/**/bbb rq5/**/bbb<br/> <a href="c3/rq4/aaa/bbb">c3/rq4/aaa/bbb</a><br/> <a href="c3/rq4/aaa/ccc/bbb">c3/rq4/aaa/ccc/bbb</a><br/> <a href="c3/rq5/aaa/bbb">c3/rq5/aaa/bbb</a><br/> <br/> 3 rq6/qqq* or rq6/qqq? rq7/qqq*<br/> <a href="c3/rq6/qqqw">c3/rq6/qqqw</a><br/> <a href="c3/rq6/qqqww">c3/rq6/qqqww</a><br/> <a href="c3/rq7/qqqw">c3/rq7/qqqw</a><br/> <br/> 4<br/> rq8/**/kkk or rq8/aaa/**<br/> <a href="c3/rq8/aaa/kkk">c3/rq8/aaa/kkk</a><br/> rq8_bm/bbb/** rq8_bm/**/mmm<br/> <a href="c3/rq8_bm/bbb/mmm">c3/rq8_bm/bbb/mmm</a><br/> <br/> 5<br/> rq9/*/kkk/nnn or rq9/aaa/*/*<br/> <a href="c3/rq9/aaa/kkk/nnn">c3/rq9/aaa/kkk/nnn</a><br/> rq10/aaa/*/* or rq10/*/kkk/nnn<br/> <a href="c3/rq10/aaa/kkk/nnn">c3/rq10/aaa/kkk/nnn</a><br/> </body> </html>显示出来:
我们将上面五组请求对应的通配符标记了出来,并写出相应的控制器方法。
package com.happyBKs.springmvc.handlers; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @RequestMapping("/c3") @Controller public class RMHandler { //1 //handle4和handle5测试当请求的url符合两个映射方法的value通配符时,如何springmvc选择 @RequestMapping(value="rq3/**/") public String handle4() { return "successrm"; } @RequestMapping(value="rq3/**/hhh") public String handle5() { return "robot_baymax1"; } //2 //handle6-8测试当请求的url符合两个映射方法的value通配符时,如何springmvc选择 @RequestMapping(value="rq4/*/bbb") public String handle6() { return "robot_baymax1"; } @RequestMapping(value="rq4/**/bbb") public String handle7() { return "robot_baymax2"; } @RequestMapping(value="rq5/**/bbb") public String handle8() { return "robot_baymax2"; } //3 //handle9-11测试当请求的url符合两个映射方法的value通配符时,如何springmvc选择 @RequestMapping(value="rq6/qqq*") public String handle9() { return "robot_baymax1"; } @RequestMapping(value="rq6/qqq?") public String handle10() { return "robot_baymax3"; } @RequestMapping(value="rq7/qqq*") public String handle11() { return "robot_baymax1"; } //4 //handle12-13测试当请求的url符合两个映射方法的value通配符时,如何springmvc选择 @RequestMapping(value="rq8/**/kkk") public String handle12() { System.out.print("handle12"); return "robot_baymax1"; } @RequestMapping(value="rq8/aaa/**") public String handle13() { System.out.print("handle13"); return "robot_baymax2"; } @RequestMapping(value="rq8_bm/bbb/**") public String handle12_bm() { System.out.print("handle12_bm"); return "robot_baymax1"; } @RequestMapping(value="rq8_bm/**/mmm") public String handle13_bm() { System.out.print("handle13_bm"); return "robot_baymax2"; } //5 //handle14-15测试当请求的url符合两个映射方法的value通配符时,如何springmvc选择 @RequestMapping(value="rq9/*/kkk/nnn") public String handle14() { System.out.print("handle14"); return "robot_baymax1"; } @RequestMapping(value="rq9/aaa/*/*") public String handle15() { System.out.print("handle15"); return "robot_baymax2"; } //handle16-17测试当请求的url符合两个映射方法的value通配符时,如何springmvc选择 @RequestMapping(value="rq10/aaa/*/*") public String handle16() { System.out.print("handle16"); return "robot_baymax1"; } @RequestMapping(value="rq10/*/kkk/nnn") public String handle17() { System.out.print("handle17"); return "robot_baymax2"; } }那么,我们来看看结果和结论吧:
第1组实验:
一个请求:c3/rq3/aaa/bbb/hhh
对于两个通配符请求url: rq3// 和 rq3//hhh
结果是rq3/**/hhh显示的页面robot_baymax1.jsp。
结论: 当springmvcDispatchServlet会选择映射范围更小、更具体的url来进行映射。
第2组实验:
(A)请求:c3/rq4/aaa/bbb
通配符请求url:rq4/*/bbb
(B)请求:c3/rq5/aaa/bbb
通配符请求url:rq5/**/bbb
连个请求是类似的,但映射到的物理视图的情况截然不同。
(A)结果:
(B)结果:
这是因为符合(A)请求c3/rq4/aaa/bbb 的由两个方法的RequestMapping通配符,rq4//bbb和 rq4/*/bbb
这时候,的优先级会高于*的通配符。
第3组实验:
(A)请求:c3/rq6/qqqw
通配符请求url:rq6/qqq*
(B)请求:c3/rq7/qqqw
通配符请求url:rq7/qqq*
连个请求是类似的,但映射到的物理视图的情况截然不同。
(A)结果: (B)结果:
结论:当请求url两个都符合时,含有?的映射优先级高于含有*的。
大结论:至此,我们可以得到,相同位置相同个数的含有一个通配符,优先级由高到低:? * **
第4组实验:
(A)请求:c3/rq8/aaa/kkk
通配符请求url:rq8//kkk or rq8/aaa/
(B)请求:c3/rq8_bm/bbb/mmm
通配符请求url:rq8_bm/bbb/* rq8_bm/*/mmm
目的:看看相同的通配符在不同位置的请求url的映射情况。
结果: (A)
(B) 结论:映射优先级与通配符位置无关,当两个RequestMapping通配符url差别仅仅是位置差别时,映射结果是随机的。
(这里的实验也出现过两个baymax2)
第5组实验:
(A)请求:c3/rq9/aaa/kkk/nnn
通配符请求url:rq9//kkk/nnn or rq9/aaa//*
(B)请求:c3/rq10/aaa/kkk/nnn
通配符请求url:rq10/aaa// or rq10/*/kkk/nnn
目的:看看相同的通配符在个数不同请求url的映射情况。
结果:
(A)
(B)
结论:通配符个数少的RequestMapping的value更高优先级。