胖哥學SpringMVC:RequestMapping註解之映射路徑 上卷

@RequestMapping

我的建議從新練習一遍搭建的過程,若是感受麻煩你能夠直接複製上一個工程,可是須要修改pom.xml中的一點信息html

<groupId>com.hanpang.springmvc</groupId>
<artifactId>springmvc-demo02</artifactId>
<version>0.0.1-SNAPSHOT</version>
複製代碼

1.基本用法

咱們可使用@RequestMapping標註來將請求URL(相似於@WebServlet),如/hanpang等,映射到整個類上某個特定的處理器方法上。java

通常來講,類級別的標註負責將一個特定(或符合某種模式)的請求路徑映射到一個控制器上,同時經過方法級別的標註來細化映射,即根據特定的HTTP請求方法(「GET」和「POST」方法等)、HTTP請求中是否攜帶特定參數等條件,將請求映射到匹配的方法上。web

package com.hanpang.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller//告知其是一個控制器
@RequestMapping("/sys")
public class Demo01Controller {
	//映射默認的路徑
	public ModelAndView test01() {
		System.out.println("該方法是訪問sys執行");
		return null;
	}
	//----------------細化--------------------//

	//映射一個路徑
	@RequestMapping(value="/user01")
	public ModelAndView test02() {
		System.out.println("/user01 path和value屬性同樣");
		return null;
	}
	//映射一個路徑
	@RequestMapping(path="/user02")
	public ModelAndView test03() {
		System.out.println("/user02 path和value屬性同樣");
		return null;
	}

	//簡寫方式
	@RequestMapping("/user03")
	public ModelAndView test04() {
		System.out.println("/user03 當只有path或者value屬性的時候,可使用簡寫方式");
		return null;
	}

	//多個映射路徑執行一個方法
	@RequestMapping(value= {"/user04","/user05"})
	public ModelAndView test05() {
		System.out.println("設置多個映射路徑");
		return null;
	}
	//簡寫方式
	@RequestMapping({"/user06","/user07"})
	public ModelAndView test06() {
		System.out.println("設置多個映射路徑");
		return null;
	}

}
複製代碼

2.路徑模式的匹配規則

閱讀一下,咱們簡單瞭解一下規則就行,主要介紹一下通配符"*"的演示,實際開發中我的基本上沒有使用過.正則表達式

package com.hanpang.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller//告知其是一個控制器
@RequestMapping("/web")
public class Demo02Controller {

	@RequestMapping("/*")
	public ModelAndView test01() {
		System.out.println("* 表明一層");
		return null;
	}

	@RequestMapping("/**")
	public ModelAndView test02() {
		System.out.println("** 表明任意層次");
		return null;
	}

}
複製代碼

NOTE: 誰描述的更加準確,就執行誰spring

測試路徑以下:api

http://127.0.0.1:8001/mvc/web/user01 執行tes01方法
http://127.0.0.1:8001/mvc/web/user02 執行tes01方法
http://127.0.0.1:8001/mvc/web/user01/user02  執行tes02方法
http://127.0.0.1:8001/mvc/web/a/b/c/d  執行tes02方法
複製代碼

package com.hanpang.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller//告知其是一個控制器
@RequestMapping("/web")
public class Demo02Controller {

	@RequestMapping("/*")
	public ModelAndView test01() {
		System.out.println("* 表明一層");
		return null;
	}

	@RequestMapping("/role*")
	public ModelAndView test02() {
		System.out.println("role* 的描述更準確");
		return null;
	}

	@RequestMapping("/role")
	public ModelAndView test03() {
		System.out.println("role 我更準確");
		return null;
	}
}
複製代碼

修改以前上面的代碼,咱們繼續測試路徑瀏覽器

http://127.0.0.1:8001/mvc/web/user01 執行test01方法
http://127.0.0.1:8001/mvc/web/roleuser01 執行test02方法
http://127.0.0.1:8001/mvc/web/role 執行test03方法
複製代碼

使用通配符的方式真的不多,可是實際開發中咱們常常使用URI模式,路徑傳遞數據的方式(佔位符),咱們再次修改原來代碼mvc

package com.hanpang.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller//告知其是一個控制器
@RequestMapping("/web")
public class Demo02Controller {

	@RequestMapping("/*")
	public ModelAndView test01() {
		System.out.println("* 表明一層");
		return null;
	}

	@RequestMapping("/**")
	public ModelAndView test02() {
		System.out.println("** 表明一層");
		return null;
	}

	@RequestMapping("/{a}")
	public ModelAndView test03() {
		System.out.println("{a} 一個佔位符");
		return null;
	}
	@RequestMapping("/{a}/{b}")
	public ModelAndView test04() {
		System.out.println("/{a}/{b} 多個佔位符");
		return null;
	}

}
複製代碼

測試路徑:app

http://127.0.0.1:8001/mvc/web/user01 執行test03方法
http://127.0.0.1:8001/mvc/web/user01/user02 執行test04方法
http://127.0.0.1:8001/mvc/web/user01/user02//user03 執行test02方法
複製代碼

