說說Spring中的 @RestController 和 @Controller

Spring MVC執行流程已經是JAVA面試中老生常談的問題,相信各位小夥伴也是信手拈來。今天咱們來談談另外一個面試中必會必知的問題: @RestController@Controller的區別?html

  • Spring MVC中的REST實現
  • @Controller + @ResponseBody註解
  • @RestController註解

Spring MVC 與 REST

基於註解的MVC框架簡化了建立RESTful web服務的過程。傳統的Spring MVC控制器和RESTful web服務控制器之間的關鍵區別是HTTP響應體的建立方式。傳統的MVC控制器依賴於視圖技術,基於REST的web服務控制器僅返回對象,而對象數據直接以JSON/XML的形式寫入HTTP響應。java

Spring MVC對 REST 的支持

支持如下方式來建立 REST 資源:web

  • 控制器能夠處理全部的HTTP方法,包含四個主要的REST方法:GET、PUT、DELETE以及POST;
  • 消息轉換器(Message conversion)將資源的JAVA表述形式轉換爲發送給客戶端的表述形式;
  • 藉助於 SpringMVC 的一系列註解,構建 REST API;
  • 藉助 RestTemplate,Spring應用可以方便地使用REST資源;

典型的Spring MVC工做流

典型的Spring MVC工做流程

在傳統的工做流中,ModelAndView對象是從控制器轉發到客戶機的,經過在方法上加@ResponseBody,Spring直接從控制器返回數據,而不須要查找視圖。從4.0版本開始,隨着@RestController註釋的引入,這個過程獲得了進一步簡化。下面將解釋每種方法。面試

使用@Controller + @ResponseBody註解

@Controller用於標記在一個類上,使用它標記的類就是一個Spring MVC Controller對象,分發處理器會掃描使用該註解的類的方法,並檢測該方法是否使用了@RequestMapping註解。spring

@ResponseBody註解用於將Controller的方法返回的對象,經過適當的HttpMessageConverter轉換爲指定格式後,寫入到Response對象的body數據區,一般用來返回 JSON 或者 XML 數據,返回 JSON 數據的狀況比較多。json

Spring有一個在後臺註冊的HttpMessageConverters列表。HTTPMessageConverter的職責是根據預約義的mime類型將請求主體轉換爲特定的類,而後再轉換回響應主體。每當發出的請求點擊@ResponseBody時,Spring循環遍歷全部已註冊的HttpMessageConverters,尋找第一個符合給定mime類型和類的請求,而後將其用於實際的轉換。

Spring3.x MVC RESTful網絡服務工做流程

代碼示例

建立實體類:後端

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:api

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:服務器

返回JSON格式數據

使用URL:http://localhost:8687/week_1/dogs/哮天犬.xml,輸出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 "";
}

Spring4.x MVC RESTful網絡服務工做流程

要在咱們的示例中使用@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了。

參考資料

本文做者:Srivatsan Sundararajan, 翻譯:laocaicaicai
原文連接: https://dzone.com/articles/sp...
譯文首發: http://blog.didispace.com/tr-...
本文有spring4all技術翻譯組完成,更多國外前沿知識和乾貨好文,歡迎關注公衆號:後端面試那些事兒。
相關文章
相關標籤/搜索