1. 程式人生 > >springMVC請求對映全面分析

springMVC請求對映全面分析

在springMVC的控制器中,我們常使用@RequestMapping來完成我們的請求對映,我們可以在類定義上和方法定義上使用註解,其配置的路徑將為類中定義的所有方法的父路徑,如上篇例項中的/user(類)/hello(方法)。
一般的,我們類定義上的路徑註解起到名稱空間的作用,防止不同方法的路徑對映產生衝突,比如我在UserController和ArticleController下都定義瞭如下的方法:

@RequestMapping("list")
public void list(){
    ....
}

一個list對映路徑,這時候springMVC就不知道該將請求交給到哪個方法處理。當然,我們也能在方法上進行二級路徑配置區分:

/*************UserController***********/
@RequestMapping("user/list")
public void list(){
    ....
}
/*************ArticleController***********/
@RequestMapping("article/list")
public void list(){
    ....
}

這樣就能有效防止衝突了,但如果我有很多個方法存在這樣的衝突,是否都要在每個方法加上字首呢?這時候我們可以選擇在類路徑上註解@RequestMapping來對全體方法進行區分。

通過url進行對映

1. Ant風格字元匹配

除了標準的url外,@RequestMapping還支援Ant風格字元,即”?”、”*”、”**”,其中
1. “?”:匹配一個任意字元,如/user/a?,匹配user/aa,user/ab等路徑
2. “*”:匹配任意字串,如/user/a*,匹配/user下任意以a開頭的路徑如/user/abc,/user/aqw等
3. “**“:匹配多級路徑字串,如/user/**/list,匹配/user/user1/list,/user/1resu/list等

在這裡,需要注意的是當*的位置個數不同時,*可以代表的字元數有區別,看下面示例:

@RequestMapping("u1/*")//只能匹配u1/a,u1/b,不能匹配u1/————即此時*表示一個或多個字元
public void test(HttpServletResponse response) throws IOException{ response.getWriter().print("u1/*"); } @RequestMapping("u1/**")//能夠匹配u1/,u1/qq,u1/qq/ww,這裡要特別注意的是,“**“能匹配零個而“*”不能 public void test(HttpServletResponse response) throws IOException{ response.getWriter().print("u1/*"); } @RequestMapping("u2/a*")//能夠匹配u2/a,u2/ab,u2/aqqqq等————即此時*表示零個或零個以上字元 public void test1(HttpServletResponse response) throws IOException{ response.getWriter().print("u2/a*"); }

2. restful佔位符匹配

除了使用上面風格,@RequestMapping還支援restful風格佔位符的形式,假如我們需要針對特定使用者檢視其特定文章,restful風格路徑匹配如下所示:


@Controller//註解為控制器,通過spring容器掃描,會註冊為一個Bean
@RequestMapping("/user/{uid}")//一級訪問路徑,對類中所有方法生效
public class UserController {
    @RequestMapping("article/{aid}")
    public String detail(@PathVariable("uid")Integer uid,@PathVariable("aid")Integer aid){
        System.out.println( "檢視id為" + uid + "的使用者文章,且文章id為"+aid);
        return "someplace";
    }
}

這裡,如果我們想訪問使用者id為1,文章id為2的使用者文章,就可以訪問如下路徑:[專案根路徑]/user/1/article/2來完成。
我們使用@PathVariable(“val”)來完成對應路徑中{val}的資源請求,這裡的兩個val名稱需一致,緊接著的方法入參名字任意,我們剛剛示例了一個多路徑引數繫結,假設只有一個,如下也是合法的:

@RequestMapping("user/{uid}")
    public String detail(@PathVariable("uid")Integer notUid){//notUid名字也能成功繫結
        return "someplace";
    }

此外,如果我們入參名字和url路徑資源名稱一致,則可以省略配置@PathVariable中的value值,如下例項也能正確繫結路徑資源到入參

@RequestMapping("user/{uid}")
    public String detail(@PathVariable Integer uid){//notUid名字也能成功繫結
        return "someplace";
    }

