栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring mvc 中的数据响应和内容协商

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring mvc 中的数据响应和内容协商

一、数据响应

spring mvc 中存在2中响应,一个是数据响应(常用于API开发),另一种是页面响应(常用于单体项目的开发)。

JSON的响应

spring boot 中只要引入了 web 启动器,就会自动的引入json的相关功能。在接口上标注@ResponseBody即可。

返回值解析器,一共15中:

 处理返回值:

  public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
        //寻找返回值处理器
        HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
        if (handler == null) {
            throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
        } else {
            handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
        }
    }

跟参数处理器一样,返回值处理器也是先判断是否支持,然后在调用返回值处理器进行处理。

 支持的返回值:

 返回值处理,利用MessageConverters进行处理:

	@Override
	public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

		mavContainer.setRequestHandled(true);
		ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
		ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

		// Try even with null return value. ResponseBodyAdvice could get involved.
		writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
	}

内容协商:

  • 请求方回根据自己的实际情况,告诉服务器端,需要什么类型的数据。 
  • 服务器根据自身能力,生成请求方需要的数据
  • 根据确定的数据类型,选择对应类型的消息转换器,消息转换器的作用就是是否支持将class类型的对象转换成MediaType类型的数据。
  • 默认的消息转换器,有以下几个:

最终使用MappingJackJon2HttpMessageConverter,转换成了json中。注意一点的是MappingJackJon2HttpMessageConverter是可以支持所有的返回值类型。

二、内容协商

内容协商就是客户端和服务端根据实际情况,约定双方需要的数据格式。也可能在某种情况下,相同的接口web端需要返回json而手机端需要返回xml,这个时候就可以用到spring mvc的内容协商。

根据客户端接收能力的不同,而返回不同媒体类型的数据。

也可以开启参数方式,参数中包含format=jsonxml 就可以返回不同的模式。当然也可以自定义MediaType,也就是重写 MessageConverter

spring:
  mvc:
    contentnegotiation:
      favor-parameter: true #开启请求参数内容协商模式 

接口端会根据 Accept 参数,进行判断返回格式 

  • application/json 返回json
  • application/xml 返回xml

如果同时定义了,就会根据权重进行判断,

Accept:

text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,* public class MgMessageConverter implements HttpMessageConverter { @Override public boolean canRead(Class clazz, MediaType mediaType) { return false; } @Override public boolean canWrite(Class clazz, MediaType mediaType) { return clazz.isAssignableFrom(Person.class); } @Override public List getSupportedMediaTypes() { return MediaType.parseMediaTypes("application/x-mg"); } @Override public Person read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { return null; } @Override public void write(Person person, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { String data = person.getName() + ";" + person.getSex() + ";" + person.getAge(); //数据写到流中 outputMessage.getBody().write(data.getBytes()); } }

客户端请求:

 

 跟踪源码可以看到,获取客户端的媒体类型为:

 服务器可以处理消息的Converter:

以上是使用请求头的方式,下面可以说一下使用参数方式。

因为参数协商策略只支持json和xml,所以就需要自定义策略:

自定义策略也十分的简单:

package com.example.demo.conf;

import com.example.demo.converter.MgMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.accept.ParameterContentNegotiationStrategy;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Configuration(proxyBeanMethods = false)
public class WebMvcConfig {

    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {

            
            @Override
            public void configureMessageConverters(List> converters) {
                //添加自定义的Converter
                converters.add(new MgMessageConverter());
            }

            
            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                //支持的媒体类型
                Map mediaTypes = new HashMap<>();
                mediaTypes.put("json", MediaType.APPLICATION_JSON);
                mediaTypes.put("xml", MediaType.APPLICATION_ATOM_XML);
                mediaTypes.put("mg", MediaType.parseMediaType("application/x-mg"));
                ParameterContentNegotiationStrategy parameterContentNegotiationStrategy = new ParameterContentNegotiationStrategy(mediaTypes);
                configurer.strategies(Arrays.asList(parameterContentNegotiationStrategy));
            }
        };
    }

}

跟踪代码可以看到,已经从原来的2中支持到现在的3中了: 

在自定义功能的时候,小心默认功能失效,这个时候需要dubeg源码,查看哪里出现问题,解决即可。 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/306194.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号