• 说说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工作流

    典型的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类型和类的请求,然后将其用于实际的转换。

    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:

    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/spring-framework-restcontroller-vs-controller
    译文首发:http://blog.didispace.com/tr-spring-framework-restcontroller-vs-controller/

    本文有spring4all技术翻译组完成,更多国外前沿知识和干货好文,欢迎关注公众号:后端面试那些事儿。

  • 相关阅读:
    CH1301 邻值查找【set应用】
    poj1185 炮兵阵地【状压DP】
    codeforces#516 Div2---ABCD
    2017ACM-ICPC沈阳区域赛
    poj2411 Mondriaan's Dream【状压DP】
    hdu2196 Computer【树形DP】【换根法】
    poj3345 Bribing FIPA【树形DP】【背包】
    poj1463 Strategic game【树形DP】
    poj1191 棋盘分割【区间DP】【记忆化搜索】
    CH5E09 能量相连【区间DP】
  • 原文地址:https://www.cnblogs.com/didispace/p/13438340.html
Copyright © 2020-2023  润新知