@RequestMapping 是 Spring Web 應用程序中最常被用到的註解之一。這個註解會將 HTTP 請求映射到 MVC 和 REST 控制器的處理方法上。html
下面咱們看看,@RequestMapping 註解在被用來進行 Spring MVC 控制器方法的映射能夠如何發揮其多才多藝的功能的。 正則表達式
Request Mapping 基礎用法 spring
在 Spring MVC 應用程序中,RequestDispatcher (在 Front Controller 之下) 這個 servlet 負責將進入的 HTTP 請求路由到控制器的處理方法。 app
在對 Spring MVC 進行的配置的時候, 你須要指定請求與處理方法之間的映射關係。post
要配置 Web 請求的映射,就須要你用上 @RequestMapping 註解。fetch
@RequestMapping 註解能夠在控制器類的級別和/或其中的方法的級別上使用。 ui
在類的級別上的註解會將一個特定請求或者請求模式映射到一個控制器之上。以後你還能夠另外添加方法級別的註解來進一步指定處處理方法的映射關係。spa
下面是一個同時在類和方法上應用了 @RequestMapping 註解的示例:code
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 @RequestMapping("/") 5 String get() { 6 //mapped to hostname:port/home/ 7 return "Hello from get"; 8 } 9 @RequestMapping("/index") 10 String index() { 11 //mapped to hostname:port/home/index/ 12 return "Hello from index"; 13 } 14 }
如上述代碼所示,到 /home 的請求會由 get() 方法來處理,而到 /home/index 的請求會由 index() 來處理。 htm
@RequestMapping 來處理多個 URI
你能夠將多個請求映射到一個方法上去,只須要添加一個帶有請求路徑值列表的 @RequestMapping 註解就好了。
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 5 @RequestMapping(value = { 6 "", 7 "/page", 8 "page*", 9 "view/*,**/msg" 10 }) 11 String indexMultipleMapping() { 12 return "Hello from index multiple mapping."; 13 } 14 }
如你在這段代碼中所看到的,@RequestMapping 支持統配符以及ANT風格的路徑。前面這段代碼中,以下的這些 URL 都會由 indexMultipleMapping() 來處理:
帶有 @RequestParam 的 @RequestMapping
@RequestParam 註解配合 @RequestMapping 一塊兒使用,能夠將請求的參數同處理方法的參數綁定在一塊兒。
@RequestParam 註解使用的時候能夠有一個值,也能夠沒有值。這個值指定了須要被映射處處理方法參數的請求參數, 代碼以下所示:
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 5 @RequestMapping(value = "/id") 6 String getIdByValue(@RequestParam("id") String personId) { 7 System.out.println("ID is " + personId); 8 return "Get ID from query string of URL with value element"; 9 } 10 @RequestMapping(value = "/personId") 11 String getId(@RequestParam String personId) { 12 System.out.println("ID is " + personId); 13 return "Get ID from query string of URL without value element"; 14 } 15 }
在代碼的第6行,id 這個請求參數被映射到了 thegetIdByValue() 這個處理方法的參數 personId 上。
若是請求參數和處理方法參數的名稱同樣的話,@RequestParam 註解的 value 這個參數就可省掉了, 如代碼的第11行所示。
@RequestParam 註解的 required 這個參數定義了參數值是不是必需要傳的。
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 @RequestMapping(value = "/name") 5 String getName(@RequestParam(value = "person", required = false) String personName) { 6 return "Required element of request param"; 7 } 8 }
在這段代碼中,由於 required 被指定爲 false,因此 getName() 處理方法對於以下兩個 URL 都會進行處理:
@RequestParam 的 defaultValue 取值就是用來給取值爲空的請求參數提供一個默認值。
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 @RequestMapping(value = "/name") 5 String getName(@RequestParam(value = "person", defaultValue = "John") String personName) { 6 return "Required element of request param"; 7 } 8 }
在這段代碼中,若是 person 這個請求參數爲空,那麼 getName() 處理方法就會接收 John 這個默認值做爲其參數。
用 @RequestMapping 處理 HTTP 的各類方法
Spring MVC 的 @RequestMapping 註解可以處理 HTTP 請求的方法, 好比 GET, PUT, POST, DELETE 以及 PATCH。
全部的請求默認都會是 HTTP GET 類型的。
爲了能降一個請求映射到一個特定的 HTTP 方法,你須要在 @RequestMapping 中使用 method 來聲明 HTTP 請求所使用的方法類型,以下所示:
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 @RequestMapping(method = RequestMethod.GET) 5 String get() { 6 return "Hello from get"; 7 } 8 @RequestMapping(method = RequestMethod.DELETE) 9 String delete() { 10 return "Hello from delete"; 11 } 12 @RequestMapping(method = RequestMethod.POST) 13 String post() { 14 return "Hello from post"; 15 } 16 @RequestMapping(method = RequestMethod.PUT) 17 String put() { 18 return "Hello from put"; 19 } 20 @RequestMapping(method = RequestMethod.PATCH) 21 String patch() { 22 return "Hello from patch"; 23 } 24 }
在上述這段代碼中, @RequestMapping 註解中的 method 元素聲明瞭 HTTP 請求的 HTTP 方法的類型。
全部的處理處理方法會處理從這同一個 URL( /home)進來的請求, 但要看指定的 HTTP 方法是什麼來決定用哪一個方法來處理。
例如,一個 POST 類型的請求 /home 會交給 post() 方法來處理,而一個 DELETE 類型的請求 /home 則會由 delete() 方法來處理。
你會看到 Spring MVC 將使用這樣相同的邏輯來映射其它的方法。
用 @RequestMapping 來處理生產和消費對象
可使用 @RequestMapping 註解的 produces 和 consumes 這兩個元素來縮小請求映射類型的範圍。
爲了能用請求的媒體類型來產生對象, 你要用到 @RequestMapping 的 produces 元素再結合着 @ResponseBody 註解。
你也能夠利用 @RequestMapping 的 comsumes 元素再結合着 @RequestBody 註解用請求的媒體類型來消費對象。
下面這段代碼就用到的 @RequestMapping 的生產和消費對象元素:
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 @RequestMapping(value = "/prod", produces = { 5 "application/JSON" 6 }) 7 @ResponseBody 8 String getProduces() { 9 return "Produces attribute"; 10 } 11 12 @RequestMapping(value = "/cons", consumes = { 13 "application/JSON", 14 "application/XML" 15 }) 16 String getConsumes() { 17 return "Consumes attribute"; 18 } 19 }
在這段代碼中, getProduces() 處理方法會產生一個 JSON 響應, getConsumes() 處理方法能夠同時處理請求中的 JSON 和 XML 內容。
使用 @RequestMapping 來處理消息頭
@RequestMapping 註解提供了一個 header 元素來根據請求中的消息頭內容縮小請求映射的範圍
在能夠指定 header 元素的值,用 myHeader = myValue 這樣的格式:
@RestController @RequestMapping("/home") public class IndexController { @RequestMapping(value = "/head", headers = { "content-type=text/plain" }) String post() { return "Mapping applied along with headers"; } }
在上面這段代碼中, @RequestMapping 註解的 headers 屬性將映射範圍縮小到了 post() 方法。有了這個,post() 方法就只會處理到 /home/head 而且 content-typeheader 被指定爲 text/plain 這個值的請求。
你也能夠像下面這樣指定多個消息頭:
@RestController @RequestMapping("/home") public class IndexController { @RequestMapping(value = "/head", headers = { "content-type=text/plain", "content-type=text/html" }) String post() { return "Mapping applied along with headers"; } }
這樣, post() 方法就能同時接受 text/plain 還有 text/html 的請求了。
使用 @RequestMapping 來處理請求參數
@RequestMapping 直接的 params 元素能夠進一步幫助咱們縮小請求映射的定位範圍。使用 params 元素,你可讓多個處理方法處理到同一個URL 的請求, 而這些請求的參數是不同的。
你能夠用 myParams = myValue 這種格式來定義參數,也可使用通配符來指定特定的參數值在請求中是不受支持的。
@RestController @RequestMapping("/home") public class IndexController { @RequestMapping(value = "/fetch", params = { "personId=10" }) String getParams(@RequestParam("personId") String id) { return "Fetched parameter using params attribute = " + id; } @RequestMapping(value = "/fetch", params = { "personId=20" }) String getParamsDifferent(@RequestParam("personId") String id) { return "Fetched parameter using params attribute = " + id; } }
在這段代碼中,getParams() 和 getParamsDifferent() 兩個方法都能處理相同的一個 URL (/home/fetch) ,可是會根據 params 元素的配置不一樣而決定具體來執行哪個方法。
例如,當 URL 是 /home/fetch?id=10 的時候, getParams() 會執行,由於 id 的值是10,。對於 localhost:8080/home/fetch?personId=20 這個URL, getParamsDifferent() 處理方法會獲得執行,由於 id 值是 20。
使用 @RequestMapping 處理動態 URI
@RequestMapping 註解能夠同 @PathVaraible 註解一塊兒使用,用來處理動態的 URI,URI 的值能夠做爲控制器中處理方法的參數。你也可使用正則表達式來只處理能夠匹配到正則表達式的動態 URI。
@RestController @RequestMapping("/home") public class IndexController { @RequestMapping(value = "/fetch/{id}", method = RequestMethod.GET) String getDynamicUriValue(@PathVariable String id) { System.out.println("ID is " + id); return "Dynamic URI parameter fetched"; } @RequestMapping(value = "/fetch/{id:[a-z]+}/{name}", method = RequestMethod.GET) String getDynamicUriValueRegex(@PathVariable("name") String name) { System.out.println("Name is " + name); return "Dynamic URI parameter fetched using regex"; } }
在這段代碼中,方法 getDynamicUriValue() 會在發起到 localhost:8080/home/fetch/10 的請求時執行。這裏 getDynamicUriValue() 方法 id 參數也會動態地被填充爲 10 這個值。
方法 getDynamicUriValueRegex() 會在發起到 localhost:8080/home/fetch/category/shirt 的請求時執行。不過,若是發起的請求是 /home/fetch/10/shirt 的話,會拋出異常,由於這個URI並不能匹配正則表達式。
@PathVariable 同 @RequestParam的運行方式不一樣。你使用 @PathVariable 是爲了從 URI 裏取到查詢參數值。換言之,你使用 @RequestParam 是爲了從 URI 模板中獲取參數值。
@RequestMapping 默認的處理方法
在控制器類中,你能夠有一個默認的處理方法,它能夠在有一個向默認 URI 發起的請求時被執行。
@RestController @RequestMapping("/home") public class IndexController { @RequestMapping() String default () { return "This is a default method for the class"; } }
在這段代碼中,向 /home 發起的一個請求將會由 default() 來處理,由於註解並無指定任何值。
@RequestMapping 快捷方式
Spring 4.3 引入了方法級註解的變體,也被叫作 @RequestMapping 的組合註解。組合註解能夠更好的表達被註解方法的語義。它們所扮演的角色就是針對 @RequestMapping 的封裝,並且成了定義端點的標準方法。
例如,@GetMapping 是一個組合註解,它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一個快捷方式。
方法級別的註解變體有以下幾個:
以下代碼展現瞭如何使用組合註解:
@RestController @RequestMapping("/home") public class IndexController { @GetMapping("/person") public @ResponseBody ResponseEntity < String > getPerson() { return new ResponseEntity < String > ("Response from GET", HttpStatus.OK); } @GetMapping("/person/{id}") public @ResponseBody ResponseEntity < String > getPersonById(@PathVariable String id) { return new ResponseEntity < String > ("Response from GET with id " + id, HttpStatus.OK); } @PostMapping("/person") public @ResponseBody ResponseEntity < String > postPerson() { return new ResponseEntity < String > ("Response from POST method", HttpStatus.OK); } @PutMapping("/person") public @ResponseBody ResponseEntity < String > putPerson() { return new ResponseEntity < String > ("Response from PUT method", HttpStatus.OK); } @DeleteMapping("/person") public @ResponseBody ResponseEntity < String > deletePerson() { return new ResponseEntity < String > ("Response from DELETE method", HttpStatus.OK); } @PatchMapping("/person") public @ResponseBody ResponseEntity < String > patchPerson() { return new ResponseEntity < String > ("Response from PATCH method", HttpStatus.OK); } }
在這段代碼中,每個處理方法都使用 @RequestMapping 的組合變體進行了註解。儘管每一個變體均可以使用帶有方法屬性的 @RequestMapping 註解來互換實現, 但組合變體仍然是一種最佳的實踐 — 這主要是由於組合註解減小了在應用程序上要配置的元數據,而且代碼也更易讀。
@RequestMapping 總結
如你在本文中所看到的,@RequestMapping 註解是很是靈活的。你可使用該註解配置 Spring MVC 來處理大量的場景用例。它能夠被用來在 Spring MVC 中配置傳統的網頁請求,也能夠是 REST 風格的 Web 服務。
英文原文地址:https://dzone.com/articles/using-the-spring-requestmapping-annotation