春季启动:覆盖图标 [英] Spring Boot: Overriding favicon

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

问题描述

如何覆盖Spring Boot的图标?

How can I override the favicon of Spring Boot?

注意:这是我的另一个问题,提供了另一个不涉及任何编码的解决方案:

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类,并且可以通过将其放置在静态内容的根目录中来提供自己的收藏夹图标.

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,(请参见源

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?

此外,由于我希望在客户端(网络浏览器)上尽快更新图标文件,因此我想将收藏图标的缓存周期设置为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文件放置在放置静态Web文件的目录中,而不要放置在资源目录中.

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),(请参见

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提供的favicon功能.
也许有一种添加我自己的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.

但两种选择都不令人满意.
我只想将favicon文件放在我的静态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. (当然)
  • 对于客户端(Web浏览器),我使用AngularJS.

工具:

  • 对于服务器端,我使用Spring Tool Suite.
  • 对于客户端,我使用WebStorm.

主目录结构:

ProjectRoot\
    src\
    bin\
    build\
    webapp\
    build.gradle

  • src:我的Spring Java源文件驻留的位置.
  • bin:Spring Tool Suite放置其构建输出的位置.
  • build:"gradle build"放置其build输出的位置.
  • webapp:我的客户端源文件(.js,.css,.htm和favicon)所在的位置.因此,这是WebStorm项目目录. (如有必要,我可以更改目录名称)
    • src: Where my Spring java source files reside.
    • bin: Where Spring Tool Suite places its build output.
    • build: Where 'gradle build' places its build output.
    • webapp: Where my client source files(.js, .css, .htm and favicon) reside. Thus this is the WebStorm project directory. (I can change the directory name if necessary)
    • 我想要的是:

      • 能够在不重建/重新启动Spring服务器应用程序的情况下修改和测试我的客户端代码.因此,不得将客户端代码放入jar文件中.无论如何,Spring Tool Suite根本不会构建jar文件(至少对于当前配置而言)
      • 为了能够使用客户端代码测试我的Spring服务器应用程序,请在Spring Tool Suite输出和gradle输出之间轻松切换.因此,必须可以从build子目录(实际上是build\libs)中的服务器应用程序和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 build\libs) 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)的情况下,Google Chrome浏览器会无限期地缓存文件,而无需询问服务器更新.它甚至不连接到服务器. (Google工程师说这种行为是正确的.)因此,我所能做的就是手动清除浏览器缓存.在开发环境上令人沮丧,在生产环境上令人无法接受.

      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.

      BTW,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().

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

      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完全禁用Favicon分辨率.

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

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

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