1. 程式人生 > >一篇文章搞定springMVC中的請求對映

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

實驗的專案是採用預設配置的spring boot專案,使用的工具為IDEA和POSTMAN。

希望這些案例能夠幫助你理解和思考。

talk is cheap,show me the code!

1、從最簡單的hello world開始

這裡寫圖片描述

@Controller
public class HelloController {
    @RequestMapping("/helloWorld")
    @ResponseBody
    public String helloWorld(){
        return "hello world";
    }
}

上例也許就是一個最簡單的springmvc程式碼了,當請求的uri為”/helloWorld”時,將會得到字串”hello world”,下圖是用postman模擬請求的結果。

這裡寫圖片描述

簡單介紹幾個基礎的註解,因為後面的實驗中可能會用到:

  • @Controller 宣告HelloController類為springMVC中的一個controller,優點是不需要繼承任何類或者實現任何的介面。在配置了註解掃描後,頭上有@Controller註解的類將會被spring容器自動的載入。
    spring 註解掃描的配置方式(java config)如下:
@Configuration
@ComponentScan("org.example.web")
public class WebConfig {

    // ...
}
  • @RequestMapping: 用於提供的請求對映資訊。@RequestMapping註解即可以用在class級別中也可以用在方法級別中。
  • @ResponseBody: 表示該方法的返回結果直接寫入 HTTP response body 中。
  • @GetMapping、@PostMapping、@PutMapping等:他們相當於RequestMapping(value = “/xxx” , method = RequestMethod.GET)或 RequestMapping(value = “/xxx” , method = RequestMethod.POST),即限定請求方法的簡寫。
  • @RestController :官方文件的描述如下,即@RestController 註解相當於@Controller和@ResponseBody兩個註解的組合。
    @RestController is a composed annotation that is itself annotated with @Controller and @ResponseBody

2、通過指定HTTP請求方法來限定請求

URI為”/testShortcut”的介面將請求的方法限定為GET請求,也就以為著請求地址和請求方法都必須正確才會返回字串”success”。

程式碼如下:

這裡寫圖片描述

@Controller
public class MyRequestMappingDemo {

    @RequestMapping(value = "/testShortcut",method =  RequestMethod.GET)
    @ResponseBody
    public String testShortcut(){
        return "success";
    }

}

使用postman請求介面”/testShortcut”如下,可以看到,使用的HTTP METHOD為GET請求,並且成功返回了字串”success”。

這裡寫圖片描述

下面使用HTTP METHOD為POST請求同樣的介面

這裡寫圖片描述
可以看到,同樣的介面只是請求的方式不同得到的結果也就不相同。達到了通過請求方式來限定請求的目的。

再此順便試一下@GetMapping、@PostMapping、@PutMapping等註解好不好用。

這裡寫圖片描述

@Controller
public class GETMappingDemo {
    @GetMapping(value= "/testGetMapping")
    @ResponseBody
    public String testGetMapping(){
        return "testGetMapping";
    }
}

這裡寫圖片描述

這裡寫圖片描述

由上面兩張圖可以看到,@GetMapping、@PostMapping等註解對於通過請求方式來限定也是賊好用的。

3、url pattern

springMVC也是支援在請求的url中使用萬用字元的,具體規則如下:
  • ?萬用字元表示匹配一個字元(matches one character)。
    • 萬用字元表示在一個路徑分段中匹配一個或者多個字元(matches zero or more characters within a path segment)。
  • ** 統配符表示匹配零個或者多個路徑分段(match zero or more path segments)。

相關程式碼和實驗如下:

這裡寫圖片描述

@RestController
public class URIPatternsDemo {

    @RequestMapping("/testURIPatterns/?")
    public String testURIPatterns(){
        return "?萬用字元表示匹配一個字元!";
    }

    @RequestMapping("/testURIPatterns1/*")
    public String testURIPatterns1(){
        return "*萬用字元表示匹配零個或者多個字元,但必須是在一個路徑分段中!";
    }

    @RequestMapping("/testURIPatterns2/**")
    public String testURIPatterns2(){
        return "**萬用字元表示匹配零個或者多個路徑分段!";
    }

}

上述程式碼中,URIPatternsDemo類裡定義了三個方法,分別用於測試三種萬用字元的使用。使用postman測試如下:

