springBoot内容协商原理,追踪流程

将数据以xml的方式返回给浏览器,在参数解析器解析时涉及到内容协商。

@ResponseBody
    @RequestMapping("/test/person")
    public Person getPerson(){
        Person person = new Person();
        person.setAge(20);
        person.setBrith(new Date());
        person.setUserName("张三");
        return person;
    }

1. 开启请求参数协商模式,可以随时修改浏览器接受的参数类型,xml、json格式的数据

 spring:
 contentnegotiation:
      favor-parameter: true

 

2.得到请求参数的返回值

Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		setResponseStatus(webRequest);

 返回值的参数类型如图所示:

 3.调用返回值处理器对得到的参数值、请求进行处理

ry {
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}

4,查找哪一种返回值处理器能够处理@Reponse注解的处理器,去处理相应的请求

返回值处理器的类型总共有15种

5.调用RequestResponseBodyMethodProcessor中的方法进行处理

writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);

 6.内容协商处理时,首先获取到客户端(浏览器)的accept看浏览器能够处理哪些类型

List<MediaType> acceptableTypes = getAcceptableMediaTypes(request);

7.step Into进去,利用一个for循环,得到所有浏览器支持的类型。基本请求头的协商策略,确定客户端可以接受的内容类型。HeaderContentNegotiationStrategy.还有根据配置基于参数的内容协商策略

 

for (ContentNegotiationStrategy strategy : this.strategies) {
			List<MediaType> mediaTypes = strategy.resolveMediaTypes(request);
			if (mediaTypes.equals(MEDIA_TYPE_ALL_LIST)) {
				continue;
			}
			return mediaTypes;
		}
		return MEDIA_TYPE_ALL_LIST;
	}

 从accept获取数据

	String[] headerValueArray = request.getHeaderValues(HttpHeaders.ACCEPT);

mediaTypes的类型共有5种

 8.后台服务器所支持的类型

List<MediaType> producibleTypes = getProducibleMediaTypes(request, valueType, targetType);

判断哪些MessageConverters能够转换person类型,将结果封装到result结果集里边。

for (HttpMessageConverter<?> converter : this.messageConverters) {
				if (converter instanceof GenericHttpMessageConverter && targetType != null) {
					if (((GenericHttpMessageConverter<?>) converter).canWrite(targetType, valueClass, null)) {
						result.addAll(converter.getSupportedMediaTypes());
					}
				}
				else if (converter.canWrite(valueClass, null)) {
					result.addAll(converter.getSupportedMediaTypes());
				}

类型转换器如图共有11种,其中能够转换对象类型的有10种

 9.将浏览器能够处理的类型与后台所能处理的类型进行对比,找出最适合的类型转换

for (MediaType requestedType : acceptableTypes) {
				for (MediaType producibleType : producibleTypes) {
					if (requestedType.isCompatibleWith(producibleType)) {
						mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType));
					}
				}
			}

可用的媒体类型共有14种

 10.用消息转换器,将对象类型转换为xml/json类型的数据写入到响应体中

for (HttpMessageConverter<?> converter : this.messageConverters) {
				GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ?
						(GenericHttpMessageConverter<?>) converter : null);
				if (genericConverter != null ?
						((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) :
						converter.canWrite(valueType, selectedMediaType)) {
					body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,
							(Class<? extends HttpMessageConverter<?>>) converter.getClass(),
							inputMessage, outputMessage);
objectWriter.writeValue(generator, value);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值