Spring Boot:覆盖图标 [英] Spring Boot: Overriding favicon

查看:39
本文介绍了Spring Boot:覆盖图标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何覆盖 Spring Boot 的图标?

How can I override the favicon of Spring Boot?

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

NOTE: Here is my another question that provides another solution which does not involve any coding: Spring Boot: Is it possible to use external application.properties files in arbitrary directories with a fat jar? It's for application.properties, but it can also be applied to the favicon. In fact, I'm using that method for favicon overriding now.

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

If I implement a class that has @EnableWebMvc, WebMvcAutoConfiguration class of Spring Boot does not load, and I can serve my own favicon by placing it to the root directory of the static contents.

否则,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 主资源目录中的绿叶"图标.

Otherwise, WebMvcAutoConfiguration registers faviconRequestHandler bean, (see source https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java) and it serve the 'green leaf' icon which is placed in the Spring Boot's main resource directory.

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

How can I override it without implementing a class that has @EnableWebMvc myself, thus disabling whole default configuration functionality of WebMvcAutoConfiguration class of Spring Boot?

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

Also, since I want the icon file be updated as soon as possible on the client (web browser) side, I want to set the cache period of the favicon file to 0. (like the following code, which I'm using for my 'static' webapp content and script files which must be updated on the client side as soon as possible after I change the file.)

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

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

So, just to find the place to save the favicon.ico file that Spring Boot's faviconRequestHandler honors may not be sufficient.

更新

现在我知道我可以通过将图标文件放置到 src/main/resources 目录来覆盖默认的.但是缓存周期问题依然存在.
另外,favicon 文件最好放在放置静态网页文件的目录,而不是资源目录.

Now I know that I can override the default one by placing a favicon file to src/main/resources directory. But the cache period problem still remains.
Also, it is preferable to place the favicon file to the directory that static web files are placed, rather than the resource directory.

更新

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

Ok, I managed to override the default one. What I did is as follows:

@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) 添加一个具有最高顺序的资源处理程序来覆盖默认的.

Basically, I overrode the default one by adding a resource handler with the highest order by calling 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) 我的处理程序获胜.

Since the default one in Spring Boot has the order value (Integer.MIN_VALUE + 1), (see FaviconConfiguration class in https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java) my handler wins.

这样好吗?有没有其他方法(比我做的更温和)?

Is this Ok? Is there another way (something gentler than what I did)?

更新

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

It's not Ok. When I call registry.setOrder(Integer.MIN_VALUE), actually I raise the priority of all resource handlers. So, when I add following code to another WebMvcConfigurerAdapter, effectively all http request is directed to that resource handler, preventing any dynamic handling by Java code.

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

需要另一种解决方案.

更新

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

For now, I could not find the way to override the favicon functionality Spring Boot provides.
Maybe there is a way to add add my own HandlerMapping bean, but I don't know how to do it.

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

Now I can choose one of following options:

  1. 有一个具有 @EnableWebMvc 的类,从而禁用 Spring Boot WebMvcAutoConfiguration 类.(我可以复制WebMvcAutoConfiguration类的代码并删除favicon功能)
  2. 放弃将 favicon 文件放置到任意位置的自由,而将其放置在 Spring Boot 的 favicon 功能所需的资源目录中.并忽略缓存问题.
  1. Have a class that has @EnableWebMvc thus disabling Spring Boot WebMvcAutoConfiguration class. (I can copy the code of WebMvcAutoConfiguration class and delete the favicon functionality)
  2. Give up the freedom of placing favicon file to arbitary location and place it to the resource directory as Spring Boot's favicon functionality requires. And ignore caching problem.

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

But neither option is satisfactory.
I just want to place the favicon file with my static web files (which can be any directory since I can change the document root) and resolve the caching problem.
Am I missing something?
Any suggestion would be greatly appreciated.

更新

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

BTW, the reason I want to change the location of favicon and other static files is as follows. For now it is mainly the development environment issue.

我正在构建一个单页 Web 应用程序 (SPA).

I'm building a single page web application(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 子目录(实际上是 buildlibs)中的服务器应用程序和 bin 目录中的服务器应用程序访问.
    • 当我修改客户端代码时,它必须立即可供 Web 浏览器使用.因此浏览器不能无限期地缓存它,并且必须始终要求服务器更新.
    • 部署后,客户端代码必须是可修改的,而无需重新构建/重新启动服务器应用程序.所以客户端代码一定不能放到jar文件中.
    • To be able to modify and test my client code without rebuilding/restarting my Spring server application. So, the client code must not be put into the jar file. Anyways Spring Tool Suite does not build a jar file at all (at least for the current configuration)
    • To be able to test my Spring server application with the client code, easily switching between Spring Tool Suite output and gradle output. So, client code must be accessible from both the server application in build subdirectory (actually buildlibs) and the server application in bin directory.
    • When I modify the client code, it must be immediately available to the web browser. So browser must not cache it indefinitely, and must always ask for the server for update.
    • When deployed, client code must be modifiable without rebuilding/restarting the server application. So the client code must not be put into the jar file.

    关于缓存问题:

    在 addResourceHandlers() 上没有 setCachePeriod(0) 时,谷歌浏览器会无限期地缓存文件,而不会要求服务器进行更新.它甚至无法连接到服务器.(谷歌工程师说这种行为是正确的.)所以,我所能做的就是手动清除浏览器缓存.在开发环境中令人沮丧,在生产环境中令人无法接受.

    Without setCachePeriod(0) on addResourceHandlers(), Google Chrome caches the file indefinitely, without asking the server for updates. It does not even connect to the server. (Google engineers say that the behavior is correct.) So, all I can do is to manually clear the browser cache. It is frustrating on development environment, and unacceptable on production environment.

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

    BTW, express.js module on Node.js gives reasonable default HTTP header so that Google Chrome ask the server for updates. When I reviewed the HTTP headers that Spring and express.js produces using Fiddler, they were different.

    对于改善我的环境的任何建议将不胜感激.
    由于我是 Spring 初学者,所以我可能会遗漏一些东西.

    Any suggestion for improving my environment would be appreciated.
    Since I'm a Spring beginner, I may be missing something.

    更新

    我终于有了一个工作代码.如下:

    Finally I have a working code. It is as follows:

    @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() 中的代码所必需的.

    Notice the bean names. I have added 'my' to avoid name clash.
    Autowiring application context itself seems awkward, but it was neccessary for mimicking the code in org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration.addResourceLocations().

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

    Now I have a favicon handler free of caching problem, and I can place the favicon file anywhere I want.
    Thanks.

    推荐答案

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

    You can just put your own favicon.ico in the root of the classpath or in any of the static resource locations (e.g. classpath:/static). You can also disable favicon resolution completely with a single flag spring.mvc.favicon.enabled=false.

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

    Or to take complete control you can add a HandlerMapping (just copy the one from Boot and give it a higher priority), e.g.

    @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;
    }
    }
    

    这篇关于Spring Boot:覆盖图标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