27.基于请求参数的内容协商原理

基于请求参数的内容协商原理
上面通过postman可以把数据又变成json,但是总有一个情况是又要json,又要xml,又要别的。这时不可能打开好几个软件发请求。

在上面的不设置就用,就是基于请求头转换结果数据。就也可以基于请求参数转换指定参数值的结果数据类型

结合之前的学习内容,上面的请求一路执行到找请求里面的accept内容【确定请求接受的转换类型】时,会有一个resolveMediaTypes方法,在这个方法里有这么一句

这一句就是那请求头里面的accept内容。基于请求头内容协商

String[] headerValueArray = request.getHeaderValues(HttpHeaders.ACCEPT);
在SpringBoot地层提供了一个配置项,他就是管理能不能通过参数的方式设置请求响应结果类型,默认是false关闭的。

在刚学springboot时就知道,可以用注解使类中的属性和配置文件中的指定前缀的配置绑定。所以我们点进去就会发现,这是一个set方法。

spring:
 mvc:
  contentnegotiation:
   favor-parameter: true
   
set方法
public void setFavorParameter(boolean favorParameter) {
            this.favorParameter = favorParameter;
        }
favorParameter值
#Whether a request parameter ("format" by default) should be used to determine the requested media type.
#上面自带的注释就说是如果想用参数形式的执行类型转换就加一个名为format的参数,参数值就是转换类型
private boolean favorParameter = false;
这样就能通过请求直接指定返回结果类型

http://localhost:8080/returnValue?format=json【返回结果】
在源码中

处理方法返回值的 writeWithMessageConverters 方法里,这里的内容协商从之前的只有一个Header模式,现在还加了一个Parameter模式。这是因为开启了参数内容协商,而且参数内容协商在请求头内容协商之前。

在writeWithMessageConverters 方法里确定请求要规定的响应数据格式这一步骤,

进入这一行

acceptableTypes = getAcceptableMediaTypes(request);
进入后,先看见,这个contentNegotiationManager就是内容协商,有两个,第一个是参数类型的,可以看见参数名是format,他也很明确的说了就支持两中参数值,一个是xml,一个是json。底下是参数值对应的转换类型。


在进入,这个方法是遍历内容协商数组,找到请求的要求的返回类型。

public List<MediaType> resolveMediaTypes(NativeWebRequest request) throws HttpMediaTypeNotAcceptableException {
   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;
}
进入后

public List<MediaType> resolveMediaTypes(NativeWebRequest webRequest)
      throws HttpMediaTypeNotAcceptableException {
//getMediaTypeKey(webRequest)这个方法会拿到参数值,resolveMediaTypeKey由这个方法转换参数值为对应的媒体类型
   return resolveMediaTypeKey(webRequest, getMediaTypeKey(webRequest));
}
进入后
...
    protected String getMediaTypeKey(NativeWebRequest request) {
        return request.getParameter(getParameterName());
    }
....
再来到
public List<MediaType> resolveMediaTypeKey(NativeWebRequest webRequest, @Nullable String key)
            throws HttpMediaTypeNotAcceptableException {
​
        if (StringUtils.hasText(key)) {
            //这一行就是把参数值转为媒体类型
            MediaType mediaType = lookupMediaType(key);
            if (mediaType != null) {
                handleMatch(key, mediaType);
                return Collections.singletonList(mediaType);
            }
            mediaType = handleNoMatch(webRequest, key);
            if (mediaType != null) {
                addMapping(key, mediaType);
                return Collections.singletonList(mediaType);
            }
        }
        return MEDIA_TYPE_ALL_LIST;
    }

最后一路执行,就完成了确定请求需要的数据格式。

这样就通过请求参数确定了返回数据的格式

posted @ 2022-08-08 13:35  随遇而安==  阅读(22)  评论(0编辑  收藏  举报