zoukankan      html  css  js  c++  java
  • 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方式。

  • 相关阅读:
    从句分析
    artDialog ( v 6.0.2 ) content 参数引入页面 html 内容
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 11 盛最多水的容器
    Java实现 LeetCode 11 盛最多水的容器
  • 原文地址:https://www.cnblogs.com/yang-wu/p/5442804.html
Copyright © 2011-2022 走看看