NOTE: 發現佔位符的描述性比通配符的描述更加準確框架


當一個URL同時匹配多個模式時,只會選擇最匹配的一個:

  • URI模式變量的數目和通配符數量的總和最少的那個路徑模式更準確。好比,/hotels/{hotel}/*這個路徑擁有一個URI變量和一個通配符,而/hotels/{hotel}/**這個路徑則擁有一個URI變量和兩個通配符,所以前者是更準確的路徑模式。
  • 若是兩個模式的URI模式數量和通配符數量總和一致,則路徑更長的那個模式更準確。舉個例子,/foo/bar*就被認爲比/foo/*更準確,由於前者的路徑更長。
  • 若是兩個模式的數量和長度均一致,則那個具備更少通配符的模式是更加準確的。好比,/hotels/{hotel}就比/hotels/*更精確。
  • 默認的通配模式/**比其餘全部的模式都更"不許確"。比方說,/api/{a}/{b}/{c}就比默認的通配模式/**要更準確
  • 前綴通配(好比/public/**)被認爲比其餘任何不包括雙通配符的模式更不許確。例如,/public/path3/{a}/{b}/{c}就比/public/**更準確

3.URI模式

請重視這種模式,URI模式爲獲取**@RequestMapping**中指定的URL的眸一個特定部分提供很大的方便。

URI模式是一個相似於URI的字符串,只不過其中包含了一個或多個的變量名。當使用實際的值去填充這些變量名的時候,模式就成爲一個URI。好比說,一個這個URI模式http://127.0.0.1/mvc/shxt/{userId}就包含了一個變量名userId。將值1001賦給這個變量名後,它就變成了一個URI:http://127.0.0.1/mvc/shxt/1001

在Spring MVC中能夠在方法參數上使用@PathVariable標註,將其與URI模式中的參數綁定起來:

瀏覽器訪問路徑以下: http://127.0.0.1:8001/mvc/shxt/1001

package com.hanpang.web;

@Controller//告知其是一個控制器
@RequestMapping("/shxt")
public class Demo03Controller {
	@RequestMapping("/{userId}")
	public ModelAndView test01(@PathVariable String userId) {
		System.out.println("獲取佔位符的值:"+userId);
		return null;
	}
}
複製代碼

會在控制檯輸出: 獲取佔位符的值:1001

URI模式"/shxt/{userId}"定義了一個變量,名爲userId。當控制器處理這個請求的時候,userId的值就會被URI模式中對應部分的值所填充。好比說,若是請求的URI是/userId/1001,此時變量userId的值就是1001

若是形參id跟佔位符{userId}不一致

爲了處理@PathVariables標註,Spring MVC必須經過變量名來找到URI模式中相對應的變量。能夠在標註中直接聲明:

package com.hanpang.web;

@Controller//告知其是一個控制器
@RequestMapping("/shxt")
public class Demo03Controller {
	@RequestMapping("/{userId}")
	public ModelAndView test01(@PathVariable(name="userId") String id) {
		System.out.println("獲取佔位符的值:"+id);
		return null;
	}
}
複製代碼

一個方法能夠擁有任意數量的@PathVariable標註:

package com.hanpang.web;

@Controller//告知其是一個控制器
@RequestMapping("/shxt")
public class Demo03Controller {

	@RequestMapping("/{userId}/role/{roleKey}")
	public ModelAndView test01(@PathVariable(name="userId") String id,@PathVariable String roleKey) {
		System.out.println("userId:"+id);
		System.out.println("roleKey:"+roleKey);
		return null;
	}
}
複製代碼

@PathVariable標註被應用於Map<String, String>類型的參數上時,框架會使用全部URI模式變量來填充map。

package com.hanpang.web;

@Controller//告知其是一個控制器
@RequestMapping("/shxt")
public class Demo03Controller {

	@RequestMapping("/{userId}/role/{roleKey}")
	public ModelAndView test01(@PathVariable Map<String,String> map) {
		System.out.println(map);
		return null;
	}
}
複製代碼

@PathVariable能夠被應用於全部簡單類型的參數上,好比int、long、Date等類型。Spring會自動地幫你把參數轉化成合適的類型,若是轉換失敗,就拋出一個TypeMismatchException。若是須要處理其餘數據類型的轉換,也能夠註冊自定義的類。


帶正則表達式的URI模式[來自官網]

有時候可能須要更準確地描述一個URI模式的變量,好比:/spring-web/spring-web-3.0.5.jar。要怎麼把它分解成幾個有意義的部分呢?

@RequestMapping標註支持在URI模式變量中使用正則表達式。語法是{varName:regex},其中第一部分定義了變量名,第二部分就是所要應用的正則表達式。好比下面的代碼樣例:

@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")
    public void handle(@PathVariable String version, @PathVariable String extension) {
        // ......
    }
}
複製代碼

除了URI模式外,@RequestMapping標註還支持Ant風格的路徑模式(如/myPath/*.do等)。不只如此,還能夠把URI模式變量和Ant風格的glob組合起來使用(好比/owners/*/pets/{petId}這樣的用法等)。

相關文章
相關標籤/搜索