SpringBoot: 覆盖图标

如何覆盖 SpringBoot 的图标?

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

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

另外,由于我希望图标文件在客户端(web 浏览器)尽快更新,我想设置图标文件的缓存期为0。(如下面的代码,我使用的’静态’网络应用程序的内容和脚本文件,必须在客户端尽快更新后,我改变了文件。)

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

因此,仅仅为了找到一个地方来保存 Favicon.ico 文件,Spring Boot 的 FaviconRequestHandler 的优点可能是不够的。

更新

现在我知道可以通过在 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/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java中的 FaviconConfiguration 类)我的处理程序胜出。

这样可以吗? 还有别的方法吗(比我做的更温和的方法) ?

更新

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

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

需要另一种解决方案。

更新

现在,我找不到覆盖 Spring Boot 提供的图标功能的方法。
也许有一种方法可以添加我自己的 HandlerMapping bean,但我不知道如何做到这一点。

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

  1. 拥有一个具有 @EnableWebMvc的类,从而禁用 Spring BootWebMvcAutoConfiguration类。(我可以复制代码的 WebMvcAutoConfiguration类和删除图标的功能)
  2. 放弃将图标文件放置到任意位置的自由,将其放置到 Spring Boot 的图标功能所要求的资源目录中。忽略缓存问题。

但这两种选择都不令人满意。
我只是想把图标文件与我的静态 web 文件(可以是任何目录,因为我可以更改文档根)和解决缓存问题。
我错过了什么吗?
如有任何建议,我将不胜感激。

更新

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

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

图书馆/架构:

  • 对于服务器端,我使用 Spring。(当然)
  • 对于客户端(web 浏览器) ,我使用 AngularJS。

工具:

  • 对于服务器端,我使用 Spring 工具套件。
  • 对于客户端,我使用 WebStorm。

主目录结构:

ProjectRoot\
src\
bin\
build\
webapp\
build.gradle
  • Src: 我的 Springjava 源文件所在的位置。
  • Bin: Spring Tool Suite 放置其构建输出的位置。
  • Build: “ gradle build”放置其构建输出的地方。
  • Webapp: 我的客户端源文件(。JS.CSS.Htm 和 Favicon)居住。因此,这是 WebStorm 项目目录。(如果需要,我可以更改目录名)

我想要的是:

  • 能够修改和测试我的客户端代码,而无需重新构建/重新启动 Spring 服务器应用程序。因此,不能将客户机代码放入 jar 文件中。总之,SpringToolSuite 根本不构建 jar 文件(至少在当前配置中是这样)
  • 为了能够用客户端代码测试我的 Spring 服务器应用程序,可以轻松地在 Spring Tool Suite 输出和 gradle 输出之间切换。因此,必须能够从 build子目录(实际上是 build\libs)中的服务器应用程序和 bin目录中的服务器应用程序访问客户机代码。
  • 当我修改客户端代码时,它必须立即对 Web 浏览器可用。因此浏览器不能无限期地缓存它,而且必须总是请求服务器进行更新。
  • 在部署时,客户端代码必须是可修改的,无需重新构建/重新启动服务器应用程序。因此,不能将客户机代码放入 jar 文件中。

关于缓存问题:

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

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

任何改善我的环境的建议都会受到欢迎。
由于我是一个春季初学者,我可能遗漏了一些东西。

更新

最后,我有一个工作代码。它是这样的:

@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()中的代码是必要的。

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

66599 次浏览

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.

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

None of this was necessary for me.

Why override the default when you can bundle a resource with the generated JAR that will take higher precedence than the default one.

To achieve a custom favicon.ico file, I created a src/main/resources directory for my application and then copied the favicon.ico file into there. The files in this resources directory are moved to the root of the compiled JAR and therefore your custom favicon.ico is found before the Spring provided one.

Doing the above achieved the same effect as your updated solution above.

Note that since v1.2.0 you can also put the file in src/main/resources/static.

I really like Springboot because overall it is full of smart solutions but I refuse to register an application bean to provide a favicon because that is just plain stupid.

I just added my own favicon link in my html page head like so.

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

Then I renamed my favicon and placed it at

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

Now I have an icon in Chrome and Firefox browser tabs and the Safari address bar without having to use Spring and Java, and I should not have to chase changes to Springboot in newer versions for such trivial functionality.

Newer versions of Boot (1.2 for sure but maybe also 1.1.8) allow you to just put a favicon.ico in your static resources.

Since Spring Boot 1.2.2 and 1.1.11 you can easily disable default favicon using spring.mvc.favicon.enabled = false property.

For more informations visit:

UPDATE: there is no longer spring.mvc.favicon.enabled property since Spring Boot 2.2.x

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

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

robots.txt, favicon.ico file location : /src/main/resources

i used spring boot 1.2.1

I tried a lot of options/variants, but only this worked. (Spring Boot 2.2.7)

Favicon.ico files & robots.txt put in /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();
}
}

and

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

If it helps, please like it ;)

I'm using Spring Boot version 2.5.2. In my case, I just needed a jpg/png file for favicon, not a favicon.ico file.

Put your favicon.jpg/favicon.png file in the resources folder in your classpath - src/main/resources/favicon.png
or in the static folder in the resources folder in your classpath -
src/main/resources/static/favicon.png

In each of your HTML pages in templates folder in the resources folder, put -
<link rel="icon" type="image/png" href="../favicon.png">
or
<link rel="icon" type="image/png" href="../static/favicon.png">
inside the head tag respectively .