说白了,这个接口就是想知道你(客户端)需要什么类型(MediaType)的数据。不是针对Content-Type的,因为没有解析charset。
/**
* 处理请求中的媒体类型的策略接口
*/
public interface ContentNegotiationStrategy {
/**
* 将给定的请求解析为媒体类型列表
* 返回的 List 首先按照 specificity 参数排序,其次按照 quality 参数排序
*
* webRequest: 当前的请求
* 返回请求的媒体类型或者是一个空的 List
* 如果请求的媒体类型不能被解析则抛出 HttpMediaTypeNotAcceptableException 异常
*/
List<MediaType> resolveMediaTypes(NativeWebRequest webRequest)
throws HttpMediaTypeNotAcceptableException;
}
SpringMVC 默认加载两个该接口的实现类:
ServletPathExtensionContentNegotiationStrategy–根据文件扩展名。
HeaderContentNegotiationStrategy–根据HTTP Header里的Accept字段。
HeaderContentNegotiationStrategy
负责解析Http Request Header
中的Accept
/**
* 检查请求头 Accept 的 ContentNegotiationStrategy 的实现类
*/
public class HeaderContentNegotiationStrategy implements ContentNegotiationStrategy {
/**
* 如果 Accept 请求头不能被解析则抛出 HttpMediaTypeNotAcceptableException 异常
*/
@Override
public List<MediaType> resolveMediaTypes(NativeWebRequest request)
throws HttpMediaTypeNotAcceptableException {
//获得请求头 Accept 的值
// 形如: "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
String[] headerValueArray = request.getHeaderValues(HttpHeaders.ACCEPT);
if (headerValueArray == null) {
return Collections.<MediaType>emptyList();
}
List<String> headerValues = Arrays.asList(headerValueArray);
try {
// 将上述媒体类型组成的字符串分离出来
List<MediaType> mediaTypes = MediaType.parseMediaTypes(headerValues);
// 将媒体类型排序
MediaType.sortBySpecificityAndQuality(mediaTypes);
return mediaTypes;
}
catch (InvalidMediaTypeException ex) {
throw new HttpMediaTypeNotAcceptableException(
"Could not parse 'Accept' header " + headerValues + ": " + ex.getMessage());
}
}
}
调用关系:
private final ContentNegotiationManager contentNegotiationManager;
contentNegotiationManager
保存了ContentNegotiationStrategy
的实现类
private final List<ContentNegotiationStrategy> strategies = new ArrayList<ContentNegotiationStrategy>();
同时也可以看到如果没有传递Accept,则默认使用MediaType.ALL
也就是*/*