1、測試?萬用字元,路徑中輸入一個字元a,資訊成功返回。
這裡寫圖片描述
2、測試?萬用字元,路徑中輸入一個字元b,資訊成功返回。
這裡寫圖片描述
3、測試?萬用字元,路徑中輸入多個字元,報錯。
這裡寫圖片描述
結論,?萬用字元只能匹配一個隨機的字元
4、測試*萬用字元,路徑中輸入多個字元,正確返回。
這裡寫圖片描述
5、測試*萬用字元,路徑中輸入零個字元,正確返回。
這裡寫圖片描述
6、測試*萬用字元,在多個路徑分段中輸入多個字元,報錯。
這裡寫圖片描述
結論,* 萬用字元表示在一個路徑分段中匹配一個或者多個字元
7、測試**萬用字元,在一個路徑分段中輸入多個字元,正確返回。
這裡寫圖片描述
8、測試**萬用字元,在多個路徑分段中輸入多個字元,正確返回。
這裡寫圖片描述
8、測試**萬用字元,零個路徑分段,正確返回。
這裡寫圖片描述
結論,** 統配符表示匹配零個或者多個路徑分段。

4、URI Template Patterns

URI templates can be used for convenient access to selected parts of a URL in a @RequestMapping method.

URI模板可以很方便的用於獲取@RequestMapping方法裡的URL的一部分。(本屌的渣渣翻譯)
意思就是說可以使用URI Template獲取URL路徑中的變數。在sprngMVC中使用的是@PathVariable註解。talk is cheap,上程式碼。
這裡寫圖片描述

@Controller
public class TestUrlPatterns {
    //演示一個URL路徑變數的情況
    @RequestMapping("/UrlPatternDemo/{pathVar}")
    @ResponseBody
    public String UrlPatternDemo(@PathVariable String pathVar){
        return pathVar;
    }

    //演示兩個路徑變數的情況
    @RequestMapping("/multiUrlPatternDemo/{pathVar1}/{pathVar2}")
    @ResponseBody
    public String multiUrlPatternDemo(@PathVariable String pathVar1 , @PathVariable String pathVar2){
        return "this is first path variable:" + pathVar1+", this is second path variable:" + pathVar2;
    }

    //演示路徑變數支援多種基本資料型別,而不是隻有String一種
    @RequestMapping("/multiUrlPatternDemo2/{pathVar1}/{pathVar2}")
    @ResponseBody
    public String multiUrlPatternDemo2(@PathVariable Integer pathVar1 , @PathVariable Integer pathVar2){
        return "第一個引數是:" + pathVar1+",第二個引數是:" + pathVar2 +"。兩個引數的和是:"+ (pathVar1 + pathVar2);
    }
}

下面測試一下這三個方法:
這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

結論:@PathVariable註解可以獲取請求URL中的路徑引數,並且也可以用基本資料型別來接收引數的值。

