第一層注解:@Controller 和 @RestController。
這兩個注解的作用是:處理頁面的HTTP請求,不同點 @RestController相當於@Controller +@ResponseBody。@ResponseBody的解釋見下文。
1 @Controller 2 //@ResponseBody 3 public class HelloController { 4 5 @RequestMapping(value="/hello",method= RequestMethod.GET) 6 public String sayHello(){ 7 return "hello"; 8 } 9 }
如果直接使用@Controller這個注解,當運行該SpringBoot項目后,在瀏覽器中輸入:local:8080/hello,會得到如下錯誤提示:
出現這種情況是因為沒有使用模板,使用@Controller響應頁面必須配合模板來使用。Spring boot支持的引擎包括:
1,FreeMaker 2,Groovy 3,Thymeleaf 4,Velocity 5,JSP
使用模板時需要在pom.xml文件中添加模板依賴。如下所示:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
然后需要在resources目錄下的templates目錄中添加一個hello.html文件,這個文件就是你所要顯示的頁面。
使用@RestController相當於同時使用了@Controller和@ResponseBody。
第二層注解:@RequestMapping
這個注解既可以作用在類上,也可以作用在方法上,也可以同時作用在類和方法上,其作用是指明該類或者該方法響應哪個路徑下的請求。
在使用這些注解之前,先了解一下請求與處理方法之間的映射關系。(圖片來源於網上,沒太看懂)
在類的級別上的注解會將一個特定請求或者請求模式映射到一個控制器之上。之后你還可以另外添加方法級別的注解來進一步指定到處理方法的映射關系。 下面是一個同時在類和方法上應用了 @RequestMapping 注解的示例:
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() 來處理。
@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() 來處理:
- localhost:8080/home
- localhost:8080/home/
- localhost:8080/home/page
- localhost:8080/home/pageabc
- localhost:8080/home/view/
- localhost:8080/home/view/view
第三層注解:@ResponseBody和@RequestBody
@ResponseBody表示該方法的返回結果直接寫入HTTP響應正文(ResponseBody)中,默認返回值是跳轉路徑;
@RequestBody表示將HTTP請求直接寫入對象中,默認請求參數是URL。
1 @RequestMapping(value = "user/login") 2 @ResponseBody 3 // 將ajax(datas)發出的請求寫入 User 對象中,返回json對象響應回去 4 public User login(User user) { 5 User user = new User(); 6 user .setUserid(1); 7 user .setUsername("MrF"); 8 user .setStatus("1"); 9 return user ; 10 }
1 @RequestMapping(value = "user/login") 2 @ResponseBody 3 // 將ajax(datas)發出的請求寫入 User 對象中 4 public User login(@RequestBody User user) { 5 // 這樣就不會再被解析為跳轉路徑,而是直接將user對象寫入 HTTP 響應正文中 6 return user; 7 }
第四層注解:@RequestParam 、 @Valid 和 @PathVariable
@RequestParam 是指明請求的參數,@Vaild是驗證參數的合法性,@PathVariable是處理動態的URL。
@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 這個參數定義了參數值是否是必須要傳的,為true時必須要傳。
1 1 @RestController 2 2 @RequestMapping("/home") 3 3 public class IndexController { 4 4 @RequestMapping(value = "/name") 5 5 String getName(@RequestParam(value = "person", required = false) String personName) { 6 6 return "Required element of request param"; 7 7 } 8 8 }
在這段代碼中,因為 required 被指定為 false,所以 getName() 處理方法對於如下兩個 URL 都會進行處理:
- /home/name?person=xyz
- /home/name
@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 這樣的格式:
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 @RequestMapping(value = "/head", headers = { 5 "content-type=text/plain" 6 }) 7 String post() { 8 return "Mapping applied along with headers"; 9 } 10 }
在上面這段代碼中, @RequestMapping 注解的 headers 屬性將映射范圍縮小到了 post() 方法。有了這個,post() 方法就只會處理到 /home/head 並且 content-typeheader 被指定為 text/plain 這個值的請求。
你也可以像下面這樣指定多個消息頭:
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 @RequestMapping(value = "/head", headers = { 5 "content-type=text/plain", 6 "content-type=text/html" 7 }) String post() { 8 return "Mapping applied along with headers"; 9 } 10 }
這樣, post() 方法就能同時接受 text/plain 還有 text/html 的請求了。
使用 @RequestMapping 來處理請求參數
@RequestMapping 直接的 params 元素可以進一步幫助我們縮小請求映射的定位范圍。使用 params 元素,你可以讓多個處理方法處理到同一個URL 的請求, 而這些請求的參數是不一樣的。
你可以用 myParams = myValue 這種格式來定義參數,也可以使用通配符來指定特定的參數值在請求中是不受支持的。
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 @RequestMapping(value = "/fetch", params = { 5 "personId=10" 6 }) 7 String getParams(@RequestParam("personId") String id) { 8 return "Fetched parameter using params attribute = " + id; 9 } 10 @RequestMapping(value = "/fetch", params = { 11 "personId=20" 12 }) 13 String getParamsDifferent(@RequestParam("personId") String id) { 14 return "Fetched parameter using params attribute = " + id; 15 } 16 }
在這段代碼中,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。
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 @RequestMapping(value = "/fetch/{id}", method = RequestMethod.GET) 5 String getDynamicUriValue(@PathVariable String id) { 6 System.out.println("ID is " + id); 7 return "Dynamic URI parameter fetched"; 8 } 9 @RequestMapping(value = "/fetch/{id:[a-z]+}/{name}", method = RequestMethod.GET) 10 String getDynamicUriValueRegex(@PathVariable("name") String name) { 11 System.out.println("Name is " + name); 12 return "Dynamic URI parameter fetched using regex"; 13 } 14 }
在這段代碼中,方法 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 發起的請求時被執行。
下面是默認處理方法的示例:
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 @RequestMapping() 5 String 6 default () { 7 return "This is a default method for the class"; 8 } 9 }
在這段代碼中,向 /home 發起的一個請求將會由 default() 來處理,因為注解並沒有指定任何值。
@RequestMapping 快捷方式 @PutMapping,@PostMapping,@GetMapping,@PatchMapping,@DeleteMapping
Spring 4.3 引入了方法級注解的變體,也被叫做 @RequestMapping 的組合注解。組合注解可以更好的表達被注解方法的語義。它們所扮演的角色就是針對 @RequestMapping 的封裝,而且成了定義端點的標准方法。
例如,@GetMapping 是一個組合注解,它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一個快捷方式。
方法級別的注解變體有如下幾個:
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
如下代碼展示了如何使用組合注解:
1 @RestController 2 @RequestMapping("/home") 3 public class IndexController { 4 @GetMapping("/person") 5 public @ResponseBody ResponseEntity < String > getPerson() { 6 return new ResponseEntity < String > ("Response from GET", HttpStatus.OK); 7 } 8 @GetMapping("/person/{id}") 9 public @ResponseBody ResponseEntity < String > getPersonById(@PathVariable String id) { 10 return new ResponseEntity < String > ("Response from GET with id " + id, HttpStatus.OK); 11 } 12 @PostMapping("/person") 13 public @ResponseBody ResponseEntity < String > postPerson() { 14 return new ResponseEntity < String > ("Response from POST method", HttpStatus.OK); 15 } 16 @PutMapping("/person") 17 public @ResponseBody ResponseEntity < String > putPerson() { 18 return new ResponseEntity < String > ("Response from PUT method", HttpStatus.OK); 19 } 20 @DeleteMapping("/person") 21 public @ResponseBody ResponseEntity < String > deletePerson() { 22 return new ResponseEntity < String > ("Response from DELETE method", HttpStatus.OK); 23 } 24 @PatchMapping("/person") 25 public @ResponseBody ResponseEntity < String > patchPerson() { 26 return new ResponseEntity < String > ("Response from PATCH method", HttpStatus.OK); 27 } 28 }
在這段代碼中,每一個處理方法都使用 @RequestMapping 的組合變體進行了注解。盡管每個變體都可以使用帶有方法屬性的 @RequestMapping 注解來互換實現, 但組合變體仍然是一種最佳的實踐 — 這主要是因為組合注解減少了在應用程序上要配置的元數據,並且代碼也更易讀。
本文參考自:
http://www.iteye.com/news/32657,
https://blog.csdn.net/ff906317011/article/details/78552426 ,