SpringMVC处理JSON

本文介绍了如何在SpringMVC中处理JSON数据,包括配置、实现步骤及原理。重点讲解了HttpMessageConverter的作用及其匹配过程,并展示了如何通过注解实现JSON数据的发送与接收。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、具体实现

1、加入jar包

2、编写目标方法,使其返回JSON对应的对象或集合

3、在编写的方法上面添加@ResponseBody注解

@Controller
public class testJson {

	@ResponseBody
	@RequestMapping("/testJson")
	public List<Department> testJson() {

		List<Department> list = new ArrayList<>();
		Department department1 = new Department(1, "GL");
		Department department2 = new Department(2, "LG");
		list.add(department1);
		list.add(department2);
		return list;
	}
}

这样我们就可以返回一个JSON数组。

二、原理

SpringMVC在处理JSON数据时,需要使用HttpMessageConverter接口,其是Spring3.0新添加的接口,主要负责将请求信息转换为一个Java对象(类型为 T),或将Java对象(类型为 T)输出为响应信息。 
  HttpMessageConverter的基本流程如下图所示: 

HttpMessageConverter的实现类主要有:

DispatcherServlet默认装配有ReuqestMappingHandlerAdapter

而ReuqestMappingHandlerAdapter默认装配的HttpMessageConverter如下: 

加入Jackson所需要的jar包后,RequestMappingHandlerAdapter装配的HttpMessageConverter如下:

由此可见,在加入Jackson所需要的jar包后,SpringMVC会自动将MappingJackson2HttpMessageConverter装配上,以实现对JSON数据的处理。

三、HttpMessageConverter

使用HttpMessageConverter<T>将请求信息转化并绑定到处理方法的入参中或将响应结果转化为对应类型的响应信息,SpringMVC提供了两种途径: 
  ①. 使用@RequestBody标注处理方法的入参或使用@ResponseBody标注处理方法; 
  ②. 使用HttpEntity<T>作为处理方法的入参或使用ResponseEntity<T>作为处理方法的返回值。 

  1. @Responsebody 注解表示该方法的返回的结果直接写入 HTTP 响应正文(ResponseBody)中,一般在异步获取数据时使用;
  2. 在使用 @RequestMapping 后,返回值通常解析为跳转路径,加上 @Responsebody 后返回结果不会被解析为跳转路径,而是直接写入HTTP 响应正文中。例如,异步获取 json 数据,加上 @Responsebody 注解后,就会直接返回 json 数据。
  3. @RequestBody 注解则是将 HTTP 请求正文插入方法中,使用适合的 HttpMessageConverter 将请求体写入某个对象。

那么HttpMessageConverter的匹配过程是什么样的呢?

@RequestBody注解时: 根据Request对象header部分的Content-Type类型,逐一匹配合适的HttpMessageConverter来读取数据。

spring 3.1源代码如下:

private Object readWithMessageConverters(MethodParameter methodParam, HttpInputMessage inputMessage, Class paramType) throws Exception {  

    MediaType contentType = inputMessage.getHeaders().getContentType();  
    if (contentType == null) {  
        StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));  
        String paramName = methodParam.getParameterName();  
        if (paramName != null) {  
            builder.append(' ');  
            builder.append(paramName);  
        }  
        throw new HttpMediaTypeNotSupportedException("Cannot extract parameter (" + builder.toString() + "): no Content-Type found");  
    }  

    List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();  
    if (this.messageConverters != null) {  
        for (HttpMessageConverter<?> messageConverter : this.messageConverters) {  
            allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());  
            if (messageConverter.canRead(paramType, contentType)) {  
                if (logger.isDebugEnabled()) {  
                    logger.debug("Reading [" + paramType.getName() + "] as \"" + contentType  + "\" using [" + messageConverter + "]");  
                }  
                return messageConverter.read(paramType, inputMessage);  
            }  
        }  
    }  
    throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);  
}

@ResponseBody注解时:根据Request对象header部分的Accept属性(逗号分隔),逐一按accept中的类型,去遍历找到能处理的HttpMessageConverter。

spring 3.1 源代码如下:

private void writeWithMessageConverters(Object returnValue,  HttpInputMessage inputMessage, HttpOutputMessage outputMessage)  
                throws IOException, HttpMediaTypeNotAcceptableException {  
    List<MediaType> acceptedMediaTypes = inputMessage.getHeaders().getAccept();  
    if (acceptedMediaTypes.isEmpty()) {  
        acceptedMediaTypes = Collections.singletonList(MediaType.ALL);  
    }  
    MediaType.sortByQualityValue(acceptedMediaTypes);  
    Class<?> returnValueType = returnValue.getClass();  
    List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();  
    if (getMessageConverters() != null) {  
        for (MediaType acceptedMediaType : acceptedMediaTypes) {  
            for (HttpMessageConverter messageConverter : getMessageConverters()) {  
                if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {  
                    messageConverter.write(returnValue, acceptedMediaType, outputMessage);  
                    if (logger.isDebugEnabled()) {  
                        MediaType contentType = outputMessage.getHeaders().getContentType();  
                        if (contentType == null) {  
                            contentType = acceptedMediaType;  
                        }  
                        logger.debug("Written [" + returnValue + "] as \"" + contentType +  
                                "\" using [" + messageConverter + "]");  
                    }  
                    this.responseArgumentUsed = true;  
                    return;  
                }  
            }  
        }  
        for (HttpMessageConverter messageConverter : messageConverters) {  
            allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());  
        }  
    }  
    throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);  
}

 

 

 

转载于:https://my.oschina.net/lin546/blog/1786621

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值