一尘不染

Spring Boot:覆盖图标

spring-boot

如果我实现的类具有@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类的整个默认配置功能?

另外,由于我希望在客户端(网络浏览器)上尽快更新图标文件,因此我希望将收藏图标的缓存周期设置为0。(例如以下代码,我将其用于更改文件后,必须尽快在客户端上更新“静态”
webapp内容和脚本文件。)

public void addResourceHandlers(ResourceHandlerRegistry registry)
{
    registry.addResourceHandler("/**")
        .addResourceLocations("/")
        .setCachePeriod(0);
}

因此,仅找到Spring Boot的faviconRequestHandler认可的favicon.ico文件的保存位置可能还不够。

更新

现在,我知道可以通过将图标图标放置到src / main / resources目录中来覆盖默认值。但是缓存期问题仍然存在。
另外,最好将收藏夹图标放置在放置静态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功能的方法。
也许有一种添加我自己的HandlerMappingbean的方法,但是我不知道该怎么做。

现在,我可以选择以下选项之一:

  1. 有一个@EnableWebMvc因此禁用了Spring Boot WebMvcAutoConfiguration类的类。(我可以复制WebMvcAutoConfiguration该类的代码并删除favicon功能)
  2. 放弃将favicon文件放置到任意位置的自由,并按照Spring Boot的favicon功能的要求将其放置到资源目录中。并忽略缓存问题。

但是,两种选择都不令人满意。
我只想将favicon文件与我的静态Web文件(可以更改目录的根目录,因为我可以更改文档根目录)一起放置并解决缓存问题。
我想念什么吗?
任何建议将不胜感激。

更新

顺便说一句,我要更改图标图标和其他静态文件的位置的原因如下。目前主要是开发环境问题。

我正在构建一个单页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浏览器要求服务器进行更新。当我回顾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()

现在,我有了一个没有缓存问题的favicon处理程序,并且可以将favicon文件放在我想要的任何位置。
谢谢。


阅读 406

收藏
2020-05-30

共1个答案

一尘不染

您可以将自己的favicon.ico放在类路径的根目录或任何静态资源位置(例如classpath:/static)中。您也可以使用单个标志完全禁用Favicon分辨率spring.mvc.favicon.enabled=false

或者,要完全控制,可以添加一个HandlerMapping(只需从Boot复制一个并赋予其更高的优先级),例如

@Configuration
public static class FaviconConfiguration {

@Bean
public SimpleUrlHandlerMapping faviconHandlerMapping() {
    SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
    mapping.setOrder(Integer.MIN_VALUE);
    mapping.setUrlMap(Collections.singletonMap("mylocation/favicon.ico",
            faviconRequestHandler()));
    return mapping;
}

@Bean
protected ResourceHttpRequestHandler faviconRequestHandler() {
    ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
    requestHandler.setLocations(Arrays
            .<Resource> asList(new ClassPathResource("/")));
    return requestHandler;
}
}
2020-05-30