序言
在上一節中,集中講解了Spring框架中的構造型註解@Component,@Controller,@Service和@Repository。在本章節中,將集中講解Spring MVC中的註解進行講解。對Spring MVC框架中所有註解的作用和用法進行解析。
1.@Controller
@Controller是一個類級別的註解,其表明當前類是Spring MVC中的視圖控制器。當Spring應用程序開啟了組件掃描後,Spring會根據類路徑對那些帶有@Controller註解的類進行掃描,並將其自動注入到Spring的容器中。該註解是Spring MVC框架中一個比較常見的註解,通常與@RequestMapping搭配使用。處理能在Spring MVC中使用外,@Controller註解也可以在Spring WebFlux中使用。下面是@Controller註解的簡單示例:
<code>@Controller
@RequestMapping("/demo")
public class DemoController{
//省略其他
}/<code>
2. @RequestMapping
@RequestMapping可同時在類和方法上使用的註解。該註解用於將Web請求映射到具體的處理類和處理方法上。當該註解作用在類上時,你可以簡單的理解為該註解定義了當前控制器所映射的Request請求地址的前綴,類中所有的處理方法都會加上在類上定義的URI地址。當該註解作用於方法上時,會將符合其URI規則的Request請求映射到當前的方法上。請看下面的例子:
<code>@Controller
@RequestMapping("/users")
public class UserController{
@RequestMapping("/")
public String index(){
return "/user/index";
}
@RequestMapping("/add")
public String add(){
return "/user/add"
}
}/<code>
在上面的例子中,"/users/"會被映射到index()方法上,而”/users/add“會被映射到add()方法上。在默認情況下,@RequestMapping所處理的Web請求類型為"GET"類型。除了上述的方式之外,我們還可以取消在類上的註解,只在方法上進行定義,代碼如下:
<code>@Controller
public class UserController{
@RequestMapping("/users/")
public String index(){
return "/user/index";
}
@RequestMapping("/users/add")
public String add(){
return "/user/add"
}
}/<code>
為了代碼的可讀性和簡潔性,推薦使用第一種方式定義請求的URI規則。
上述的書寫方式是@RequestMapping的簡寫,“/users/”,"/users/add"其實是在給@RequestMapping的value屬性進行賦值。value屬性接受一個或多個String類型的變量,該變量可以是字符串,也可以是EL表達式。
2.1 @RequestMapping屬性
@RequestMapping有六個屬性值,它們分別是value,method,consumes,produces,params和headers。我們可以通過@RequestMapping註解詳細瞭解一下:
RequestMapping.java
<code>@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}/<code>
接下來,將分別對@RequestMapping的屬性進行介紹。
在接下來的內容中,將分別演示如何使用這些屬性。
2.2 處理多個URL
從@RequestMapping的代碼中可以看到,value屬性接受一個String類型的數組。因此,我們可以通過value屬性將多個URL請求映射到同一個方法上,例如:
<code>@Controller
public class DemoController{
@RequestMapping(value={"/","/index","/index.html","/home/index","/home/index.html","/start","/start.html"})
public String home(){
return "/home";
}
}/<code>
設定應用程序的端口號為8080,那麼,下列的請求都將被映射到DemoController類的home()方法上。
- localhost:8080/
- localhost:8080/index
- localhost:8080/index.html
- localhost:8080/home/index
- localhost:8080/home/index.html
- localhost:8080/start
- localhost:8080/start.html
2.3 限定請求類型
@RequestMapping註解能夠處理多種類型的Web請求,通過指定method屬性的值,可以讓方法處理諸如GET,POST,PUT,DELETE,PATCH等類型的請求。在默認情況下,@RequestMapping註解處理請求的類型為GET。在@RequestMapping註解中,method屬性值的類型為RequestMethod類型,RequestMethod是一個枚舉類型的Java類,內容如下:
RequestMethod.java
<code>public enum RequestMethod {
GET,
HEAD,
POST,
PUT,
PATCH,
DELETE,
OPTIONS,
TRACE;
private RequestMethod() {
}
}
/<code>
接下來,通過一個簡單的Demo代碼,瞭解method屬性的使用。
<code>@RestController
@RequestMapping("/hello")
public class SayHelloController{
@RequestMapping(method=RequestMethod.GET)
public String get(){
return "Hello World!";
}
@RequestMapping(method=RequestMethod.DELETE)
public String delete(){
return "Delete Handler.";
}
@RequestMapping(method=RequestMethod.POST)
public String post(){
return "POST Handler.";
}
@RequestMapping(method=RequestMethod.PUT)
public String put(){
return "PUT Handler.";
}
@RequestMapping(method=RequestMethod.PATCH)
public String patch(){
return "PATCH Handler.";
}
}/<code>
說明
為了便於測試,在這裡使用了@RestController註解,它是@Controller和@ResponseBody兩個註解的組合註解。你也可以理解為快捷方式。
在上述的例子中,方法上的@RequestMapping沒有指定value屬性的值,則所有方法的請求URL都為類上定義的“/hello”;Spring MVC會根據“/hello”請求類型的不同,將URL映射到各自的方法上。例如,當“/hello”是以GET的方式發送請求,則該請求會被映射到get()方法上,同時將“Hello World”字符串返回到客戶端。最後,我們通過CURL命令來測試這些請求:
<code>
$ curl -X GET http://localhost:8080/hello
Hello World
/<code>
<code>$ curl -X DELETE http://localhost:8080/hello
Delete Handler.
/<code>
<code>$ curl -X POST http://localhost:8080/hello
POST Handler.
/<code>
<code>$ curl -X PUT http://localhost:8080/hello
PUT Handler.
/<code>
<code>$ curl -X PATCH http://localhost:8080/hello
PATCH Handler./<code>
2.4 限定數據格式
在使用@RequestMapping註解時,可以通過consumes和produces兩個屬性來限定請求和響應的數據格式。如果某個處理方法只允許接收JSON格式的請求數據,則可以通過設置consumes屬性進行限定,例如:
<code>@RestController
@RequestMapping("/users")
public class UserController{
@RequestMapping(value="/add",method=RequestMethod.POST,consumes="application/JSON")
public String add(User user){
//...
return "Success!";
}
}/<code>
如果你想限定方法返回值的數據類型,則可以通過produes屬性進行指定,例如:
<code>@RestController
@RequestMapping("/users")
public class UserController{
@RequestMapping(value="/add",method=RequestMethod.POST,produces="application/JSON")
public User add(User user){
//...
return user;
}
}/<code>
2.5 headers屬性
如果在使用@RequestMapping註解時,你想根據header中設置的參數來映射具體的處理方法,則可以通過headers屬性進行指定,例如:
<code>@RestController
@RequestMapping("/demo")
public class DemoController{
@RequestMapping(headers={"content-type=text/plain"})
public String header(){
return "headers handler";
}
}/<code>
在此示例中,只有當請求頭中Content-Type=text/plain時,“http://localhost:8080/demo”請求才會被映射到header()方法上。下面是通過curl測試的結果:
<code>$ curl -H "Content-Type:text/html" http://localhost:8080/demo
header handler/<code>
<code>$ curl -H "Content-Type:application/json" http://localhost:8080/demo
{"timestamp":"2020-04-01T08:08:57.224+0000","status":415,"error":"Unsupported Media Type","message":"Content type 'application/json' not supported","path":"/demo"}/<code>
2.6 params屬性
如果某個方法在處理Web請求時必須要求中攜帶指定的參數,則可以通過params指定,只有符合URL規則且有指定參數的請求才會映射到當前的方法上,例如:
<code>@RestController
public class OtherController {
@RequestMapping(value = "/demo/params",params = "token=123")
public String params(){
return "params handler";
}
}/<code>
curl測試結果:
<code>$ curl http://localhost:8080/demo/params?token=123
params handler
/<code>
<code>$ curl http://localhost:8080/demo/params
{"timestamp":"2020-04-01T08:26:18.492+0000","status":400,"error":"Bad Request","message":"Parameter conditions "token=123" not met for actual request parameters: ","path":"/demo/params"}
/<code>
2.7 與@RequestParam註解配合使用
@RequestMapping和@RequestParam註解一起使用,可以將Web請求參數綁定到處理方法的參數上。可以使用@RequestParam給方法屬性指定默認值以及設定該參數是否是必須的。例如:
<code>@RequestMapping("/demo/requestparam")
public String requestMethod(@RequestParam("username")String username,@RequestParam(value = "id",defaultValue = "0")Integer id){
return "username:"+username+", id:"+id;
}/<code>
curl測試結果:
<code>$ curl http://localhost:8080/demo/requestparam?username=ramostear&id=1000
username:ramostear, id:1000/<code>
<code>$ curl http://localhost:8080/demo/requestparam?username=ramostear
username:ramostear, id:0/<code>
2.8 動態URL
@RequestMapping可以和@PathVariable註解配合處理動態的URI,在這種情況下,URI中動態參數可以和方法中的參數進行綁定,同時還可以使用正則表達式進行URI的匹配。下面是一個簡單的示例:
<code>@RequestMapping("/demo/{id}")
public String dynamicUri(@PathVariable Integer id){
return "user`s id="+id;
}/<code>
<code>$ curl http://localhost:8080/demo/5
user`s id=5
/<code>
<code>@RequestMapping("user/{id:\\\\d+}/{username:[a-z]+}")
public String dynamicUris(@PathVariable("id") Integer id,
@PathVariable("username") String username){
return "user`s info id="+id+", username="+username;
}/<code>
<code>$ curl http://localhost:8080/user/100/ramostear
user`s info id=100, username=ramostear
/<code>
<code>$ curl http://localhost:8080/user/100/RAMOSTEAR
{"timestamp":"2020-04-01T09:00:04.150+0000","status":404,"error":"Not Found","message":"No message available","path":"/user/100/RAMOSTEAR"}
/<code>
在第二個方法中,我們使用了正則表達式,限定了id必須為數字,username必須是a到z26個小寫字母組成的字符串。
提示:
@PathVariable註解的參數不允許有空值,也沒有默認值,但你可以選擇當前參數是否是必須的。
3 @RequestMapping的快捷方式
Spring框架從4.3版本開始引入@RequestMapping註解的簡寫方式,這些簡寫方式可以提高編碼的效率和代碼的可讀性。簡單來說,@RequestMapping註解快捷方式是@RequestMpping(method=RequestMethod.XX)的一種變體。下面通過一張表格來進行對比:
以上就是本節的全部內容,在下一篇內容當中,將介紹更細粒度的Spring MVC註解,例如@ExceptionHandler,@InitBinder,@RequestAttribute,@RequestBody等等。
閱讀更多 ramostear 的文章