SpringMVC框架詳細教程(八)_@RequestMapping使用詳解

来源:https://www.cnblogs.com/lemon-coke-pudding/archive/2020/04/17/12722934.html
-Advertisement-
Play Games

這一節雖然簡單,但是很繁瑣,可以先瞭解 @RequestMapping 的使用,不是很明白也沒有關係,先繼續往下學習,等你回頭再看一遍的時候,你會發現 @RequestMapping 竟然是如此的簡單! @RequestMapping @RequestMapping可以在控制器 類 上或者控制器 方 ...


這一節雖然簡單,但是很繁瑣,可以先瞭解 @RequestMapping 的使用,不是很明白也沒有關係,先繼續往下學習,等你回頭再看一遍的時候,你會發現 @RequestMapping 竟然是如此的簡單!

@RequestMapping

@RequestMapping可以在控制器上或者控制器方法上使用。

在類的級別上的註解會將一個特定請求或者請求模式映射到一個控制器之上。之後你還可以另外添加方法級別的註解來進一步指定到處理方法的映射關係。

基礎用法:

下麵的 @RequestMapping("/index") 等同於 @RequestMapping(value = "/index")

package com.pudding.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/index")
public class HelloWorldController {

	@RequestMapping(value = "/hello", method = RequestMethod.GET)
	public String hello() {

		return "/WEB-INF/views/success.jsp";
	}

	@RequestMapping(value = "/world", method = RequestMethod.POST)
	public String world() {

		return "/WEB-INF/views/success.jsp";
	}

}

method 參數支持:GET, PUT, POST, DELETE 以及 PATCH。使用 method 可以限制接受的請求類型。

hello() 方法將只接受請求方式為 GET 方式,請求地址為:/index/hello 的請求。

world() 方法將只接受請求方式為 POST 方式,請求地址為:/index/world 的請求。

映射多個地址:

@RequestMapping 還可以將多個請求映射到一個方法上,只需要給 value 來指定一個包含多個路徑的列表。

package com.pudding.controller;

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

@Controller
@RequestMapping("/index")
public class HelloWorldController {

	@RequestMapping(value = {"/hello", "/world", "/helloworld"})
	public String hello() {

		return "/WEB-INF/views/success.jsp";
	}

}

URI模板:

URI模板可以為快速訪問 @RequestMapping 中指定的URL的一個特定的部分提供很大的便利。

使用 @PathVariable 可以獲取到 {name} 的值,併在控制台進行輸出。比如請求地址為:http://localhost:8080/SpringMVC/hello/jack 那麼控制臺上將會把 jack 進行輸出。

package com.pudding.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloWorldController {

	@RequestMapping("/hello/{name}")
	public String hello(@PathVariable String name) {
		System.out.println(name);

		return "/WEB-INF/views/success.jsp";
	}

}

如果路徑中的URI變數和方法中的參數名不一樣的話,那麼需要在 @PathVariable 中顯示的綁定參數。

package com.pudding.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloWorldController {

	@RequestMapping("/hello/{name}")
	public String hello(@PathVariable("name") String username) {
		System.out.println(username);

		return "/WEB-INF/views/success.jsp";
	}

}

一個方法可以擁有任意數量的 @PathVariable 註解:

package com.pudding.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloWorldController {

	@RequestMapping("/hello/{name}/age/{age}")
	public String hello(@PathVariable String name, @PathVariable int age) {
		System.out.println("name:" + name + ",age:" + age);

		return "/WEB-INF/views/success.jsp";
	}

}

@PathVariable 可以被應用於所有 簡單類型 的參數上,比如 int、long、Date 等類型。Spring會自動地幫你把參數轉化成合適的類型,如果轉換失敗,就拋出一個 TypeMismatchException。如果你需要處理其他數據類型的轉換,也可以註冊自己的類。

帶正則表達式的URI模板:

你可以使用正則表達式來準確的描述可以接受的請求路徑:

