SpringMVC中的@RequestMapping注解的使用詳細教程
@RequestMapping注解的功能
從注解名稱上我們可以看出,@RequestMapping注解的作用就是將請求和處理請求的控制器方法關(guān)聯(lián)起來,建立映射關(guān)系,SpringMVC接收到指定的請求,就會來找到在映射關(guān)系中對應(yīng)的控制方法來處理這個請求。
@RequestMapping注解的位置
@RequestMapping標(biāo)識一個類:設(shè)置映射請求的請求路徑的初始信息
@RequestMapping標(biāo)識一個方法:設(shè)置映射請求,請求路徑的具體信息
如下所示:
當(dāng)前我們Protal方法的訪問路徑是hello
package AnnotationController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ProtalController {
@RequestMapping("/hello")
public String Protal(){
return "index";
}
}
當(dāng)前的控制層,我們只給控制層中的Protal方法加上了@RequestMapping注解,而并沒有給該控制層的類上加,因此我們可以直接通過Protal方法上的請求路徑訪問。
假設(shè)我們此時也給類加上@RequestMapping注解,訪問地址不變化,如下所示:
@RequestMapping("test")
public class ProtalController {訪問結(jié)果如下所示,我們會發(fā)現(xiàn)當(dāng)前資源無法被找到

要想資源 被正確的訪問,我們需要進行如下操作:
在路徑的具體信息之前添加路徑的初始信息,因為當(dāng)在類上添加了請求路徑的初始信息之后,我們想訪問該類中的某個方法,就必須先正確的訪問到該類。

而這樣做的目的在于,在實際開發(fā)中,我們往往會給請求方法設(shè)置較為簡單的路徑請求具體信息,例如查詢學(xué)生的方法,我們會將其請求路徑具體的信息設(shè)置select,刪除學(xué)生的方法,我們會將其我們會將其請求路徑具體的信息設(shè)置delete,而需求往往不是適合于一類人而已,對于除學(xué)生以外的其他用戶,都會有增刪的操作,這樣就導(dǎo)致了,系統(tǒng)也不知道該訪問哪一個,因此,我們需要在類上添加請求路徑的初始化信息。
@RequestMapping注解value屬性值
我們通過查看@RequestMapping注解:
它的匹配方式有很多種,通過請求路徑,通過請求方法…,而比較常用的就是通過path和method
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}@RequestMapping注解value屬性
通過查看源碼可知,value的類型為String[],如下所示:
我們將@RequestMapping的值設(shè)置為多個
package AnnotationController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ProtalController {
//當(dāng)匹配方式中只有value時,value可以省略不寫
@RequestMapping({"/hello","/abc"})
public String Protal(){
return "index";
}
}那么我們是否可以根據(jù)數(shù)組中任意的一個值來訪問到正確的資源呢?
我們將項目重新部署:


由此可知,@RequestMapping注解value屬性的作用是:通過請求的請求路徑匹配請求,value屬性是數(shù)組類型,即當(dāng)前瀏覽器所發(fā)送請求的請求路徑匹配value屬性中的任何一個值,則當(dāng)前請求就會被注解所標(biāo)識的方法進行處理
@RequestMapping注解method屬性
通過查看源碼如下所示,我們知道m(xù)ethod屬性是ReuestMethod類型的:
RequestMethod[] method() default {<!-- -->};繼續(xù)跟進查看ReuestMethod的源碼,如下所示:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.web.bind.annotation;
public enum RequestMethod {
GET,
HEAD,
POST,
PUT,
PATCH,
DELETE,
OPTIONS,
TRACE;
private RequestMethod() {
}
}我們發(fā)現(xiàn)它是一個枚舉類型,列舉了所有的請求方式,其中g(shù)et和post是我們已經(jīng)學(xué)過的,那么接下來我們就以post和get請求為例演示起作用。
創(chuàng)建實現(xiàn)頁面跳轉(zhuǎn)的模塊
首頁請求控制器:
package AnnotationController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ProtalController {
@RequestMapping("/")
public String Protal(){
return "index";
}
}跳轉(zhuǎn)頁面請求控制器
package AnnotationController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class JumpPageController {
@RequestMapping(value = {"/hello","/abc"},method= RequestMethod.GET)
public String Page(){
return "success";
}
}index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁</title>
</head>
<body>
<h1>成功進入首頁!</h1>
<a th:href="@{/hello}">測試@RequestMapping注解所標(biāo)識的位置</a><br>
<a th:href="@{/abc}">測試@RequestMapping注解的value屬性</a><br>
<form th:action="@{/hello}">
<input type="submit" value="測試@RequestMapping注解的method屬性">
</form>
</body>
</html>success.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>成功</title>
</head>
<body>
<h1>成功進入!</h1>
</body>
</html>此時運行服務(wù)器,如下所示:

