• Spring MVC对象转换说明


    在Spring MVC之前我们需要在Servlet里处理HttpServletRequest参数对象,但这个对象里的属性都是通用类型的对象(如字符串),处理起来很繁琐并且容易出错,而Spring MVC允许我们直接把参数和返回值定义为对象,比如:

    先定义一个对象:

    @Data
    public class User {
    
        private String id;
        private String name;
    
    }

    然后定义一个Spring MVC方法:

    @RequestMapping(value = "/create-user", method = RequestMethod.POST)
    public void createUser(@RequestBody User user) {
        LOGGER.debug("参数:user = {}", user);
    }

    其中,参数为User类型的对象,@RequestBody注解通知Spring MVC把http请求的body转换为User对象,并作为参数调用我们写的createUser方法。

    除把参数定义为对象外,返回值也能为对象:

    @RequestMapping(value = "/find-user", method = RequestMethod.GET)
    @ResponseBody
    public User findUser() {
        return new User("01", "yw");
    }

    返回值对象需要加@ResponseBody注解,该注解通知Spring MVC把返回值对象转换为字符串,并作为http响应消息中的body部分。

    除@RequestBody、@ResponseBody注解外,Spring MVC还提供了其它注解,具体请参见相关文档说明。

    Spring MVC是如何进行http消息与对象之间的转换呢?答案是HttpMessageConverter转换器接口。

    HttpMessageConverter

    Spring MVC就像是一个中间人,一边为http消息(即HttpServletRequest和HttpServletResponse),另一边是@RequestMapping方法,Spring MVC的使命就是自动把http消息转换为对象,以及反过来把对象转换为字符串返回。这一切都依赖于HttpMessageConverter转换接口。Spring MVC内置了其很多实现,每个实现对应于一种格式的数据转换,我们可按需配置加载转换器。如果未配置则Spring MVC进行默认加载,至于默认加载了哪些转换器请参见WebMvcConfigurationSupport#addDefaultHttpMessageConverters方法,另请参见[Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest)。

    特别要提醒的是,如果你配置了则Spring MVC将只加载你配置的,如果你未配置则默认加载。因此,不要误以为你的配置是对默认值的补充。

    我们基本上不需要自己去配置转换器,使用默认配置就足够了。但如果你有必要则可这样配置:

    @Configuration
    @EnableWebMvc
    public class WeMvcConfiguration extends WebMvcConfigurerAdapter {
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            converters.add(...);
        }
    }

    不论你是否配置了,我们最好都检查一下运行时到底加载了哪些转换器:

    @EventListener
    public void on(ContextRefreshedEvent event) {
        RequestMappingHandlerAdapter requestMappingHandlerAdapter =     applicationContext.getBean(RequestMappingHandlerAdapter.class);
        List<?> messageConverters =     requestMappingHandlerAdapter.getMessageConverters();
        StringBuilder sb = new StringBuilder();
        sb.append("Spring共加载了").append(messageConverters.size()).append("个消息转换器对象:").append(messageConverters.toString());
        LOGGER.info(sb.toString());
    }

    上面的事件监听器方法将在Spring启动完毕后打印输出所有加载的转换器。你可做两个试验,一是自己不配置,二是自己配置,然后分别启动系统看看到底加载了哪些转换器。

    JSON

    如果系统加载了json转换器你就可以发送json消息了:

    curl -X POST -H 'Content-Type: application/json' -d '{"id":"01","name":"yw"}' http://localhost:8080/create-user

    如果调用不成功则很可能是系统并未加载json转换器。Spring MVC的默认配置只当存在jackson-databind时才加载json转换器。

    你可先检查是否存在jackson-databind依赖项:

    mvn dependency:tree | find "jackson-databind"

    若不存在则定义之:

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
    </dependency>

    这样Spring MVC将自动加载json转换器。

    除发送json消息外,你也可以接收json消息:

    curl http://localhost:8080/find-user
    {"id":"01","name":"yw"}

    XML

    同json一样,Spring MVC也是利用转换器来实现发送和接收xml消息。不同的是,Spring MVC只支持jackson-databind一种json转换器,但支持jaxb和jackson-databind-xml两种xml转换器,你可选择其一使用。

    要让Spring MVC自动配置jackson-databind-xml就需存在该依赖项。你可先检查是否存在该依赖项:

    mvn dependency:tree | find "jackson-databind-xml"

    若不存在则定义之:

    <dependency>
      <groupId>com.fasterxml.jackson.dataformat</groupId>
      <artifactId>jackson-dataformat-xml</artifactId>
    </dependency>

    接着你就可以传xml消息了:

    curl -X POST -H 'Content-Type: application/xml' -d '<root><id>01</id><name>yw</name></root>' http://localhost:8080/create-user

    强制数据格式

    如上,你的create-user方法既可接收xml消息,也可接收json消息,但有时你希望限制数据格式,此时可加consumes参数:

    @RequestMapping(value = "/xml-create-user", consumes = {MediaType.APPLICATION_XML_VALUE}, method = RequestMethod.POST)
    public void xmlCreateUser(@RequestBody User user) {
        LOGGER.debug("参数:user = {}", user);
    }

    上例表示只接收xml格式的消息。因此若你再发json消息则将失败。

    同样,你也可以限制返回值为xml:

    @RequestMapping(value = "/xml-find-user", method = RequestMethod.GET, produces = {MediaType.APPLICATION_XML_VALUE})
    @ResponseBody
    public User xmlFindUser() {
        return new User("02", "yw");
    }

    接着我们就可以接收xml消息了:

    curl http://localhost:8080/xml-find-user
    <User xmlns=""><id>02</id><name>yw</name></xml>

    Jackson XML

    上面说到,Spring MVC支持jackson-databind-xml作为xml转换器,并实际测试得到返回的xml:

    <User xmlns=""><id>01</id><name>yw</name></xml>

    其中有 xmlns="" 。该xmlns并无什么副作用,但如果你很在意一定要去掉它则可增加依赖项:

    <dependency>
      <groupId>com.fasterxml.woodstox</groupId>
      <artifactId>woodstox-core</artifactId>
      <version>5.0.2</version>
    </dependency>

    其原因请参见[FasterXML讨论](https://github.com/FasterXML/jackson-dataformat-xml/issues/32)。

    面向对象

    上面我们花了很多篇幅介绍了json和xml,但Spring MVC给我们带来的好处却在于让我们忽视它们的存在,让我们只关注对象,无需去考虑对象是从json来的还是从xml来的,这些底层的事就交给Spring MVC去处理吧。同时,直接把我们自己的对象作为参数和返回值也使得单元测试更容易写。

    练习

    1、如果你的系统同时有json和xml转换器,请解释为何用RestTemplate代码和curl工具调用同一个Spring MVC方法时时,一个返回的是xml,另一个返回的是json?

    @Test
    public void test() {
        RestTemplate restTemplate = new RestTemplate();
        String s = restTemplate.getForObject("http://localhost:8080/find-user", String.class);
        System.out.println(s);
        // <User xmlns=""><id>01</id><name>yw</name></xml>
    }
    curl http://localhost:8080/find-user
    {"id":"01","name":"yw"}

    2、本说明文档介绍了用Jackson-Xml作为Xml转换器,同时说到你也可以用jaxb进行Xml转换。请改为使用jaxb方式。

  • 相关阅读:
    转载:怎样用通俗的语言解释REST,以及RESTful?
    WiresShark 图解教程1
    派力奥 1.3 发动机
    EtherChannel Cisco 端口聚合详解
    Linux 排除问题的前5分钟
    Linux 定时任务crontab
    Linux SCP命令复制传输文件的用法
    Linux 挂载aliyun数据盘
    BCDedit 研究
    Bcdedit命令使用详解使用方法
  • 原文地址:https://www.cnblogs.com/yang-wu/p/5442804.html
Copyright © 2020-2023  润新知