Spring MVC註解詳解(上)


Spring MVC註解詳解(上)


序言

在上一節中,集中講解了Spring框架中的構造型註解@Component,@Controller,@Service和@Repository。在本章節中,將集中講解Spring MVC中的註解進行講解。對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的屬性進行介紹。


Spring MVC註解詳解(上)


在接下來的內容中,將分別演示如何使用這些屬性。


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註解詳解(上)


以上就是本節的全部內容,在下一篇內容當中,將介紹更細粒度的Spring MVC註解,例如@ExceptionHandler,@InitBinder,@RequestAttribute,@RequestBody等等。



分享到:


相關文章: