`

SpringMVC中使用@RequestBody,@ResponseBody注解实现Java对象和XML/JSON数据自动转换(上)

阅读更多

        Spring3.1开始使用新的HandlerMapping 和 HandlerAdapter 来支持@Contoller 和@RequestMapping注解处理:处理器映射RequestMappingHandlerMapping和处理器适配器RequestMappingHandlerAdapter组合来代替Spring2.5 开始的处理器映射DefaultAnnotationHandlerMapping和处理器适配器AnnotationMethodHandlerAdapter。

        HandlerMapping:请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain 对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor 拦截器)对象;

        HandlerAdapter:HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器。

        配合@ResponseBody注解,以及HTTP Request Header中的Accept属性,Controller返回的Java对象可以自动被转换成对应的XML或者JSON数据。

        先看一个例子,只需要简单的几步,就可以返回XML数据(此例使用的Spring版本4.1.1)。

UserDTO.java

package com.bijian.study.controller.dto;

public class UserDTO {

    private String name;
    private int age;
    
    public UserDTO() {
        
    }
    
    public UserDTO(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "UserDTO [name=" + name + ", age=" + age + "]";
    }
}

UserDTOX.java

package com.bijian.study.controller.dto;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class UserDTOX extends UserDTO {
    
    public UserDTOX() {
        super();
    }
    
    public UserDTOX(String name, int age) {
        super(name, age);
    }
}

HelloController.java

package com.bijian.study.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.bijian.study.controller.dto.UserDTO;
import com.bijian.study.controller.dto.UserDTOX;

@Controller
public class HelloController {

    @ResponseBody
    @RequestMapping(value="/process")
    public UserDTO process(HttpServletRequest request) {
        
        return new UserDTOX("bijian", 18);
    }
}

        在Eclipse中启动Tomcat Server,然后在浏览器中访问:


        非常简单!Spring是怎么实现这个转换的呢?我们先了解下Spring的消息转换机制。

        在SpringMVC中,可以使用@RequestBody和@ResponseBody两个注解,分别完成请求报文到对象和对象到响应报文的转换,底层这种灵活的消息转换机制,就是Spring3.x中新引入的HttpMessageConverter即消息转换器机制。

        我们可以用下面的图,简单描述一下这个过程。

        这里最关键的就是<mvc:annotation-driven/>,加了这句配置,Spring会调用org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser来解析。

        在这个类的parse(Element, ParserContext)方法中,分别实例化了RequestMappingHandlerMapping,RequestMappingHandlerAdapter等诸多类。

        RequestMappingHandlerAdapter是请求处理的适配器,我们重点关注它的messageConverters属性。

        1).RequestMappingHandlerAdapter在调用handle()的时候,会委托给ServletInvocableHandlerMethod的invokeAndHandle()方法进行处理,这个方法又调用HandlerMethodReturnValueHandlerComposite类进行处理。

        HandlerMethodReturnValueHandlerComposite维护了一个HandlerMethodReturnValueHandler列表。

        由于我们使用了@ResponseBody注解,getReturnValueHandler就会返回RequestResponseBodyMethodProcessor的实例。


        2).之后RequestResponseBodyMethodProcessor.handleReturnValue()方法会被调用。此方法会调用AbstractMessageConverterMethodProcessor.writeWithMessageConverters()。它会根据request header中的Accept属性来选择合适的message converter。


        3).messageConverters中有如下的6个converter. 它们是从哪里来的呢?前面提到,AnnotationDrivenBeanDefinitionParser.parse(Element, ParserContext)方法中,分别实例化了RequestMappingHandlerMapping,RequestMappingHandlerAdapter以及messageConverters属性。

需要关注org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter这个类,就是它实现了返回对象到XML的转换。


        4).看一下getMessageConverters()中的处理。有5个message converter是一定会加进来的。


        然后再看,这里jaxb2Present为true, 因此Jaxb2RootElementHttpMessageConverter被添加到messageConverters中。

if (convertersElement == null || Boolean.valueOf(convertersElement.getAttribute("register-defaults"))) {
	messageConverters.setSource(source);
	messageConverters.add(createConverterDefinition(ByteArrayHttpMessageConverter.class, source));

	RootBeanDefinition stringConverterDef = createConverterDefinition(StringHttpMessageConverter.class, source);
	stringConverterDef.getPropertyValues().add("writeAcceptCharset", false);
	messageConverters.add(stringConverterDef);

	messageConverters.add(createConverterDefinition(ResourceHttpMessageConverter.class, source));
	messageConverters.add(createConverterDefinition(SourceHttpMessageConverter.class, source));
	messageConverters.add(createConverterDefinition(AllEncompassingFormHttpMessageConverter.class, source));

	if (romePresent) {
		messageConverters.add(createConverterDefinition(AtomFeedHttpMessageConverter.class, source));
		messageConverters.add(createConverterDefinition(RssChannelHttpMessageConverter.class, source));
	}

	if (jackson2XmlPresent) {
		messageConverters.add(createConverterDefinition(MappingJackson2XmlHttpMessageConverter.class, source));
	}
	else if (jaxb2Present) {
		messageConverters.add(createConverterDefinition(Jaxb2RootElementHttpMessageConverter.class, source));
	}

	if (jackson2Present) {
		messageConverters.add(createConverterDefinition(MappingJackson2HttpMessageConverter.class, source));
	}
	else if (gsonPresent) {
		messageConverters.add(createConverterDefinition(GsonHttpMessageConverter.class, source));
	}
}

        5).看一下jaxb2Present的定义,原来javax.xml.bind.Binder这个类是JDK中包含的类,所以jaxb2Present=true。

        6).我们看一下Jaxb2RootElementHttpMessageConverter的canWrite()方法。返回true的条件有两个

        a).返回对象的类具有XmlRootElement注解;

        b).请求头中的Accept属性包含application/xml。


        7).在chrome中打开开发者工具,可以看到请求头中确实包含了Accept=application/xml

        接下来我们看看如果想要返回JSON数据,应该怎么做?

        根据上面的分析,首先我们需要添加一个支持JSON的message converter。前面分析getMessageConverters()代码的时候,看到

if (jackson2Present) {
	messageConverters.add(createConverterDefinition(MappingJackson2HttpMessageConverter.class, source));
}
else if (gsonPresent) {
	messageConverters.add(createConverterDefinition(GsonHttpMessageConverter.class, source));
}

        然后再来看看jackson2Present和gsonPresent的定义。

private static final boolean jackson2Present =
	ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", AnnotationDrivenBeanDefinitionParser.class.getClassLoader()) &&
			ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
private static final boolean gsonPresent =
	ClassUtils.isPresent("com.google.gson.Gson", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());

        所以我们只要把Jackson2或者GSON加入工程的class path,Spring就会自动把GsonHttpMessageConverter加进来。

        并在HelloController.java中添加getEmployeeJson()方法

@ResponseBody
@RequestMapping(value="/process2")
public UserDTO process2(HttpServletRequest request) {
	
	return new UserDTO("bijian", 18);
}

        和process()相比,这里唯一的不同是返回对象变成了UserDTO,因为UserDTO类上没有@XmlRootElement注解,所以Spring不会选择Jaxb2RootElementHttpMessageConverter。又因为Accept属性中包含了*/*,表示接受任意格式返回数据,所以GsonHttpMessageConverter的canWrite()方法返回true.这样Spring就会选择MappingJackson2HttpMessageConverter或者GsonHttpMessageConverter来进行数据转换。


        至此,我们知道请求头中的Accept属性是一个很关键的东西,我们可以根据这个在Controller中写一个方法,根据Accept的值自动返回XML或者JSON数据。

@ResponseBody
@RequestMapping(value="/process")
public UserDTO process(HttpServletRequest request) {
	
	return new UserDTOX("bijian", 18);
}

        因为浏览器的Accept值不方便修改,我们自己写客户端来调用。

package com.bijian.study.controller.test;

import java.io.IOException;
import java.net.URISyntaxException;

import org.junit.Test;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.client.RestTemplate;

public class XmlOrJasonControllerTest {

    @Test
    public void testJsonResponse() throws IOException, URISyntaxException {
        
        String url = "http://localhost:8080/SpringMVC/process";
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.set("Accept", "application/json");
        
        RestTemplate restTemplate = new RestTemplate();
        HttpEntity<Object> httpEntity = new HttpEntity<Object>(requestHeaders);
        String jsonData = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class).getBody();
        
        System.out.println(jsonData);
    }

    @Test
    public void testXmlResponse() throws IOException, URISyntaxException {
        
        String url = "http://localhost:8080/SpringMVC/process";
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.set("Accept", "application/xml");

        RestTemplate restTemplate = new RestTemplate();
        HttpEntity<Object> httpEntity = new HttpEntity<Object>(requestHeaders);
        String xmlData = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class).getBody();

        System.out.println(xmlData);
    }
}

 

文章来源:http://blog.csdn.net/fw0124/article/details/48280083

  • 大小: 11.7 KB
  • 大小: 26.7 KB
  • 大小: 75.6 KB
  • 大小: 70.5 KB
  • 大小: 86.1 KB
  • 大小: 51.8 KB
  • 大小: 39.6 KB
  • 大小: 10.1 KB
  • 大小: 38.3 KB
  • 大小: 63.4 KB
  • 大小: 46.5 KB
分享到:
评论

相关推荐

    SpringMVC中使用@RequestBody,@ResponseBody注解实现Java对象和XML/JSON数据自动转换(下)

    本篇文章将详细解释这两个注解的工作原理、使用场景以及如何实现Java对象与XML/JSON数据的自动转换。 ### 1. @RequestBody 注解 `@RequestBody` 用于方法参数前,表示该参数将会从HTTP请求的主体(通常为POST或PUT...

    springMvc注解之@ResponseBody和@RequestBody详解

    例如,在控制器中,我们可以使用@ResponseBody注解来将方法的返回值序列化为JSON格式。 ```java @RequestMapping("/testResponseBody") @ResponseBody public String testResponseBody() { return "Hello, World!";...

    SpringMVC restful 注解之@RequestBody进行json与object转换

    在Spring MVC中,`@RequestBody`注解是用于将HTTP请求体中的数据转换为Java对象的,特别适用于处理JSON或XML格式的数据。当控制器方法接收POST、PUT等带有请求体的HTTP请求时,`@RequestBody`可以帮助我们将接收到的...

    springMVC的 RequestBody和 ResponseBody和RequestParam.docx

    在 Spring MVC 中,请求参数的处理非常灵活,可以使用 `@RequestParam`、`@RequestBody` 和 `@ResponseBody` 等注解进行数据绑定和响应体的控制。 #### 二、`@RequestBody` `@RequestBody` 注解通常用于控制器中的...

    springmvc对json支持

    总结起来,Spring MVC对JSON的支持主要依赖于Jackson库,通过`@ResponseBody`和`@RequestBody`注解实现数据交换,配合注解进行类型转换控制,同时允许开发者自定义序列化和反序列化行为,以及配置错误处理机制。...

    springMVC json格式转换demo

    在Spring MVC中,为了将对象转换为JSON,我们需要使用`@RequestBody`和`@ResponseBody`注解。`@RequestBody`用于将HTTP请求体中的JSON数据转换为Java对象,而`@ResponseBody`则将Java对象转换为HTTP响应体的JSON数据...

    SpringMVC中Json数据格式转换

    当服务器接收到这个请求后,通过@RequestBody注解自动将JSON数据转换为Items对象,并在返回时,通过@ResponseBody注解将对象转换为JSON格式的响应。 为了保证知识点的准确性和完整性,需要注意的是,文档中提到的...

    SpringMVC中使用JSON传递数据时用的jar包

    3. **JSON序列化与反序列化**:在Spring MVC中,你可以通过使用`@RequestBody`和`@ResponseBody`注解来实现JSON数据的传递。`@RequestBody`用于将HTTP请求体中的JSON数据转换为Java对象,而`@ResponseBody`则将方法...

    SpringMVC JSON格式的读取和显示

    `@RequestBody`和`@ResponseBody`使得JSON数据与Java对象之间的转换变得简单,而Jackson库提供了丰富的功能来满足各种序列化需求。通过理解这些核心概念和实践,你就能在Spring MVC中有效地处理JSON格式的读取和显示...

    SpringMVC中解决@ResponseBody注解返回中文乱码问题

    在SpringMVC框架中,`@ResponseBody`注解用于将方法的返回值直接转换为HTTP响应体,通常用于处理JSON或XML格式的数据。然而,当返回的字符串中包含中文字符时,如果没有正确设置编码,就可能导致乱码问题。本文将...

    springmvc-json-lib.rar

    在SpringMVC中,我们可以使用Jackson的`@ResponseBody`注解,将控制器方法的返回值自动转换为JSON格式。同时,通过`@RequestBody`注解,我们可以将HTTP请求体中的JSON数据自动映射到方法参数中。 配置Jackson库需要...

    springMVC+json.zip_JSON_myeclipse_springmvc_数据传递

    - Controller方法接收参数,SpringMVC会自动将JSON数据转化为Java对象,通过`@RequestBody`注解注入到方法参数中。 - Controller处理业务逻辑后,可能需要返回JSON数据。通过`@ResponseBody`注解,SpringMVC会调用...

    Springmvc 4.x利用@ResponseBody返回Json数据的方法

    实际开发中,常常需要返回一个对象,这时Spring MVC会自动使用配置好的消息转换器来将Java对象序列化为JSON字符串,然后返回给客户端。 ### 控制器层与前端交互示例 ```java @RequestMapping("House/ClassManager/...

    SpringMVC环境搭建

    本教程将指导你如何搭建一个非Maven的SpringMVC项目,主要关注@RequestBody和@ResponseBody的配置。 首先,让我们了解SpringMVC的基本结构。一个标准的SpringMVC项目通常包含以下几个关键部分: 1. **src目录**:...

    springMVC+ajax+json

    然后,使用@RequestBody或@ResponseBody注解将HTTP请求体或响应体绑定到JSON对象。 例如,一个简单的Ajax请求可能如下: ```javascript $.ajax({ url: '/api/data', type: 'GET', dataType: 'json', success: ...

    SpringMVC框架中传递JSON数据时前台报406错误解决办法

    在这个例子中,`@ResponseBody`注解告诉Spring MVC将方法返回的对象转换为JSON,`produces = "application/json"`则设置了Content-Type。 如果以上步骤都已完成,但仍遇到406错误,可能的原因包括但不限于:前端...

    完整版 Java开发实训课程系列-SpringMVC框架技术教程 第7章 文件上传和json数据交互 (共30页).pptx

    在Controller中,使用`@RequestBody`将JSON字符串转换为Java对象,`@ResponseBody`将Java对象转换为JSON响应。 本课程通过实际的代码示例和项目实践,帮助学习者掌握如何在SpringMVC中实现文件上传和JSON数据交互,...

    springmvc加入json支持需要的jar包

    3. **使用注解**:在控制器方法上使用`@RequestBody`和`@ResponseBody`注解来处理JSON请求和响应。`@RequestBody`用于将JSON请求体转换为Java对象,而`@ResponseBody`则将方法的返回值转换为JSON响应。 4. **测试**...

    SpringMVC例子注解

    它可以将JSON或XML数据转换为Java对象。 7. `@ResponseBody`: 标记在方法返回值上,表示该方法的返回结果应该直接写入HTTP响应体,而不是作为一个视图解析。这常用于返回JSON或XML数据。 8. `@Autowired`: Spring...

Global site tag (gtag.js) - Google Analytics