MIME 的主要作用是定义一种机制,允许发送和接收包括文本、图片、音频、视频等多种类型的数据格式。它在 HTTP 协议中也起到了重要作用,帮助 Web 服务器和客户端明确传递的内容类型。
MIME 类型(也称为媒体类型)是由两部分组成的字符串,用于标识传输数据的具体类型和格式。格式为 type/subtype,例如 text/html 表示 HTML 文档,image/jpeg 表示 JPEG 图像。
Http
请求中的 ContentType
和 Accept
关于这个的概念参考:Http请求中的Content-Type
Content-Type
是返回消息中非常重要的内容,表示后面的文档属于什么 MIME
类型。例如最常见的就是 text/html
,它的意思是说返回的内容是文本类型,这个文本又是 HTML
格式的。原则上浏览器会根据 Content-Type
来决定如何显示返回的消息体内容。
Accept
属于请求头,代表发送端(客户端)希望接受的数据类型。比如:Accept:text/xml
,代表客户端希望接受的数据类型是xml
类型Content-Type
属于实体头,代表发送端(客户端|服务器)发送的实体数据的数据类型。比如:Content-Type:text/html
,代表发送端发送的数据格式是html
比如一次 Http
请求中 Accept:text/xml
、Content-Type:text/html
,代表希望接受的数据类型是 xml
格式,本次请求发送的数据的数据格式是 html
Spring MVC
中的内容协商
参考 Spring MVC内置支持的4种内容协商方式【享学Spring MVC】
一个
URL
资源服务端可以以多种形式进行响应:即MIME(MediaType)
媒体类型。但对于某一个客户端(浏览器、APP
、Excel
导出…)来说它只需要一种。so
这样客户端和服务端就得有一种机制来保证这个事情,这种机制就是内容协商机制。
下面说一下 Spring MVC
中支持的几种内容协商方式,我们这里使用 SpringBoot
进行演示,首先创建一个 Spring Web
项目,增加一个接口:
1 |
|
这时我们在浏览器或 Postman
中请求这个接口,返回的 ContentType
是 application/json
,而我们如果在 pom.xml
加入下面的依赖:
1 | <!-- 此处需要导入databind包即可, jackson-annotations、jackson-core都不需要显示自己的导入了--> |
这时请求接口,返回的 ContentType
就是 application/xml
了。这是因为默认情况下 Spring MVC
并不支持 application/xml
这种媒体格式,而默认情况下 xml
的优先级高于 json
,所以增加了 xml
支持后,默认返回的媒体格式就是 application/xml
。而没有引入上面依赖时,不支持 appliction/xml
媒体格式,所以才轮到 json
的。
下面看下 Spring MVC
支持的几种内容协商方式:
- 在
Http
请求头Accept
中指定数据类型。 Http
请求的Url
增加拓展名,比如xxx.json
、xxx.xml
- 在请求参数中传递
xxx?format=xml
参数,需要用户手动开启配置1
2
3
4
5
6
7
8
9
public class WebMvcConfig extends WebMvcConfigurerAdapter {
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
// 支持请求参数协商
configurer.favorParameter(true);
}
} - 接口中固定媒体类型:指定
produces
按上面的方式改造后,即使引入了上面支持1
2
3
4
5
6
7
8
public User test() {
User user = new User();
user.setUserUid(UuidUtil.getUid());
user.setRealName("张三");
return user;
}xml
媒体类型的依赖,最终默认返回的仍然是application/json
。该方式有一个注意事项:**produces
指定的MediaType
类型不能和后缀、请求参数、Accept
冲突**。如果有冲突,那么接口就会出现报错提示。
源码解析
具体见:Spring MVC内容协商实现原理及自定义配置【享学Spring MVC】
继承树见上图,上面提到的4种协商方式对应的实现类分别是:
HeaderContentNegotiationStrategy
- 根据请求头Accept
完成内容协商ServletPathExtensionContentNegotiationStrategy
- 根据文件拓展名进行内容协商一个
MediaType
对应多个拓展名,一个拓展名只属于一个MediaType
ParameterContentNegotiationStrategy
- 根据url
中携带的请求参数(默认是format
)进行内容协商(注:Spring MVC
默认关闭,需要手动开启)FixedContentNegotiationStrategy
- 根据@RequestMapping.produces
这个注解属性进行内容协商