3. 優先匹配規則

url還有如下兩個常見匹配準則:最長最精確優先匹配佔位符優先匹配

1. 最長最精確優先匹配

下面我們來看一個匹配例項:

@RequestMapping("test/**")
public void test2(HttpServletResponse response) throws IOException{
    response.getWriter().print("test/**");
}
@RequestMapping("test/*")
public void test3(HttpServletResponse response) throws IOException{
    response.getWriter().print("test/*");
}
@RequestMapping("test/*/**")
public void test4(HttpServletResponse response) throws IOException{
    response.getWriter().print("test/*/**");
}
@RequestMapping("test/*/*")
public void test5(HttpServletResponse response) throws IOException{
    response.getWriter().print("test/*/*");
}
@RequestMapping("test/1/*")
public void test6(HttpServletResponse response) throws IOException{
    response.getWriter().print("test/1/*");
}
@RequestMapping("test/1/2")
public void test7(HttpServletResponse response) throws IOException{
    response.getWriter().print("test/1/2");
}

直接看上面匹配會覺得很亂,我們直接看下面的測試:

測試 匹配結果
test/a 匹配test/*而不匹配test/**(更精確優先匹配)
test/a/a/aa/a 匹配test/**而不匹配test/*/**,(在多層匹配中,**比*/**更精確)
test/a/a 匹配test/*/*,因為/*/*比**精確
test/1/a 匹配test/1/*,因為/1/*比/*/*精確
test/1/2 匹配test/1/2,這是完全匹配

2. 佔位符優先匹配原則

佔位符是指@PathVariable等路徑資源佔位符,下面我們在看一個例項

@RequestMapping("test/1/2")
public void test7(HttpServletResponse response) throws IOException{
    response.getWriter().print("test/1/2");
}
@RequestMapping("test/1/{id}")
public void test8(HttpServletResponse response,@PathVariable Integer id ) throws IOException{
    response.getWriter().print("test/1/(myId=)" + id );
}
@RequestMapping("test/1/a")
public void test7(HttpServletResponse response) throws IOException{
    response.getWriter().print("test/1/a");
}

從上一個例項的所有路徑對映中,我們測試出test/1/2是最精確的。但我們根據添加了佔位符對映,在遊覽器輸入test/1/2,此時遊覽器返回test/1/(myId=)2,即佔位符的優先順序比普通字串的優先順序更高!但如果我們此時輸入test/1/a。程式不會因為我們的在方法入參中id對映為Integer型別而放棄匹配,佔位符的優先順序依然比字元(串)a的優先順序高,但由於“a”不能轉化為Integer型別,所以伺服器會返回400錯誤

通過HTTP其它請求資源對映

除了使用url外,我們還能通過請求引數、請求方法、或請求頭進行對映
我們先看看@RequestMapping的完整屬性列表:

屬性 說明
value 指定請求的實際地址, 比如 /action/info之類。
method 指定請求的method型別, GET、POST、PUT、DELETE等
consumes 指定處理請求的提交內容型別(Content-Type),例如application/json, text/html;
produces 指定返回的內容型別,僅當request請求頭中的(Accept)型別中包含該指定型別才返回
params 指定request中必須包含某些引數值是,才讓該方法處理
headers 指定request中必須包含某些指定的header值,才能讓該方法處理請求

其中,consumes, produces使用content-type資訊進行過濾資訊;headers中可以使用content-type進行過濾和判斷。
在前面的使用中,我們發現並沒有指定value屬性,直接在括號裡輸入字串也能向value屬性賦值,這是因為在java註解中不加其他屬性,直接賦值必定是針對註解的value成員,如果該註解沒有名為value的成員,則會報錯
下面我們先看幾個示例:

示例1:vmethod,headers

@RequestMapping(value = "testa",method = RequestMethod.POST,headers = "content-type=text/*")

表示對映路徑為testa,請求方法必須為POST方法(如果我們用post發出請求,會返回錯誤資訊HTTP Status 405 - Request method ‘GET’ not supported),headers部分表示請求頭資訊中必須包含等號後相應部分內容,*匹配任意字串

示例2:consumes

@RequestMapping(value = "testb", consumes="application/json") 

表示方法僅匹配request Content-Type為“application/json”型別的請求。

示例3:produces

@RequestMapping(value = "/testc", produces="application/json")

表示方法匹配的請求需要請求頭中Accept部分包含”application/json“,同時在響應時,會將返回內容同時設定為”application/json‘’

示例4:params

@RequestMapping(value = "testd",method = RequestMethod.GET,params = {"id1","id2"})
public void test12(HttpServletResponse response,Integer id1,Integer id2) throws IOException{
    response.getWriter().print(id1 + "——" + id2);
}

示例表示入參需包含引數名為id1,id2的兩個引數,這裡如果我輸入:
1. http://localhost:8080/springMVC/user/testd—-報404錯誤
2. http://localhost:8080/springMVC/user/testd?id1=1報404錯誤
3. ttp://localhost:8080/springMVC/user/testd?id1=1&id2=2—-返回1——2
4. ttp://localhost:8080/springMVC/user/testd?id1=1&id2=2&id3=3—-返回1——2

從以上我們可以看出,只有具有相應引數的才能完成對映,且可以有除了params中要求以外的引數,如id3。

在params的常見對映規則如下:

示例規則 說明
”param1” 請求必須包含名為param1的引數
“!param1” 請求中不能包含名為param1的引數
“param1!=value1 請求中必須包含param1引數,但其值不能為value1
{“param1=value1”,”param2”} 請求中需要包含param1引數和param2引數,且param1的值必須為value1

相關推薦

springMVC請求對映全面分析

在springMVC的控制器中,我們常使用@RequestMapping來完成我們的請求對映,我們可以在類定義上和方法定義上使用註解,其配置的路徑將為類中定義的所有方法的父路徑,如上篇例項中的/user(類)/hello(方法)。 一般的,我們類定義上的路徑註

springMVC4(2)請求對映全面分析

在springMVC的控制器中,我們常使用@RequestMapping來完成我們的請求對映,我們可以在類定義上和方法定義上使用註解,其配置的路徑將為類中定義的所有方法的父路徑,如上篇例項中的/user(類)/hello(方法)。 一般的,我們類定義上的路徑註

springMVC請求對映

@RequestMapping(params="create", method=RequestMethod.GET) //表示請求中有“create”的引數名且請求方法為“GET”即可匹配,

SpringMVC請求對映handler原始碼解讀

#### 請求對映原始碼 首先看一張請求完整流轉圖(這裡感謝部落格園上這位大神的圖,部落格地址我忘記了): ![](https://img2020.cnblogs.com/blog/1461099/202103/1461099-20210316192419508-1150727680.png) 前臺傳送

SpringMVC-3 對映請求引數和請求

  Spring MVC通過分析控制器處理方法的簽名,將 HTTP請求資訊繫結到處理方法的相應人蔘中。除@PathVariable註解外,SpringMVC還可使用@RequestParam、@Requ

SpringMvc請求過程分析

SpringMvc請求過程分析 第一步: 請求離開瀏覽器攜帶URL到達前端控制器(DispatcherServlet),DispatcherSevlet將請求傳送給Spring MVC控制器(controller),一般應用中有多個控制器. 前端控制器:web.xml檔案中的

Intellij Idea-統一顯示SpringMVC請求和處理方法對映列表

前言 在SpringMVC中請求連結跟處理方法的對映關係因為@RequestMapping分佈在專案的各個方法上,所以不能像Struts那樣統一管理。 Intellij Idea提供了相關的支援; 新增支援 IDEA 控制檯下方預設有Spring

一篇文章搞定springMVC中的請求對映

實驗的專案是採用預設配置的spring boot專案,使用的工具為IDEA和POSTMAN。 希望這些案例能夠幫助你理解和思考。 talk is cheap,show me the code! 1、從最簡單的hello world開始 @

全面分析:內部無法使用對映的公網來訪問內部伺服器的原因

        往往我們在配置完路由器將內部成功訪問到外部網際網路以及外部網際網路能訪問成功所對映的伺服器時,就認為已經配置完成。卻忽略了仍然存在的一個重大問題:內部使用者無法使用對映的公網IP來訪問到內部伺服器。每個廠家的路由器都會出現這個問題,可能是一種安全機制,或者是

SpringMVC筆記系列(2)——@RequestMapping請求對映物理檢視解析

上一篇的例子介紹瞭如何構建一個springMVC的請求對映的方法。但是@RequestMapping不僅可以修飾控制器類的方法,還可以可以修飾控制器類本身,它對請求的影響是:請求url的分段。 還是看一個例子吧。 假如現在有一個請求頁面index2.js

Spring原始碼分析之Spring MVC之HanderMapping請求對映處理

AbstractHandlerMappig呼叫getHandler() /** * Look up a handler for the given request, falling back to the default * handler if no speci

SpringMVC請求處理原始碼分析從service到doDispatch(一)

說明:本文所用的SpringMVC版本為4.3.4.RELEASE,應用伺服器為TomCat8.0.33。 前面幾篇文章我們簡單的分析了一下SpringMVC初始化的過程,接下來的這幾篇文章我們從原始碼的角度分析一下SpringMVC對請求的處理過程。這一篇文章我們來分析請

【spring springmvcspringmvc使用註解宣告控制器與請求對映

# 概述 **註解:** 在Spring中儘管使用XML配置檔案可以實現Bean的裝配工作,但如果應用中Bean的數量較多,會導致XML配置檔案過於臃腫,從而給維護和升級帶來一定的困難。 從JDK 5開始提供了名為Annotation(註解)的功能,Spring正是利用這一特性,Spring逐步完善對Anno

SpringMVC請求流程

響應 bsp logs -1 wid 執行 map resp resolve Spring結構圖 SpringMVC請求流程圖 SpringMVC請求流程圖語述: request--->DispatcherServler(中央調度器/前端控制器)--

springmvc請求處理詳解

控制器 接口 Spring Web MVC 處理的大致過程: 一旦到來,DispatcherSevlet將負責將請求分發。DispatcherServlet可以認為是Spring提供的前端控制器,所有的請求都有經過它來統一分發。 在DispatcherServlet將請求分發給Spring Contr

為什麽要有uboot?帶你全面分析嵌入式linux系統啟動過程中uboot的作用

統一 一次 fail 進入 是我 臺式機 平板 配置 webp 1.為什麽要有uboot 1.1、計算機系統的主要部件 (1)計算機系統就是以CPU為核心來運行的系統。典型的計算機系統有:PC機(臺式機+筆記本)、嵌入式設備(手機、平板電腦、遊戲機)、單片機(家用電器像

springmvc請求處理入口:DispatcherServlet

加載 容器 listener 基本 shm spring框架 作用 控制器 web.xml 閑來無事。看spring官方文檔,整理一些知識點,為避免遺忘,來此記錄。

全面分析RHCE7(紅帽認證工程師)考試題目之 ----WEB 服務器 篇

from 基本概念 文件名 不同 forbidden log 配置dns protoc 標簽 HTTP服務基礎獨立Web服務 Web通信基本概念 基於B/S 服務端提供網頁 瀏覽器下載並顯示網頁 Hyper Text Markup Language (HTML)

Flask 請求源碼分析

which sim hid failure {} 調用 賦值 cau httponly 執行app.run()方法: def run(self, host=None, port=None, debug=None, **options): from we

linux input輸入子系統分析《四》:input子系統整體流程全面分析

總線 返回值 分代 並不是 事件 等等 lag pri 位置 1 input輸入子系統整體流程 本節分析input子系統在內核中的實現,包括輸入子系統(Input Core),事件處理層(Event Handler)和設備驅動層。由於上節代碼講解了設備驅動層的寫法