下面來討論一些特殊情況:
如果一個請求的URL同時匹配了多個萬用字元怎麼辦?
springMVC中有一些規則用於處理這種特殊情況,規則是:

  • 例如,/hotel/{hotel}/*/hotel/{hotel}/**,前者具有一個路徑變數和一個萬用字元,而後者同樣是具有一個路徑變數,但是後者卻有兩個萬用字元。此時,springMVC認為前者更加的明確,所以前者的優先順序會更高一些。
  • /foo/bar*/foo/* springMVC認為前者的指向更加明確,所以前者的優先順序更高。
  • /hotels/{hotel}/hotels/*springMVC認為前者的指向更加明確,原因是前者沒有用到萬用字元。
  • /** 在springMVC中被認為是優先順序最低的。

    具體的規則在AntPathMatcher類的AntPatternComparator()方法中有完整的體現。

URI Template另外還有兩種用法,即與正則表示式一起使用和與Placeholders一起使用。
第一種:與正則一起使用
這裡寫圖片描述

@RestController
public class RegexExpressionDemo {

    @RequestMapping("/testRegexExpressionPattern/{name:[a-z-]+}")
    public String testRegexExpressionPattern(@PathVariable String name){
        return "正則表示式匹配的變數為:" + name;
    }

}

這裡寫圖片描述

第二種,與Placeholders一起使用
這裡寫圖片描述

@Controller
@RequestMapping(value="${demo.path.variable}")
public class PropertiesPlaceholderDemo {

    @RequestMapping("/testPropertiesPlaceholder")
    @ResponseBody
    public String testPropertiesPlaceholder(){
        return "asd";
    }
}

如上面程式碼所示,@RequestMapping註解中的引數來自properties配置檔案,當路徑正確匹配時,將會返回字串”asd”。所以我們在properties檔案中建立一個key為demo.path.variable的屬性。在這裡就直接寫在application.properties中,如下圖所示。
這裡寫圖片描述

所以我們訪問的路徑應該為”/haha/testPropertiesPlaceholder”,下面為測試:
這裡寫圖片描述
成功返回字串“asd”。

5、Matrix Variables

Matrix Variables意味矩陣變數,說白了就是名值對。解釋名詞是很蛋疼的事,直接上程式碼和實驗結果,對著程式碼和結果進行解釋。

要使用矩陣變數,首先需要將RequestMappingHandlerMapping類中的removeSemicolonContent屬性設為false,預設情況下為true。設定的方法也很簡單,下面是通過java config的方式配置該屬性。
這裡寫圖片描述

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setRemoveSemicolonContent(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}

實驗程式碼如下:

這裡寫圖片描述
完整程式碼如下,其中有個沒見過的註解@MatrixVariable,下面通過實驗結果來說說這個註解到底是幹什麼。

@RestController
public class MatrixVariablesDemo {

    @RequestMapping("/testMatrixVariables/{pathVar1}")
    public String testMatrixVariables(@PathVariable String pathVar1,@MatrixVariable int matrixVariable1,@MatrixVariable int matrixVariable2){
        return "pathVar1的值為:" + pathVar1 + "; matrixVariable1的值為:" + matrixVariable1 + "; matrixVariable2的值為:" + matrixVariable2;
    }

    @RequestMapping("/testMatrixVariables2/{pathVar1}/{pathVar2}")
    public String testMatrixVariables2(@MatrixVariable(name = "matrixVariable",pathVar = "pathVar1") int matrixVariable1,@MatrixVariable(name = "matrixVariable",pathVar = "pathVar2") int matrixVariable2){
        return " pathVar1變數中的matrixVariable的值為:" + matrixVariable1 + "; pathVar2變數中的matrixVariable的值為:" + matrixVariable2;
    }

    @RequestMapping("/testMatrixVariables3/{pathVar}")
    public String testMatrixVariables3(@PathVariable String pathVar,@MatrixVariable(name = "matrixVariable",pathVar = "pathVar",required = false,defaultValue = "222233" ) String matrixVariable){
        return "pathVar變數的值是:"+pathVar+",matrixVariable變數什麼值也沒傳,預設值是:" + matrixVariable;
    }

    @RequestMapping("/testMatrixVariables4/{pathVar1}/{pathVar2}")
    public String testMatrixVariables4(@MatrixVariable MultiValueMap<String,String> matrixMap){
        return matrixMap.toString();
    }

    @RequestMapping("/testMatrixVariables5/{pathVar1}/{pathVar2}")
    public String testMatrixVariables5(@MatrixVariable(pathVar = "pathVar1") MultiValueMap<String,String> matrixMap){
        return matrixMap.toString();
    }
}

1、測試第一個介面“/testMatrixVariables/{pathVar1}”,實驗中請求的URL為http://localhost:8080//testMatrixVariables/20;matrixVariable1=1;matrixVariable2=2
結果如下:這裡寫圖片描述
先觀察URL,在{pathVar1}中有三個用分號分隔的部分,分別為20、matrixVariable1=1和matrixVariable2=2。回想Matrix Variable矩陣變數的定義,說它是明值對。這是可以大概明白所謂的矩陣變數就是寫在路徑變數{pathVar1}中的用分號“;”隔開的name=value對,即本例中的matrixVariable1=1和matrixVariable2=2。結合程式碼和實驗結果可知,@MatrixVariable註解的作用就是用來獲取路徑變數中的矩陣的變數的,並且可以用基本資料型別來接收。

2、測試第二個介面,URLhttp://localhost:8080//testMatrixVariables2/matrixVariable=1/matrixVariable=2,結合程式碼可知,我們可以用@MatrixVariable註解,並通過指定pathVar屬性來獲取兩個不同路徑變數中同名的矩陣變數。
這裡寫圖片描述
3、第三個介面用於測試@MatrixVariable註解的預設值,URLhttp://localhost:8080//testMatrixVariables3/1,結果為:
這裡寫圖片描述
4、第四個和第五個介面都是用於測試@MatrixVariable註解中用Map接收引數,URL分別為http://localhost:8080/testMatrixVariables4/a=a;b=b;c=c/a=aa;b=bb

http://localhost:8080/testMatrixVariables5/a=a;b=b;c=c/a=aa;b=bb
結果分別如下:

獲取所有路徑段中的矩陣變數,並用Map接收
這裡寫圖片描述

指定獲取某個路徑分段中的矩陣變數,並用Map接收
這裡寫圖片描述

6、通過限定MediaTypes、Request Parameters和Header Values來限制請求

通過Consumes,Produces註解來限定MediaTypes

consumes:指定處理請求的提交內容型別(Content-Type)。
produces:指定返回的內容型別,僅當request請求頭中的(Accept)型別中包含該指定型別才返回。

這裡寫圖片描述

@Controller
@RequestMapping(value="/test")
public class ConsumableMediaTypesDemo {

    @RequestMapping(value="/testConsumableMediaTypes",consumes = "application/json")
    public String testConsumableMediaTypes(){
        return "請求成功!";
    }

    @RequestMapping(value="/testConsumableMediaTypes1",consumes = MediaType.APPLICATION_JSON_VALUE)
    public String testConsumableMediaTypes1(){
        return "請求成功!                 MediaType.APPLICATION_JSON_VALUE";
    }

    @RequestMapping(value="/testConsumableMediaTypes2",consumes = MediaType.APPLICATION_XML_VALUE)
    @ResponseBody
    public String testConsumableMediaTypes2(){
        return "請求成功!                 MediaType.APPLICATION_XML_VALUE";
    }

}

1、第一個介面是用consumes屬性來限定MediaTypes的型別,並使用了字面量的形式限定型別,後面兩個介面使用了MediaType類中定義的常量。實驗的結果如下:
介面1:
這裡寫圖片描述

介面2:
這裡寫圖片描述

介面3:
這裡寫圖片描述

produces、params和headers的使用方式與@Consumes相同
程式碼如下
這裡寫圖片描述

@Controller
public class ProducibleMediaTypesDemo {

    @RequestMapping(value = "/testProducibleMediaTypes",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public String testProducibleMediaTypes(){
        return "請求成功";
    }
}

相關推薦

文章springMVC請求對映

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

文章面試的連結串列題目(java實現)

連結串列的資料結構 class ListNode { ListNode next; int val; ListNode(int x){ val = x; next = null;

文章SpringMVC參數綁

進行 pwd dad 技術 默認 int acra servlet key SpringMVC參數綁定,簡單來說就是將客戶端請求的key/value數據綁定到controller方法的形參上,然後就可以在controller中使用該參數了 下面通過5個常用的註解演

文章面試的二叉樹題目(java實現)

結構 cer dea mat lastcomm ++ mir let balanced 最近總結了一些數據結構和算法相關的題目,這是第一篇文章,關於二叉樹的。 先上二叉樹的數據結構: class TreeNode{ int val; //左孩子 Tr

文章——JDK8新增的StampedLock

一、StampedLock類簡介 StampedLock類,在JDK1.8時引入,是對讀寫鎖ReentrantReadWrit

文章Markdown

markdown一篇文章搞定Markdown一篇文章搞定Markdown

文章前端面試

ron miss 就是 節點數 網頁 那是 png html 性能優化 本文旨在用最通俗的語言講述最枯燥的基本知識 面試過前端的老鐵都知道,對於前端,面試官喜歡一開始先問些HTML5新增元素啊特性啊,或者是js閉包啊原型啊,或者是css垂直水平居中怎麽實現啊之類的基礎問題

文章你的spring定時器

Cron表示式是一個字串,字串以5或6個空格隔開,分開工6或7個域,每一個域代表一個含義,Cron有如下兩種語法 格式: Seconds Minutes Hours DayofMonth Month DayofWeek Year 或 Seconds Minutes Hours DayofMo

面試專欄|文章ArrayList和LinkedList所有面試問題

在面試中經常碰到:ArrayList和LinkedList的特點和區別? 個人認為這個問題的回答應該分成這幾部分: 介紹ArrayList底層實現 介紹LinkedList底層實現 兩者個適用於哪些場合 本文也是按照上面這幾部分組織的。 ArrayList的原始碼解析

文章C語言所有的基本語法.

C 作為一門工程實用性極強的語言,提供了對作業系統和記憶體的精準控制,高效能的執行時環境,原始碼級的跨平臺編譯等優點,才是我們必須學習和使用 C 的理由。 C語言標記/令牌 C語言程式包括各種令牌和令牌可以是一個關鍵字,識別符號,常量,字串文字或符號。 例如,下面的C語句包括五個

文章Maven安裝到建立maven版Spring MVC專案及配置

配置maven 本地安裝 新建變數名為MAVEN_HOME,值為maven安裝目錄的系統變數 在系統變數名為Path的值中新增“%MAVEN_HOME%\bin;” cmd命令列輸入mvn -v 檢視是否安裝成功 修改maven配置檔案 apac

文章2017最新標題優化方法

很多人都說小2哥你為什麼一直都在寫直通車的文章?為什麼不寫寫自然搜尋方面的內容?你不知道我們新手更需要的就是這些免費流量的內容嗎? 我從13年開始寫文章,13年和14年我是寫自然搜尋寫的最多的,但是從15年開始的時候,我基本上寫的文章都是圍繞直通車。 其實這也是和我的

資料庫的原理,文章

https://blog.csdn.net/zhangcanyan/article/details/51439012 一提到關係型資料庫,我禁不住想:有些東西被忽視了。關係型資料庫無處不在,而且種類繁多,從小巧實用的 SQLite 到強大的 Teradata 。但很少有文章講解資料庫是如何工作的。你可以自己

文章矩陣相關概念及意義--通俗解釋彙總

一篇文章理解矩陣在講什麼。 最近在學習矩陣相關知識,但是其抽象的解釋讓人摸不著頭腦,通過瀏覽一些部落格的內容和自己的理解,本文通過通俗的語言將矩陣的內涵做了總結。其中除了書本和個人觀點,部分引用部落格:。本文主要幫助大家理解矩陣,但不一定都是正確的,但願能起

資料庫的原理,文章(三)

合併聯接 合併聯接是唯一產生排序的聯接演算法。 注:這個簡化的合併聯接不區分內表或外表;兩個表扮演同樣的角色。但是真實的實現方式是不同的,比如當處理重複值時。 1.(可選)排序聯接運算:兩個輸入源都按照聯接關鍵字排序。 2.合併聯接運算:排序後的輸入源合併到一起。

Git | 文章Git、GitHub的理解和使用(學習筆記)

Git learning note 本筆記整理自廖雪峰老師的Git教程,加上了自己的實踐結果和一些理解,旨在使科研工作者(基本上是獨立開發的那種)看完就能理解和使用Git。廖老師的教程生動活潑,條理清晰,推薦閱讀。還可以贊助哦。 目錄 Git 簡

Python正則表達式很難?文章他,不是我吹!

編譯 返回 特殊字符 但是 參數 查找字符串 cas 行處理 產生 1. 正則表達式語法 1.1 字符與字符類 1 特殊字符:.^$?+*{}| 以上特殊字符要想使用字面值,必須使用進行轉義 2 字符類 1. 包含在[]中的一個或者多個字符被稱為字符類,字符類在匹

文章Python多程序(全)

1.Python多程序模組 Python中的多程序是通過multiprocessing包來實現的,和多執行緒的threading.Thread差不多,它可以利用multiprocessing.Process物件來建立一個程序物件。這個程序物件的方法和執行緒物件的方法差不多也有start(), run(), j

文章 Nginx 反向代理與負載均衡

## 代理      要想弄明白反向代理,首先要知道啥是正向代理,要搞懂正向代理只需要知道啥是代理即可。代理其實就是一箇中介,在不同事物或同一事物內部起到居間聯絡作用的環節。比如買票黃牛,房屋中介等等。   在網際網路中代理更多指的是代理伺服器,代理伺服器位於客戶端和伺服器之間,它充當兩者之間的中介。這

文章懂DataSet、DataFrame、RDD-《每日五分鐘大數據》

implicit 操作數 frame 大數據 函數 for 臨時 變量 ade 1. 三者共性: 1、RDD、DataFrame、Dataset全都是spark平臺下的分布式彈性數據集,為處理超大型數據提供便利 2、三者都有惰性機制,執行trainform操作時不會立即執