提示:这是我的另一个问题,提供了另一种解决方案,不涉及任何编码: Spring Boot:是否可以在fat jar中的任意目录中使用外部application.properties文件?它是针对application.properties的,但也适用于网站图标。事实上,我现在正在使用这种方法来覆盖网站图标。
如果我实现了一个带有@EnableWebMvc注释的类,则Spring Boot的WebMvcAutoConfiguration类不会加载,并且我可以通过将其放置在静态内容的根目录中来提供自己的网站图标。
否则,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。(就像下面的代码一样,我正在使用它来更新必须在我更改文件后尽快在客户端上更新的“静态”Web应用程序内容和脚本文件。)
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/**")
.addResourceLocations("/")
.setCachePeriod(0);
}
因此,仅仅找到保存Spring Boot的faviconRequestHandler所需的favicon.ico文件的位置可能不足。
更新
现在我知道可以通过将favicon文件放置在src/main/resources目录中来覆盖默认值。但缓存期问题仍然存在。
此外,最好将favicon文件放置在静态网页文件所在的目录中,而不是资源目录。
更新
好的,我成功地覆盖了默认值。 我的做法如下:
@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中的默认处理程序具有order值(Integer.MIN_VALUE +1),(请参见https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java中的FaviconConfiguration类),因此我的处理程序胜出。
这样可以吗? 是否还有其他方式(比我所做的温和一些)?
更新
不行。
当我调用registry.setOrder(Integer.MIN_VALUE)
时,实际上我提高了所有资源处理程序的优先级。 因此,当我将以下代码添加到另一个WebMvcConfigurerAdapter
中时,所有http请求实际上都会被重定向到该资源处理程序,从而防止任何动态Java代码处理。
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/**")
.addResourceLocations("/")
.setCachePeriod(0);
}
需要另一个解决方案。
更新
目前,我找不到覆盖Spring Boot提供的favicon功能的方法。也许有一种方法可以添加自己的HandlerMapping bean,但我不知道该怎么做。
现在我可以选择以下选项之一:
1.拥有一个类,其中包含@EnableWebMvc,从而禁用Spring Boot的WebMvcAutoConfiguration类。(我可以复制WebMvcAutoConfiguration类的代码并删除favicon功能) 2.放弃将favicon文件放置在任意位置的自由,并将其放置在资源目录中,因为Spring Boot的favicon功能需要。并忽略缓存问题。
但是,这两个选项都不令人满意。我只想将favicon文件与我的静态网页文件放在一起(可以是任何目录,因为我可以更改文档根目录)并解决缓存问题。我错过了什么吗?任何建议将不胜感激。
更新
顺便说一下,我想更改favicon和其他静态文件的位置的原因如下。目前主要是开发环境问题。
我正在构建一个单页Web应用程序(SPA)。
库/框架:
- 服务器端,我使用Spring。(当然) - 客户端(Web浏览器)端,我使用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会无限期缓存该文件,而不会向服务器请求更新。它甚至不连接到服务器。(Google工程师表示这种行为是正确的。)因此,我所能做的就是手动清除浏览器缓存。这在开发环境中很令人沮丧,在生产环境中则是不可接受的。
顺便提一下,Node.js上的express.js模块会给出合理的默认HTTP头,以便Google Chrome请求服务器进行更新。当我使用Fiddler查看Spring和express.js生成的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的名称。我已经加上了“my”以避免名称冲突。
自动装配应用程序上下文本身似乎很尴尬,但这是模仿
org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration.addResourceLocations()
中的代码所必需的。现在我有一个无缓存问题的favicon处理程序,我可以将favicon文件放在任何地方。
谢谢。
classpath:/static
中提供)。(这就是为什么Boot中的favicon支持在自己的HandlerMapping中的原因,我想。) - Dave SyerHandlerMapping
吗? - zeodtrHandlerMapping
(只需复制Boot中的一个并赋予更高的优先级)。我不太确定您为什么关心favicon.ico文件
的位置,但如果您愿意,我们可以使其可配置。所有浏览器都会将其缓存,因此我认为缓存设置并不重要,但很乐意被证明是错误的。 - Dave Syer