SpringMVC系列第2篇:@Controller、@RequestMapping
大家好,我是【路人甲 Java】號主路人,本文如果對你有幫助,請幫忙轉發(fā)一下,多謝,看的過程中有問題可以加我微信 itsoku 交流。
1、本文內(nèi)容
@Controller 用法 @RequestMapping 用在方法上 @RequestMapping 用在類上 @RequestMapping 6 種規(guī)則詳解 http 請求頭中的 Content-Type 是干什么的? http 請求頭中的 Accept 是干什么的? @PostMapping、@GetMapping、@DeleteMapping、@PutMapping
2、@Controller
用來標注在類上,表示這個類是一個控制器類,可以用來處理 http 請求,通常會和@RequestMapping 一起使用。
源碼如下,這個注解上面有@Component 注解,說明被@Controller 標注的類會被注冊到 spring 容器中,value 屬性用來指定這個 bean 的名稱,也可以不指定,由容器自動生成。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
@AliasFor(annotation = Component.class)
String value() default "";
}
3、@RequestMapping
3.1、作用
表示請求映射,一般用在我們自定義的 Controller 類上或者 Controller 內(nèi)部的方法上。
通過這個注解指定配置一些規(guī)則,滿足這些規(guī)則的請求會被標注了@RequestMapping 的方法處理。
3.2、源碼
源碼如下,包含了 8 個屬性,這些屬性都是用來配置規(guī)則的,大家通過名稱的基本上可以知道每個屬性是來配置哪些規(guī)則的。
@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[] produces() default {};
}
3.3、規(guī)則匹配原理
當 springmvc 容器啟動時,會掃描標注有@Controller 注解的類,將這些 Controller 中標注有@RequestMapping 的方法收集起來,得到一個 Map<@RequestMapping,Method>(@RequestMapping 和方法的映射),當一個請求到達 DispatcherServlet 的時候,其內(nèi)部會根據(jù)請求的信息(url、參數(shù)、header、請求的類型【通過頭中的 Content-type 指定】、可以接受的類型【可以通過頭中的 Accept 指定】)去這個 Map 中和@RequestMapping 中的規(guī)則進行匹配,從而得到可以處理這個請求的方法,然后進行調(diào)用,所有的@RequestMapping 都匹配失敗的時候,會返回 404
3.4、通過@RequestMapping 可配置 6 種規(guī)則
@RequestMapping 支持 6 種規(guī)則,這些規(guī)則都是通過@RequestMapping 中的屬性進行配置的,多個屬性的值是 AND 關系
下面我們一起來熟悉這 6 種規(guī)則。
3.4.1、規(guī)則 1:通過 value、path 來限制請求地址
用法
可以指定 value、path 這 2 個屬性中的任意一個,作用是一樣的,用來對請求的 url 進行限制。
多個值的關系
這幾個屬性的類型都是 String 類型的數(shù)組,說明可以指定多個值,多個值之間是 OR 關系。
案例
| url 的值 | 說明 |
|---|---|
| {"/user/insert"} | 可以處理/user/insert 這個請求 |
| {"/user/list","/user/getList"} | 可以同時處理/user/list 和/user/getList 這 2 個請求 |
3.4.2、規(guī)則 2:通過 header 屬性來限制請求頭
用法
通過 header 屬性來對請求中的 header 進行限制,比如我們希望請求中必須必須攜帶 token 這個頭,那么就可以使用這個。
多個值的關系
AND 關系
案例
| header 的值 | 說明 |
|---|---|
| {“header1”} | 請求的 header 中必須有 header1 這個頭,值隨意 |
| {“header1=v1”} | 必須包含 header1 為 v1 的頭 |
| {“!header1} | 這里用到了!符號,表示頭中不能有 header1 這個頭 |
| {“header1”,“header2=v2”} | header 的值是 and 關系,所以這個值表示:頭中必須包含 header1 以及 header2,且 header2 的值為 v2 |
3.4.3、規(guī)則 3:通過 params 屬性來限制請求參數(shù)
用法
通過 params 屬性來限制請求中的參數(shù),比如我們希望請求中必須有某些指定的參數(shù)時,才能被指定的方法處理,可以使用這個。
多個值的關系
AND 關系
案例
| params 的值 | 說明 |
|---|---|
| {"name"} | 請求中必須包含 name 參數(shù),值隨意 |
| {"name=路人"} | 請求中必須包含name這個參數(shù),且值必須是路人 |
| {“name","age=1"} | 請求中必須包含參數(shù) name 和參數(shù) age,且 age 的值為 1 |
| {"!age"} | 請求中不能有參數(shù) age |
3.4.4、規(guī)則 4:通過 method 屬性來限制 http 請求額方法
用法
如果需要限制某個方法只能處理 http 的 post 請求,那么就可以通過 method 屬性來進行設置,如果不指定 method 的值,表示對 http 請求額 method 無限制。
OR 關系
案例
| method 的值 | 說明 |
|---|---|
| {POST} | 只能接受 post 請求 |
| {POST,GET} | post、get 請求都可以處理 |
3.4.5、規(guī)則 5:通過 consumes 屬性來限制請求的類型
Content-Type 是什么?
熟悉 http 請求的朋友應該對 Content-Type 這個屬性比較眼熟吧,這個屬性是用來做什么的?
Content-Type 用來指定 http 請求中 body 的數(shù)據(jù)的類型,是 Json 呢?還是文本呢?還是圖片、pdf 呢?
這些就可以通過 Content-Type 來進行指定,這樣服務器接受到請求的時候,就知道 body 中數(shù)據(jù)的類型了,比如 application/json,就表示 body 中是一個 json 數(shù)據(jù),那么服務器就可以以 json 的方式來解析 body 中的數(shù)據(jù)。
來幾個大家熟悉的
| Content-Type 的值 | 說明 |
|---|---|
| application/x-www-form-urlencoded | 這個是我們最常見的,通常我們在頁面中通過 post 方式來提交一個表單,那么這個請求的類型就是這種 |
| multipart/form-data | 通過表單上傳文件用的就是這種類型,這種表示請求的 body 有多部分組成 |
| application/json | 表示 body 中的數(shù)據(jù)是一個 json 格式的數(shù)據(jù) |
| image/gif | 表示 body 中的數(shù)據(jù)是 gif 圖片 |
Content-Type 通常有主類型和子類型,中間通過/分割,這里就不詳細展開了,有興趣的朋友可以去百度專門研究下。
consumes 屬性用法
而@RquestMapping 中的 consumers 就是用來對 Content-Type 進行限制。
多個值的關系
OR 關系
案例
| consumes 的值 | 說明 |
|---|---|
| {"application/x-www-form-urlencoded"} | 請求中 Content-Type 的類型必須是 application/x-www-form-urlencoded 類型 |
| {"application/*"} | Content-Type 的類型必須是 application 類型的,比如:application/json、application/pdf、application/x-www-form-urlencoded |
| {"image/gif", "image/png"} | Content-Type 的可以是["image/gif", "image/png"]中的任意一種 |
3.4.6、規(guī)則 6:通過 produces 屬性來限制客戶端可以接受的類型
Accept 是什么?
熟悉 http 請求的朋友應該對 Accept 這個屬性比較眼熟吧,這個屬性是用來做什么的?
和 Content-Type 剛好相反,Content-Type 用來指定客戶端發(fā)送的數(shù)據(jù)的類型,而Accept 是用來指定客戶端希望接受的數(shù)據(jù)的類型的。
比如客戶端希望服務器端返回 json 格式的數(shù)據(jù),那么可以這么指定
Accept: application/json
值可以 Content-Type 的值類似,這里就不舉例了。
produces 屬性用法
指定返回的內(nèi)容類型,僅當 request 請求頭中的(Accept)類型中包含該指定類型才返回。
多個值的關系
OR 關系
案例
| produces 的值 | 說明 |
|---|---|
| {"application/json"} | 服務器端支持返回 application/json 類型數(shù)據(jù),所以要求 Accept 也可以接受這種類型的數(shù)據(jù) |
| {"image/gif", "image/png"} | 服務器端支持返回["image/gif", "image/png"]中其中一種類型數(shù)據(jù),所以要求 Accept 也可以接受這 2 中種類型中任意一種就可以 |
4、6 種規(guī)則對照表
| 屬性 | 多個值之間的關系 | 說明 |
|---|---|---|
| value、path | OR | 限制 url |
| header | AND | 限制請求頭 |
| params | AND | 限制請求的參數(shù) |
| method | OR | 限制 http 請求的 method |
| consumes | OR | 限制 Content-Type 的類型(客戶端發(fā)送數(shù)據(jù)的類型) |
| produces | OR | 限制 Aceept 的類型(客戶端可接受數(shù)據(jù)的類型) |
5、其他幾個注解
| 注解 | 相當于 |
|---|---|
| @PostMapping | @RequestMapping(method=RequestMethod.POST) |
| @GetMapping | @RequestMapping(method=RequestMethod.GET) |
| @DeleteMapping | @RequestMapping(method=RequestMethod.DELETE) |
| @PutMapping | @RequestMapping(method=RequestMethod.PUT) |
6、@RequestMapping 用在類上
作用
用于將方法上@RequestMapping 共有的規(guī)則提取出來,放在類上,起到重用的作用,可以簡化代碼。
案例
如下圖的 controller 中有 4 個方法都有@RequestMapping,他們的 value 屬性的值都以/user開頭,那么我們就可以將這部分提取出來放在這個類上面。

簡化之后,變成了下面這樣,將他們共有的部分提取到類上的@RequestMapping 中了,起到了共用的作用。

7、SpringMVC 系列源碼
https://gitee.com/javacode2018/springmvc-series
8、總結
@RequestMaping 中 value、path、consumers、producers 稍微用到的多一些,其他幾個屬性用到的比較少,了解即可。
關于 6 種規(guī)則,大家可以自己去試試,會 springboot 的朋友,可以直接使用 springboot 快速寫一些用例結合 postman 測試下,加深記憶和理解。
9、推薦一個高質(zhì)量的公眾號
這里給大家推薦一個公眾號:Java 充電社,掃碼大家關注下,這個號中會定期發(fā)布一些高質(zhì)量的 java 專題視頻,幫大家充電。
