1. 程式人生 > >spring mvc @RequestMapping value 匹配規則和匹配優先順序

spring mvc @RequestMapping value 匹配規則和匹配優先順序

在一些場景中,請求的url可能是符合一定模式的多個值,這時候需要使用Ant 風格萬用字元來進行限定。

Ant 風格資源地址支援 3 種匹配符: 
這裡寫圖片描述

    說明一下: _?萬用字元前面都多加了下劃線
  • 1
  • 2

–?:匹配檔名中的一個字元

– *:匹配檔名中的任意字元

– 兩個星花: ** 匹配多層路徑

@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

這個似乎沒什麼難的,現在我們來看看一些例子。這些例子分成幾組,分別說明當萬用字元的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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

顯示出來: 
這裡寫圖片描述

我們將上面五組請求對應的萬用字元標記了出來,並寫出相應的控制器方法。

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129

那麼,我們來看看結果和結論吧:

第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更高優先順序。 
這裡寫圖片描述