如何覆盖 Spring Boot 的 favicon?
注意:这是我的另一个问题,它提供了另一个不涉及任何编码的解决方案:Spring Boot: Is it possible to use external application.properties files in any directory with a fat jar? 它用于 application.properties,但也可以应用于 favicon。事实上,我现在正在使用这种方法来覆盖网站图标。
如果我实现一个具有@EnableWebMvc 的类,则Spring Boot 的WebMvcAutoConfiguration 类不会加载,我可以通过将其放置到静态内容的根目录来提供我自己的favicon。
否则,WebMvcAutoConfiguration 注册 faviconRequestHandler bean,(见源码https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ web/WebMvcAutoConfiguration.java),它提供了“绿叶”图标,该图标位于 Spring Boot 的主资源目录中。
如何在不自己实现具有 @EnableWebMvc 的类的情况下覆盖它,从而禁用 Spring Boot 的 WebMvcAutoConfiguration 类的整个默认配置功能?
另外,由于我希望在客户端(Web 浏览器)端尽快更新图标文件,因此我想将 favicon 文件的缓存周期设置为 0。(如下面的代码,我用于我的'静态' webapp 内容和脚本文件,在我更改文件后必须尽快在客户端更新。)
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/**")
.addResourceLocations("/")
.setCachePeriod(0);
}
所以,仅仅找到 Spring Boot 的 faviconRequestHandler 荣誉的 favicon.ico 文件的保存位置可能还不够。
更新
现在我知道我可以通过将 favicon 文件放置到 src/main/resources 目录来覆盖默认设置。但是缓存期问题仍然存在。
此外,最好将 favicon 文件放置到放置静态 Web 文件的目录,而不是资源目录。
更新
好的,我设法覆盖了默认值。我所做的如下:
@Configuration
public class WebMvcConfiguration
{
@Bean
public WebMvcConfigurerAdapter faviconWebMvcConfiguration()
{
return new FaviconWebMvcConfiguration();
}
public class FaviconWebMvcConfiguration extends WebMvcConfigurerAdapter
{
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.setOrder(Integer.MIN_VALUE);
registry.addResourceHandler("/favicon.ico")
.addResourceLocations("/")
.setCachePeriod(0);
}
}
}
基本上,我通过调用 registry.setOrder(Integer.MIN_VALUE) 添加具有最高顺序的资源处理程序来覆盖默认值。
由于 Spring Boot 中的默认值具有顺序值(Integer.MIN_VALUE + 1),(请参阅https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/中的 FaviconConfiguration 类src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java)我的处理程序获胜。
这个可以吗?还有另一种方法(比我做的更温和的方法)吗?
更新
这不好。当我调用时registry.setOrder(Integer.MIN_VALUE)
,实际上我提高了所有资源处理程序的优先级。因此,当我将以下代码添加到另一个WebMvcConfigurerAdapter
时,实际上所有 http 请求都被定向到该资源处理程序,从而防止 Java 代码进行任何动态处理。
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/**")
.addResourceLocations("/")
.setCachePeriod(0);
}
需要另一种解决方案。
更新
目前,我找不到覆盖 Spring Boot 提供的 favicon 功能的方法。
也许有一种方法可以添加我自己的HandlerMapping
bean,但我不知道该怎么做。
现在我可以选择以下选项之一:
- 有一个
@EnableWebMvc
因此禁用 Spring Boot类的WebMvcAutoConfiguration
类。(我可以复制WebMvcAutoConfiguration
类的代码并删除图标功能) - 放弃将 favicon 文件放置到任意位置的自由,并按照 Spring Boot 的 favicon 功能需要将其放置到资源目录中。并忽略缓存问题。
但这两种选择都不令人满意。
我只想将 favicon 文件与我的静态 Web 文件(可以是任何目录,因为我可以更改文档根目录)一起放置并解决缓存问题。
我错过了什么吗?
任何建议将不胜感激。
更新
顺便说一句,我想更改 favicon 和其他静态文件的位置的原因如下。目前主要是开发环境问题。
我正在构建一个单页 Web 应用程序(SPA)。
库/框架:
- 对于服务器端,我使用 Spring。(当然)
- 对于客户端(网络浏览器)端,我使用 AngularJS。
工具:
- 对于服务器端,我使用 Spring Tool Suite。
- 对于客户端,我使用 WebStorm。
主目录结构:
ProjectRoot\
src\
bin\
build\
webapp\
build.gradle
- src:我的 Spring java 源文件所在的位置。
- bin:Spring Tool Suite 放置其构建输出的位置。
- build: 'gradle build' 放置其构建输出的位置。
- webapp:我的客户端源文件(.js、.css、.htm 和 favicon)所在的位置。因此,这是 WebStorm 项目目录。(如有必要,我可以更改目录名称)
我想要的是:
- 为了能够修改和测试我的客户端代码,而无需重建/重新启动我的 Spring 服务器应用程序。因此,客户端代码一定不能放入 jar 文件中。无论如何,Spring Tool Suite 根本不构建 jar 文件(至少对于当前配置)
- 为了能够使用客户端代码测试我的 Spring 服务器应用程序,可以在 Spring Tool Suite 输出和 gradle 输出之间轻松切换。因此,客户端代码必须可以从
build
子目录中的服务器应用程序(实际上build\libs
)和服务器应用程序访问bin
目录中的服务器应用程序访问。 - 当我修改客户端代码时,它必须立即可供 Web 浏览器使用。因此浏览器不能无限期地缓存它,并且必须始终向服务器请求更新。
- 部署后,客户端代码必须是可修改的,而无需重新构建/重新启动服务器应用程序。所以客户端代码一定不能放到jar文件中。
关于缓存问题:
如果 addResourceHandlers() 上没有 setCachePeriod(0),Google Chrome 会无限期地缓存文件,而不要求服务器进行更新。它甚至不连接到服务器。(谷歌工程师说这种行为是正确的。)所以,我能做的就是手动清除浏览器缓存。它在开发环境中令人沮丧,在生产环境中是不可接受的。
顺便说一句,Node.js 上的 express.js 模块提供了合理的默认 HTTP 标头,以便 Google Chrome 向服务器请求更新。当我查看 Spring 和 express.js 使用 Fiddler 生成的 HTTP 标头时,它们是不同的。
任何改善我的环境的建议将不胜感激。
由于我是 Spring 初学者,因此我可能会遗漏一些东西。
更新
最后我有一个工作代码。如下:
@Configuration
public static class FaviconConfiguration
{
@Bean
public SimpleUrlHandlerMapping myFaviconHandlerMapping()
{
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(Integer.MIN_VALUE);
mapping.setUrlMap(Collections.singletonMap("/favicon.ico",
myFaviconRequestHandler()));
return mapping;
}
@Autowired
ApplicationContext applicationContext;
@Bean
protected ResourceHttpRequestHandler myFaviconRequestHandler()
{
ResourceHttpRequestHandler requestHandler =
new ResourceHttpRequestHandler();
requestHandler.setLocations(Arrays
.<Resource> asList(applicationContext.getResource("/")));
requestHandler.setCacheSeconds(0);
return requestHandler;
}
}
注意 bean 名称。我添加了“我的”以避免名称冲突。
自动装配应用程序上下文本身似乎很尴尬,但它是模仿代码的必要条件org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration.addResourceLocations()
.
现在我有一个没有缓存问题的网站图标处理程序,我可以将网站图标文件放在我想要的任何地方。
谢谢。