问题描述
项目中需要访问静态资源文件xxx.ccxml
,这个文件不属于标准的文件格式。浏览器访问时,默认下载该文件。我们是期望可以直接在页面上查看的。
背景知识
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
详情可参考MIME 参考文档
解决方案
我们注册关于ccxml
扩展类型的默认打开方式即可。
一般情况下,在tomcat
目录下的conf/web.xml
修改或新增
1 | <mime-mapping> |
针对于SpringBoot
的内置容器,提供了接口以供修改
Spring Boot 1:
1 |
|
Spring Boot 2:
1 |
|
Spring 加载静态资源的mime
源码分析
针对SpringBoot2
,一般我们使用的是tomcat
容器,我们自定义的加载mimeType
的类注入了ConfigurableServletWebServerFactory
实现类中TomcatServletWebServerFactory
,其方法configureContext
将自定义的mimeType
存储到集合中 节选片段
1 | for (MimeMappings.Mapping mapping : getMimeMappings()) { |
StandardContext
1 |
|
根据spring静态资源加载源码浅析中的分析,找到ResourceHttpRequestHandler
,实际执行方法handleRequest
节选代码片段
1 | MediaType mediaType = getMediaType(request, resource); |
我们先看下MediaType
的加载,
1 | protected MediaType getMediaType(HttpServletRequest request, Resource resource) { |
this.contentNegotiationStrategy
有方法initContentNegotiationStrategy
来加载
1 | protected PathExtensionContentNegotiationStrategy initContentNegotiationStrategy() { |
我们追踪PathExtensionContentNegotiationStrategy
的getMediaTypeForResource
方法中
1 | public MediaType getMediaTypeForResource(Resource resource) { |
那么我们看下具体的servletContext.getMimeType
实现,针对SpringBoot2
,一般我们使用的是tomcat
容器, 我们可定位到ApplicationContext
1 |
|
最后可以看到response
的ContentType
和mediaType
息息相关。
1 | protected void setHeaders(HttpServletResponse response, Resource resource, @Nullable MediaType mediaType) |