說說Spring中的 @RestController 和 @Controller
Spring MVC執行流程已是JAVA面試中老生常談的問題,相信各位小夥伴也是信手拈來。今天我們來談談另一個面試中必會必知的問題: @RestController
和@Controller
的區別?
- Spring MVC中的REST實現
- @Controller + @ResponseBody註解
- @RestController註解
Spring MVC 與 REST
基於註解的MVC框架簡化了建立RESTful web服務的過程。傳統的Spring MVC控制器和RESTful web服務控制器之間的關鍵區別是HTTP響應體的建立方式。傳統的MVC控制器依賴於檢視技術,基於REST的web服務控制器僅返回物件,而物件資料直接以JSON/XML的形式寫入HTTP響應。
Spring MVC對 REST 的支援
支援以下方式來建立 REST 資源:
- 控制器可以處理所有的HTTP方法,包含四個主要的REST方法:GET、PUT、DELETE以及POST;
- 訊息轉換器(Message conversion)將資源的JAVA表述形式轉換為傳送給客戶端的表述形式;
- 藉助於 SpringMVC 的一系列註解,構建 REST API;
- 藉助 RestTemplate,Spring應用能夠方便地使用REST資源;
典型的Spring MVC工作流
在傳統的工作流中,ModelAndView物件是從控制器轉發到客戶機的,通過在方法上加@ResponseBody,Spring直接從控制器返回資料,而不需要查詢檢視。從4.0版本開始,隨著@RestController註釋的引入,這個過程得到了進一步簡化。下面將解釋每種方法。
使用@Controller + @ResponseBody註解
@Controller用於標記在一個類上,使用它標記的類就是一個Spring MVC Controller物件,分發處理器會掃描使用該註解的類的方法,並檢測該方法是否使用了@RequestMapping註解。
@ResponseBody註解用於將Controller的方法返回的物件,通過適當的HttpMessageConverter轉換為指定格式後,寫入到Response物件的body資料區,通常用來返回 JSON 或者 XML 資料,返回 JSON 資料的情況比較多。
Spring有一個在後臺註冊的HttpMessageConverters列表。HTTPMessageConverter的職責是根據預定義的mime型別將請求主體轉換為特定的類,然後再轉換回響應主體。每當發出的請求點選@ResponseBody時,Spring迴圈遍歷所有已註冊的HttpMessageConverters,尋找第一個符合給定mime型別和類的請求,然後將其用於實際的轉換。
程式碼示例
建立實體類:
package com.laocaicai.week1.entity;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Dog")
public class DogEntity {
String name;
String breed;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public DogEntity() {
}
}
建立Controller:
package com.laocaicai.week1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.laocaicai.week1.entity.DogEntity;
@Controller
@RequestMapping("dogs")
public class DogController {
DogEntity dog = new DogEntity();
@RequestMapping(value = "/{name}", method = RequestMethod.GET, produces = "application/json")
public @ResponseBody DogEntity getDogInJSON(@PathVariable String name) {
dog.setName(name);
dog.setBreed("中國細犬");
return dog;
}
@RequestMapping(value = "/{name}.xml", method = RequestMethod.GET, produces = "application/xml")
public @ResponseBody DogEntity getDogInXML(@PathVariable String name) {
dog.setName(name);
dog.setBreed("中國細犬");
return dog;
}
}
在Spring配置檔案中新增
和
標籤,前者用於啟用註釋並掃描包以查詢和註冊應用程式上下文中的bean,後者增加了對讀取和寫入JSON/XML的支援(對於返回JSON格式資料,需要匯入jackson-databind依賴;對於XML格式,需要匯入jaxb-api-osgi依賴)
使用URL:http://localhost:8687/week_1/dogs/哮天犬
,輸出JSON:
使用URL:http://localhost:8687/week_1/dogs/哮天犬.xml
,輸出XML:
使用@RestController註解
Spring 4.0引入了@RestController
,@RestController
註解是一種快捷方式,它所宣告的控制器在返回響應時,就如同使用了@ResponseBody
註解一樣。它會告訴Spring 將返回型別序列化為合適的格式,預設情況下為JSON 格式。通過用@RestController
註釋控制器類,您不再需要向所有請求對映方法新增@ResponseBody
。
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Controller;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
String value() default "";
}
要在我們的示例中使用@RestController
,我們所需要做的就是將@Controller
修改為@RestController
並從每個方法中刪除@ResponseBody
。生成的類應該如下所示
package com.laocaicai.week1.controller;
import com.laocaicai.week1.entity.DogEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("2dogs")
public class DogRestController {
DogEntity dog = new DogEntity();
@RequestMapping(value = "/{name}", method = RequestMethod.GET, produces = "application/json")
public DogEntity getDogInJSON(@PathVariable String name) {
dog.setName(name);
dog.setBreed("中國細犬");
return dog;
}
@RequestMapping(value = "/{name}.xml", method = RequestMethod.GET, produces = "application/xml")
public DogEntity getgetDogInXMLInXML(@PathVariable String name) {
dog.setName(name);
dog.setBreed("中國細犬");
return dog;
}
}
注意,我們不再需要將
@ResponseBody
新增到請求對映方法中,在進行更改之後,再次在伺服器上執行應用程式會產生與之前相同的輸出。
總結
通過本篇的介紹,小夥伴們會發現使用@RestController
非常簡單,是從Spring v4.0開始建立MVC RESTful web服務的首選方法。@RestController
(Spring4+)相當於@Controller
+ @ResponseBody
,返回json或者xml格式資料;如果在控制器類上使用@RestController
來代替@Controller
的話,Spring將會為該控制器的所有處理方法應用訊息轉換功能,我們不必為每個方法都新增@ResponseBody
了。
參考資料:
- 跟開濤學SpringMVC
- SpringMVC中Controller的@ResponseBody註解分析
- 【SpringBoot】 http請求註解之@RestController
- @RestController註解初步理解
- Spring Framework: @RestController vs. @Controller
本文作者:Srivatsan Sundararajan, 翻譯:laocaicaicai 原文連結:https://dzone.com/articles/spring-framework-restcontroller-vs-controller 譯文首發:http://blog.didispace.com/tr-spring-framework-restcontroller-vs-controller/
本文有spring4all技術翻譯組完成,更多國外前沿知識和乾貨好文,歡迎關注公眾號:後端面試那些事兒。