@RequestMapping
個人建議重新練習一遍搭建的過程,如果感覺麻煩你可以直接複製上一個工程,但是需要修改pom.xml中的一點資訊
<groupId>com.hanpang.springmvc</groupId>
<artifactId>springmvc-demo02</artifactId>
<version>0.0.1-SNAPSHOT</version>
複製程式碼
1.基本用法
我們可以使用@RequestMapping標註來將請求URL(類似於@WebServlet),如/hanpang等,對映到整個類上或某個特定的處理器方法上。
一般來說,類級別的標註負責將一個特定(或符合某種模式)的請求路徑對映到一個控制器上,同時通過方法級別的標註來細化對映,即根據特定的HTTP請求方法(“GET”和“POST”方法等)、HTTP請求中是否攜帶特定引數等條件,將請求對映到匹配的方法上。
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: 誰描述的更加準確,就執行誰
測試路徑如下:
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模式,路徑傳遞資料的方式(佔位符),我們再次修改原來程式碼
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;
}
}
複製程式碼
測試路徑:
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}
這樣的用法等)。