首页 文章

Spring Boot:覆盖图标

提问于
浏览
66

如何覆盖Spring Boot的图标?

注意:这是我的另一个问题,它提供了另一个不涉及任何编码的解决方案:Spring Boot:是否可以在胖jar的任意目录中使用外部application.properties文件?它适用于application.properties,但也可以应用于favicon . 事实上,我现在正在使用该方法进行favicon覆盖 .

如果我实现了一个具有@EnableWebMvc的类,则Spring Boot的WebMvcAutoConfiguration类不会加载,我可以通过将它放在静态内容的根目录中来提供我自己的favicon .

否则,WebMvcAutoConfiguration会注册faviconRequestHandler bean(请参阅source https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java),它会提供放置在Spring Boot主资源目录中的'green leaf'图标 .

如何在不实现自己拥有@EnableWebMvc的类的情况下覆盖它,从而禁用Spring Boot的WebMvcAutoConfiguration类的整个默认配置功能?

此外,由于我希望在客户端(Web浏览器)端尽快更新图标文件,我想将favicon文件的缓存周期设置为0.(如下面的代码,我用于我的'static'webapp内容和脚本文件,我必须在更改文件后尽快在客户端更新 . )

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

所以,只是找到保存favicon.ico文件的地方,Spring Boot的faviconRequestHandler荣誉可能还不够 .

UPDATE

现在我知道我可以通过将一个favicon文件放到src / main / resources目录来覆盖默认值 . 但缓存期问题仍然存在 .
此外,最好将favicon文件放在放置静态Web文件的目录中,而不是放在资源目录中 .

UPDATE

好的,我设法覆盖默认的一个 . 我做了如下:

@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/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java中的FaviconConfiguration类)我的处理程序获胜 .

这个可以吗?还有另一种方式(比我做的更温和)?

UPDATE

这不好 . 当我调用 registry.setOrder(Integer.MIN_VALUE) 时,实际上我提高了所有资源处理程序的优先级 . 因此,当我将以下代码添加到另一个 WebMvcConfigurerAdapter 时,实际上所有http请求都被定向到该资源处理程序,从而阻止了Java代码的任何动态处理 .

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

需要另一种解决方案 .

UPDATE

目前,我找不到覆盖Spring Boot提供的favicon功能的方法 .
也许有一种方法可以添加我自己的 HandlerMapping bean,但我不知道怎么做 .

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

  • 有一个具有 @EnableWebMvc 的类因此禁用Spring Boot WebMvcAutoConfiguration 类 . (我可以复制 WebMvcAutoConfiguration 类的代码并删除favicon功能)

  • 放弃将favicon文件放置到仲裁位置的自由,并将其放置到Spring Boot的favicon功能所需的资源目录中 . 并忽略缓存问题 .

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

UPDATE

顺便说一句,我想更改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工程师说行为是正确的 . )因此,我所能做的就是手动清除浏览器缓存 . 它对开发环境感到沮丧,对 生产环境 环境不可接受 .

BTW,Node.js上的express.js模块提供合理的默认HTTP标头,以便Google Chrome向服务器请求更新 . 当我查看Spring和express.js使用Fiddler生成的HTTP头时,它们是不同的 .

任何改善我的环境的建议都将受到赞赏 .
由于我是 Spring 季初学者,我可能会遗漏一些东西 .

UPDATE

最后我有一个工作代码 . 它如下:

@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文件放在我想要的任何地方 .
谢谢 .

6 回答

  • 43

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

    或者为了完全控制,你可以添加一个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;
    }
    }
    
  • 69

    这对我来说都不是必需的 .

    当您可以使用生成的JAR捆绑资源时,为什么要覆盖默认值,该JAR的优先级高于默认值 .

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

    执行上述操作可获得与上述更新解决方案相同的效果 .

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

  • 22

    我真的很喜欢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的更改以获得这些简单的功能 .

  • 2

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

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

  • 11

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

  • 1

    . registry.addResourceHandler( “/ robots.txt的”)addResourceLocations( “/”);

    . registry.addResourceHandler( “/的favicon.ico”)addResourceLocations( “/”);

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

    我用的是 Spring 季靴子1.2.1

相关问题