點擊其中的任何一個連接,都會出現(xiàn)如下字樣:

通過輸出結(jié)果,我們不難發(fā)現(xiàn)將@RequestMapping注解中的method屬性值設(shè)置為RequestMethod.GET,也就是匹配get請求的方式是沒有任何問題的,那么如果我們將其匹配的是post還會如此嗎?
修改@RequestMapping注解中的method屬性值為RequestMethod.POST,再次運行:
出現(xiàn)下述異常:
tomcat告訴我們是因為方法不被支持

那為什么當(dāng)我們將將@RequestMapping注解中的method屬性值設(shè)置為RequestMethod.GET就能正確的處理請求?原因是:無論是超鏈接還是表單,默認的提交方式都是get請求,因此當(dāng)我們沒有設(shè)置其值的情況情況下,默認的就是get請求方式
我們可以將表單的提交方式設(shè)置為POST,這樣就可以處理POST請求了:
<form th:action="@{/hello}" method="post">
<input type="submit" value="測試@RequestMapping注解的method屬性">
</form>如下所示,通過method屬性,將其表單提交的方式設(shè)置為post

此時點擊該按鈕就可以成功的進入success.html頁面啦
但是需要注意的是,如果我們把當(dāng)前可以訪問成功的地址復(fù)制,直接在瀏覽器中訪問,如下所示:

還是出現(xiàn)了405錯誤,原因是我們將地址復(fù)制直接通過地址欄訪問,實際上是get請求,但是我們又在注解中將其請求方法設(shè)置為post請求,由于未能匹配,所以出現(xiàn)了405錯誤
通過查看它的源碼,我們得知其method是一個數(shù)組類型的,那么我們就可以利用這一特性,讓它既能匹配get請求,又能匹配post請求,設(shè)置如下所示:
@RequestMapping(value = {"/hello","/abc"},method= {RequestMethod.POST,RequestMethod.GET})此時我們刷新剛剛復(fù)制地址,而導(dǎo)致報錯的頁面,就能成功訪問啦,只要是get、post中的任意一個都能被成功訪問
@RequestMapping注解的method屬性的作用是通過請求的請求方式匹配請求,它RequestMethod類型的數(shù)組,即當(dāng)前瀏覽器所發(fā)送請求的請求方式匹配method屬性中的任何一個請求,如果匹配成功,那么當(dāng)前請求就會被注解所標(biāo)識的方法進行處理,若瀏覽器所發(fā)送的請求的請求路徑和@RequestMapping注解value屬性匹配,但是請求方式不匹配,頁面會報錯,如下所示:

在@ResquestMapping的基礎(chǔ)上,結(jié)合請求方式的一些派生注解:
@GetMapping,@PostMapping,@DeleteMapping,@PutMapping,關(guān)于這些注解在后續(xù)的學(xué)習(xí)中會使用。
@RequestMapping注解params屬性
String[] params() default {<!-- -->};@RequestMapping注解params屬性的作用是通過請求的請求參數(shù)匹配請求,即瀏覽器發(fā)送的請求的請求參數(shù)必須滿足params屬性的設(shè)置,params可以使用四種表達式:
“param”:表示當(dāng)前所匹配請求的請求參數(shù)中必須攜帶param參數(shù)
測試如下所示:
在注解中,我們添加param屬性,并給定一個值為username
package AnnotationController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class JumpPageController {
@RequestMapping(value = {"/hello","/abc"},
method= {RequestMethod.POST,RequestMethod.GET}
,params = {"username"})
public String Page(){
return "success";
}
}再重新進行項目的部署,點擊超鏈接或者表單中的按鈕,出現(xiàn)以下錯誤:

原因是,我們在注解中設(shè)置了其參數(shù)的值,而在地址欄中并沒有該參數(shù)的值,所以會報錯。
解決方法如下所示:
<!--以下兩種方式毫無區(qū)別,唯一的區(qū)別是第一種寫法在源文件中會報錯,但是該報錯不影響代碼的編譯和執(zhí)行 -->
<a th:href="@{/hello?username=admin}" >測試@RequestMapping注解的param屬性</a><br>
<a th:href="@{/hello(username='admin')}" >測試@RequestMapping注解的param屬性</a>通過這種方式,瀏覽器會在地址欄自動為我們添加其值,如下所示:
此時頁面也能被成功的訪問到!

但需要注意的是,param屬性和method屬性以及value屬性可不一樣哦,當(dāng)我們將method屬性和value屬性中設(shè)置有多個值時,只要能匹配到其中的任意一個即可,但是對于param屬性來說,如果設(shè)置的值有多個必須同時匹配,測試如下:
給param屬性值增加password,其他地方不做任何的變動
@RequestMapping(value = {"/hello","/abc"},
method= {RequestMethod.POST,RequestMethod.GET}
,params = {"username","password"})測試結(jié)果如下所示:

此時報錯原因依然為在注解中設(shè)置了Parma屬性值password,但是未能匹配到該值,所以出現(xiàn)錯誤,解決方法有兩種,一種是我們在html文件中設(shè)置該參數(shù),由瀏覽器自動為我們匹配,如下所示:
index.html:
<a th:href="@{/hello(username=${admin},password=${1234})}" >測試@RequestMapping注解的param屬性</a>
<a th:href="@{/hello(username='admin',password='12345')}">測試@RequestMapping注解的param屬性</a>重新部署項目,運行如下所示:

第二種方式是我們在地址欄通過手動添加缺失的參數(shù),如下所示:

也可以成功進入到我們想訪問的頁面!
“!param”:表示當(dāng)前所匹配請求的請求參數(shù)中一定不能攜帶param參數(shù)
假設(shè)此時我們將注解修改如下所示:
請求參數(shù)中不可以包含password,即使是只有password這個參數(shù),沒有值也不可以。
@RequestMapping(value = {"/hello","/abc"},
method= {RequestMethod.POST,RequestMethod.GET}
,params = {"username","!password"})重新部署項目如下所示,我們手動在地址欄添加了password,雖然只是添加了該參數(shù)沒有給定具體的值,結(jié)果也報錯了。

“param=value”:表示當(dāng)前所匹配請求的請求參數(shù)中必須攜帶param參數(shù)且值必須為value
假設(shè)此時我們將注解修改如下所示:
添加請求參數(shù),并將其值設(shè)置為20
@RequestMapping(value = {"/hello","/abc"},
method= {RequestMethod.POST,RequestMethod.GET}
,params = {"username","!password","age=20"})重新部署項目,如下所示,只有當(dāng)注解中的設(shè)置的所有請求參數(shù)都被滿足時,該請求才能被正確處理

“param!=value”:表示當(dāng)前所匹配請求的請求參數(shù)中可以不攜帶param,若攜帶值一定不能是value
假設(shè)此時我們將注解修改如下所示:
添加新的請求參數(shù)gender,并設(shè)置其值不能為男
@RequestMapping(value = {"/hello","/abc"},
method= {RequestMethod.POST,RequestMethod.GET}
,params = {"username","!password","age=20","gender!=男"})重新部署項目,測試如下所示:
手動添加其參數(shù)的值,gender的值可以是除了男以外的任何值,當(dāng)然也可以不傳值,或者不手動在地址欄添加該請求參數(shù)均可



@RequestMapping注解headers屬性
String[] headers() default {<!-- -->};@RequestMapping注解的headers屬性通過請求的請求頭信息匹配請求映射,它是一個字符串類型的數(shù)組,可以通過四種表達式設(shè)置請求頭信息和請求映射的匹配關(guān)系,如下所示:
"header":要求請求映射所匹配的請求必須攜帶header請求頭信息
"!header":要求請求映射所匹配的請求必須不能攜帶header請求頭信息
"header=value":要求請求映射所匹配的請求必須攜帶header請求頭信息且header=value
"header!=value":要求請求映射所匹配的請求必須攜帶header請求頭信息且header!=value
若當(dāng)前請求滿足@RequestMapping注解的value和method屬性,但是不滿足headers屬性,此時頁面顯示404錯誤,即資源未找到
例如:我們可以通過設(shè)置headers的referer屬性來指明當(dāng)前資源的來源地址,如下所示:
@RequestMapping(value = {"/hello","/abc"},
method= {RequestMethod.POST,RequestMethod.GET},headers = {"referer"})重新部署項目,在瀏覽器中右擊打開檢查,如下所示為我們?yōu)辄c擊該超鏈接的請求頭信息:

此時我們點擊該超鏈接,如下圖所示,與上圖不同之處在于多了一個Referer屬性,而該屬性的值即為該頁面的來源地址

注意:響應(yīng)頭和請求頭中的鍵不區(qū)分大小寫,但是其鍵值區(qū)分大小寫
@RequestMapping注解使用ant風(fēng)格的路徑
?:表示任意的單個字符
舉例如下:
**第一步:**編寫新的測試方法,并將其RequestMapping的值設(shè)置為/a?a/test/ant
package AnnotationController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class JumpPageController {
@RequestMapping("/a?a/test/ant")
public String testAnt(){
return "success";
}
}第二步:在index.html中為其添加超鏈接
<a th:href="@{/aaa/test/ant}">測試@RequestMapping注解支持ant風(fēng)格的路徑</a><br>將項目重新部署,測試結(jié)果如下:

