85

如何覆盖 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 功能的方法。
也许有一种方法可以添加我自己的HandlerMappingbean,但我不知道该怎么做。

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

  1. 有一个@EnableWebMvc因此禁用 Spring Boot类的WebMvcAutoConfiguration类。(我可以复制WebMvcAutoConfiguration类的代码并删除图标功能)
  2. 放弃将 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().

现在我有一个没有缓存问题的网站图标处理程序,我可以将网站图标文件放在我想要的任何地方。
谢谢。

4

8 回答 8

75

这些对我来说都不是必需的。

当您可以将资源与生成的 JAR 捆绑在一起时,为什么要覆盖默认值,该 JAR 的优先级高于默认值。

为了实现自定义favicon.ico文件,我src/main/resources为我的应用程序创建了一个目录,然后将favicon.ico文件复制到那里。此资源目录中的文件被移动到已编译 JAR 的根目录,因此您的自定义favicon.ico在 Spring 提供之前找到。

执行上述操作可以达到与上面更新的解决方案相同的效果。

请注意,从 v1.2.0 开始,您还可以将文件放入src/main/resources/static.

于 2013-12-30T06:53:02.323 回答
54

您可以将自己的 favicon.ico 放在类路径的根目录或任何静态资源位置(例如classpath:/static)。您还可以使用单个标志完全禁用网站图标解析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;
}
}
于 2013-12-19T12:36:01.770 回答
29

我真的很喜欢 Springboot,因为总的来说它充满了智能解决方案,但我拒绝注册一个应用程序 bean 来提供一个 favicon,因为这简直是愚蠢的。

我只是像这样在我的 html 页面头中添加了我自己的 favicon 链接。

<link rel="icon" type="image/png" href="images/fav.png">

然后我重命名了我的网站图标并将其放置在

<ProjFolder>/src/main/resources/static/images/fav.png

现在,我在 Chrome 和 Firefox 浏览器选项卡和 Safari 地址栏中有了一个图标,而无需使用 Spring 和 Java,而且我不应该为了这些琐碎的功能而在较新版本中追逐 Springboot 的更改。

于 2014-10-13T23:56:34.127 回答
14

spring.mvc.favicon.enabled = false从 Spring Boot 1.2.2 和 1.1.11 开始,您可以使用属性轻松禁用默认图标。

欲了解更多信息,请访问:

spring.mvc.favicon.enabled更新:自 Spring Boot 2.2.x 以来不再有属性

于 2015-02-28T17:47:06.537 回答
2

较新版本的 Boot(肯定是 1.2,但也可能是 1.1.8)允许您将 favicon.ico 放在静态资源中。

于 2014-12-05T13:13:49.793 回答
2

我尝试了很多选项/变体,但只有这个有效。(Spring Boot 2.2.7)

Favicon.ico文件和robots.txt放入/resources/static

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
  protected void configure(HttpSecurity http) throws Exception { 
    http
      .authorizeRequests()
        .antMatchers("/favicon.ico").permitAll()
        .antMatchers("/robots.txt").permitAll()
        .antMatchers("/").permitAll()
        .anyRequest().authenticated();
    }
}

@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
@Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler(
      "/favicon.ico",
      "/robots.txt")
      .addResourceLocations(
        "classpath:/static/");
  }
}

如果有帮助,请点赞;)

于 2020-05-21T08:18:48.123 回答
1

registry.addResourceHandler("/robots.txt").addResourceLocations("/");

registry.addResourceHandler("/favicon.ico").addResourceLocations("/");

robots.txt、favicon.ico 文件位置:/src/main/resources

我用的是弹簧靴 1.2.1

于 2015-03-19T11:35:27.167 回答
1

我正在使用 Spring Boot 2.5.2 版。就我而言,我只需要一个jpg/png 文件作为 favicon,而不是 favicon.ico 文件

将您的 favicon.jpg/favicon.png 文件放在类路径中的资源文件夹中- src/main/resources/favicon.png
或放在类路径中资源文件夹中的静态文件夹中-在资源文件夹中模板文件夹
src/main/resources/static/favicon.png

中的 每个HTML 页面中,放置 -或 放在头标签分别。
<link rel="icon" type="image/png" href="../favicon.png">

<link rel="icon" type="image/png" href="../static/favicon.png">

于 2021-08-07T12:43:39.923 回答