package com.pudding.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloWorldController {

	@RequestMapping("/hello/{name:[a-z]+}/age/{age}")
	public String hello(@PathVariable String name, @PathVariable int age) {
		System.out.println("name:" + name + ",age:" + age);

		return "/WEB-INF/views/success.jsp";
	}

}

Ant風格的路徑模式:

除了URI模板外,@RequestMapping註解還支持Ant風格的路徑模式(如/hello/*.do等)。不僅如此,還可以把URI模板變數和Ant風格的glob組合起來使用(比如/hello/*/user/{userId}這樣的用法等)。其中*則表示任意字元串。但是遇到 / 那麼就會認為是下一部分的URI,所以 * 中不能有 / 。

package com.pudding.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloWorldController {

    // 匹配的地址:http://localhost:8080/SpringMVC/hello/jack/user/18
	@RequestMapping("/hello/*/user/{userId}")
	public String hello(@PathVariable String userId) {
		System.out.println(userId);

		return "/WEB-INF/views/success.jsp";
	}

}

那麼想要匹配帶 / 的路徑那該怎麼辦?可以使用 ** 來進行匹配。例如 /hello/**/user/{userId} 則會匹配 /hello/ 和 /user/{userId} 之間的部分。

package com.pudding.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloWorldController {

    // 匹配的地址:http://localhost:8080/SpringMVC/hello/jack/tom/cat/user/18
	@RequestMapping("/hello/**/user/{userId}")
	public String hello(@PathVariable String userId) {
		System.out.println(userId);

		return "/WEB-INF/views/success.jsp";
	}

}

路徑樣式的匹配(Path Pattern Comparison):