點擊該超鏈接:

通過我們在index.html文件中設(shè)置的路徑,此時資源被正確的訪問到,既然?是代表一個任意的字符,那么我們可以將a和a中鍵的位置任意選擇一個符號來代替,可以是數(shù)字,可以是其他字母,當(dāng)然也可以是特殊字符,但是需要注意不能是英文的問號,中文的問號是可以的,否則如下所示:

原因是**?前面是請求路徑,問號后面是請求參數(shù)**,/a?a/test/ant并不會被當(dāng)做一個完整的請求路徑,其替代?的字符也不能是/,因為它代表地址的分隔符,表示新的一層目錄
*:表示任意的0個或多個字符
舉例如下:
此時我們將上述注解中的?替換為*,如下所示:
@RequestMapping("/a*a/test/ant")將項目重新部署后,刷新瀏覽器頁面如下所示:
無論是一個字符還是多個字符,都能成功的訪問地址


而需要注意的是和?占位符相同,此時替代*的字符不可以是/或者?(英文),否則會出現(xiàn)404,原因和?的是相通的


**:表示任意層數(shù)的任意目錄
舉例如下:
將路徑中的具體信息修改為如下所示:
@RequestMapping("/**/test/ant")需要注意的是**只能寫在//中,前后都不能有任何的字符。
錯誤實例:
@RequestMapping("/a**a/test/ant")
@RequestMapping("/**a/test/ant")重新部署項目,測試結(jié)果如下所示:
/**/所代表的的目錄我們既可以設(shè)置為一層,也可以設(shè)置為多層


但需要注意的是,即使可以設(shè)置任意層,但是目錄中依然不可以包含有英文的問號,否則如下所示:

注意:在使用**時,只能使用/**/xxx的方式
@RequestMapping注解使用路徑中的占位符
通過路徑傳值的傳統(tǒng)方式為:
/deleteUser?id=1
下面我們要介紹一種簡單的方式:需要在@RequestMapping注解的value屬性中所設(shè)置的路徑中,使用{xxx}的方式表示路徑中的數(shù)據(jù),在通過@PathVariable注解,將占位符所標(biāo)識的值和控制器方法的形參進行綁定,具體操作如下所示:
第一步:編寫對應(yīng)的控制器方法
package AnnotationController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class JumpPageController {
//注意:有幾個參數(shù)需要寫幾個{xxx}{xxx}
@RequestMapping("/test/rest/{username}/{id}")
//@PathVariable注解的值必須與@RequestMapping注解路徑具體信息中的參數(shù)名稱相一致,否則會出現(xiàn)500錯誤
public String testRest(@PathVariable("id") Integer id,@PathVariable("username") String username){
//獲取對應(yīng)參數(shù)的值
System.out.println("id:"+id+","+"username:"+username);
return "success";
}
}第二步:在index.html文件中,設(shè)置其參數(shù)的具體值
注意這里值的順序應(yīng)與@RequestMapping注解中的參數(shù)順序保持一致,否則會因為類型不匹配導(dǎo)致出現(xiàn)400錯誤
<a th:href="@{/test/rest/admin/1}">測試@RequestMapping注解value屬性中的占位符</a><br>重新部署項目,測試結(jié)果如下:
在瀏覽器欄顯示了其參數(shù)的值

在控制臺,也將對應(yīng)的參數(shù)信息顯示出來了

以上就是SpringMVC中的@RequestMapping注解的使用詳細教程的詳細內(nèi)容,更多關(guān)于SpringMVC @RequestMapping注解的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot中EasyExcel實現(xiàn)Excel文件的導(dǎo)入導(dǎo)出
這篇文章主要介紹了SpringBoot中EasyExcel實現(xiàn)Excel文件的導(dǎo)入導(dǎo)出,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
JAVA 統(tǒng)計字符串中中文,英文,數(shù)字,空格,特殊字符的個數(shù)
這篇文章主要介紹了JAVA 統(tǒng)計字符串中中文,英文,數(shù)字,空格,特殊字符的個數(shù) ,本文通過一段代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-06-06
FeignClient如何通過配置變量調(diào)用配置文件url
這篇文章主要介紹了FeignClient如何通過配置變量調(diào)用配置文件url,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
Java擴展庫RxJava的基本結(jié)構(gòu)與適用場景小結(jié)
RxJava(GitHub: https://github.com/ReactiveX/RxJava)能夠幫助Java進行異步與事務(wù)驅(qū)動的程序編寫,這里我們來作一個Java擴展庫RxJava的基本結(jié)構(gòu)與適用場景小結(jié),剛接觸RxJava的同學(xué)不妨看一下^^2016-06-06