當一個URL同時匹配多個模板(pattern)時,我們將需要一個演算法來決定其中最匹配的一個。

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/**更準確

更多的細節請參考這兩個類:AntPatternComparatorAntPathMatcher。值得一提的是,PathMatcher類是可以配置的。

尾碼模式匹配:

Spring MVC預設採用 ".*" 的尾碼模式匹配來進行路徑匹配,因此,一個映射到/person路徑的控制器也會隱式地被映射到 /person.*。這使得通過URL來請求同一資源文件的不同格式變得更簡單(比如 /person.pdf/person.xml)。

關閉尾碼模式匹配:

java:

@Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {

        @Override
        public void configurePathMatch(PathMatchConfigurer configurer) {
            configurer
                // 關閉尾碼模式匹配
                .setUseSuffixPatternMatch(false)
                .setUseTrailingSlashMatch(false)
                .setUseRegisteredSuffixPatternMatch(true)
                .setPathMatcher(antPathMatcher())
                .setUrlPathHelper(urlPathHelper());
        }

        @Bean
        public UrlPathHelper urlPathHelper() {
            //...
        }

        @Bean
        public PathMatcher antPathMatcher() {
            //...
        }

    }

xml:

 <mvc:annotation-driven>
        <mvc:path-matching
			<!-- 關閉尾碼模式匹配 -->                           
            suffix-pattern="false"
            trailing-slash="false"
            registered-suffixes-only="true"
            path-helper="pathHelper"
            path-matcher="pathMatcher"/>
    </mvc:annotation-driven>

    <bean id="pathHelper" class="org.example.app.MyPathHelper"/>
    <bean id="pathMatcher" class="org.example.app.MyPathMatcher"/>

矩陣變數:

矩陣變數可以在任何路徑段落中出現,每對矩陣變數之間使用一個分號 “;” 隔開。比如這樣的URI:"/cars;color=red;year=2012"。多個值可以用逗號隔開 "color=red,green,blue",或者重覆變數名多次 "color=red;color=green;color=blue"

如果一個URL有可能需要包含矩陣變數,那麼在請求路徑的映射配置上就需要使用URI模板來體現這一點。這樣才能確保請求可以被正確地映射,而不管矩陣變數在URI中是否出現、出現的次序是怎樣等。在方法參數中使用 @MatrixVariable 來獲得矩陣變數中的值。

使用矩陣變數之前,需要在 springmvc 配置文件中開啟自動解析矩陣變數:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:annotation-driven enable-matrix-variables="true"/>

</beans>

下麵的代碼使用了矩陣變數:

使用 /pets/42;q=11;r=22 路徑來請求之後,控制臺上會輸出 petId:42,q:11

package com.pudding.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.MatrixVariable;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MatrixController {

	@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET)
	public void findPet(@PathVariable String petId, @MatrixVariable(name = "q", pathVar = "petId") int q) {
		System.out.println("petId:" + petId + "," + "q:" + q);
	}

}

由於任意路徑段落中都可以含有矩陣變數,在某些場景下,你需要用更精確的信息來指定一個矩陣變數的位置:

使用 /owners/42;q=11/pets/21;q=22 路徑來請求之後,控制臺上會輸出 q1:11,q2:22

package com.pudding.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.MatrixVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MatrixController {

	@RequestMapping(path = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
	public void findPet(@MatrixVariable(name = "q", pathVar = "ownerId") int q1,
			@MatrixVariable(name = "q", pathVar = "petId") int q2) {
		System.out.println("q1:" + q1 + "," + "q2:" + q2);
	}

}

你也可以聲明一個矩陣變數不是必須出現的,並給它賦一個預設值:

使用 /pets/42 路徑來請求之後,控制臺上會輸出 q:1

package com.pudding.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.MatrixVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MatrixController {

	@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET)
	public void findPet(@MatrixVariable(required = false, defaultValue = "1") int q) {
		System.out.println("q:" + q);
	}

}

可以觀察到,我們請求的路徑中並沒有 q 這個參數,配置了 required = false, defaultValue = "1" 之後,如果路徑中沒有指定的矩陣變數,那麼 SpringMVC 會自動給矩陣變數設置預設值

也可以通過一個Map來存儲所有的矩陣變數:

使用 /owners/42;q=11;r=12/pets/21;q=22;s=23 路徑來請求之後,控制臺上會輸出 matrixVars:{q=11, r=12, s=23} 和 petMatrixVars:{q=22, s=23}

package com.pudding.controller;

import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.MatrixVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MatrixController {

	@RequestMapping(path = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
	public void findPet(@MatrixVariable Map<String, String> matrixVars,
			@MatrixVariable(pathVar = "petId") Map<String, String> petMatrixVars) {
		System.out.println("matrixVars:" + matrixVars);
		System.out.println("petMatrixVars:" + petMatrixVars);
	}

}

consumes:

你可以指定一組可消費的媒體類型,縮小映射的範圍。這樣只有當請求頭中 Content-Type 的值與指定可消費的媒體類型中有相同的時候,請求才會被匹配。比如下麵這個例子:

@Controller
@RequestMapping(path = "/pets", method = RequestMethod.POST, consumes="application/json")
public void addPet(@RequestBody Pet pet, Model model) {
    // 方法實現省略
}

指定可消費媒體類型的表達式中還可以使用否定,比如,可以使用 !text/plain 來匹配所有請求頭 Content-Type 中不含 text/plain 的請求。同時,在MediaType類中還定義了一些常量,比如APPLICATION_JSON_VALUEAPPLICATION_JSON_UTF8_VALUE等,推薦更多地使用它們。

produces:

你可以指定一組可生產的媒體類型,縮小映射的範圍。這樣只有當請求頭中 Accept 的值與指定可生產的媒體類型中有相同的時候,請求才會被匹配。而且,使用 produces 條件可以確保用於生成響應(response)的內容與指定的可生產的媒體類型是相同的。舉個例子:

@RestController
@RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Pet getPet(@PathVariable String petId, Model model) {
    // 方法實現省略
}

consumes 條件類似,可生產的媒體類型表達式也可以使用否定。比如,可以使用 !text/plain 來匹配所有請求頭 Accept 中不含 text/plain 的請求。同時,在MediaType類中還定義了一些常量,比如APPLICATION_JSON_VALUEAPPLICATION_JSON_UTF8_VALUE等,推薦更多地使用它們。

請求參數與請求頭的值:

你可以篩選請求參數的條件來縮小請求匹配範圍,比如"myParam""!myParam""myParam=myValue"等。前兩個條件用於篩選存在/不存在某些請求參數的請求,第三個條件篩選具有特定參數值的請求。下麵有個例子,展示瞭如何使用請求參數值的篩選條件:

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {

    @RequestMapping(path = "/pets/{petId}", method = RequestMethod.GET, params="myParam=myValue")
    public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
        // 實際實現省略
    }

}

同樣,你可以用相同的條件來篩選請求頭的出現與否,或者篩選出一個具有特定值的請求頭:

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {

    @RequestMapping(path = "/pets", method = RequestMethod.GET, headers="myHeader=myValue")
    public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
        // 方法體實現省略
    }

}

註:以上資料部分參考自W3Cschool翻譯的SpringMVC官方文檔


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ES內置的6種分詞器 standard analyzer 標準分詞器,未設置分詞器時預設使用此分詞器。在空格、符號處切,中文部分切割為一個一個的漢字。 切的意思是不要了。多個連續的空格算一個空格,符號指的是!、?、@、。等 "h!ello wo2rld a b我是a中國人d" => h ello w ...
  • 在C語言中迴圈可分為3中,while迴圈、do - while迴圈、for 迴圈。 一、while迴圈   while即:首先檢查啟動迴圈的條件是否滿足,當條件滿足時,不斷地重覆迴圈體內的語句,直到不滿足條件就退出。   while迴圈基本形式: ...
  • 有個很奇怪的現象,我自認為寫得好的文章閱讀量只有一百多,隨手寫的卻有一千多——要麼是胡搞,要麼是比較淺顯。縱觀博客園裡眾多閱讀過萬的文章,若非絕世之作,則必為介紹入門級知識的短文。為了讓我的十八線博客上升到十七線,我打算寫幾篇短文。當然,短不等於隨便,不等於不負責任。客觀的,要有確鑿的依據,代碼必須 ...
  • 問題背景: 在做Struts2學習的頁面訪問時,配置瞭如下的兩個<action>返回結果視圖: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD St ...
  • 程式每次讀入一個正3位數,然後輸出按位逆序的數字。註意:當輸入的數字含有結尾的0時,輸出不應帶有前導的0。比如輸入700,輸出應該是7。輸入格式:每個測試是一個3位的正整數。輸出格式:輸出按位逆序的數。代碼如下:#!/usr/bin/python# -*- coding: utf-8 -*-n = ... ...
  • 配置視圖解析器 在前面的章節中,我們已經把 中使用到的註解已經全部講解過了。但是 中的代碼存在了一個問題,那就是返回值跳轉的頁面地址太繁瑣了。假設我們所有的頁面都放在 下,那我們是不是每次都得覆寫很多遍 ,這是作為一個優秀的程式猿不可以忍耐的!我們想要只要 return 我們需要改變的值就可以了,那 ...
  • 使用 @RequestParam 將請求參數綁定至方法參數 你可以使用 註解將請求參數綁定到你控制器的方法參數上。 下麵這段代碼展示了它的用法: 若參數使用了該註解,則該參數預設是必須提供的,但你也可以把該參數標註為非必須的:只需要將 註解的 屬性設置為 即可: 註意:這裡使用的 是將請求的參數設置 ...
  • 項目簡介 項目來源於: "https://gitee.com/darlingzhangsh/graduation_project" 本系統是基於 Thymeleaf+SpringBoot+Mybatis 。是非常標準的SSM三大框架( SpringBoot就是一個大框架,裡面包含了許多的東西,其中S ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...