Spring Boot:ファビコンのオーバーライド


83

Spring Bootのファビコンをオーバーライドするにはどうすればよいですか?

:これは、コーディングを含まない別のソリューションを提供する別の質問です。SpringBoot:ファットジャーを使用して任意のディレクトリで外部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)であり、SpringBootのメインリソースディレクトリに配置される「緑の葉」アイコンを提供します。

@EnableWebMvcを持つクラスを自分で実装せずにオーバーライドして、Spring BootのWebMvcAutoConfigurationクラスのデフォルト構成機能全体を無効にするにはどうすればよいですか?

また、クライアント(Webブラウザ)側でアイコンファイルをできるだけ早く更新したいので、ファビコンファイルのキャッシュ期間を0に設定したいと思います(次のコードのように、 「静的」なWebアプリケーションコンテンツとスクリプトファイル。ファイルを変更した後、できるだけ早くクライアント側で更新する必要があります。)

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

したがって、SpringBootのfaviconRequestHandlerが尊重するfavicon.icoファイルを保存する場所を見つけるだけでは不十分な場合があります。

更新

これで、ファビコンファイルを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/の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);
}

別の解決策が必要です。

更新

今のところ、SpringBootが提供するファビコン機能をオーバーライドする方法を見つけることができませんでした。
自分のHandlerMappingBeanを追加する方法があるかもしれませんが、その方法がわかりません。

これで、次のオプションのいずれかを選択できます。

  1. @EnableWebMvcしたがって、SpringBootクラスを無効にするWebMvcAutoConfigurationクラスがあります。(WebMvcAutoConfigurationクラスのコードをコピーしてファビコン機能を削除できます)
  2. Spring Bootのファビコン機能が必要とするように、ファビコンファイルを任意の場所に配置する自由を放棄し、リソースディレクトリに配置します。そして、キャッシュの問題を無視します。

しかし、どちらのオプションも満足のいくものではありません。
ファビコンファイルを静的Webファイル(ドキュメントルートを変更できるため、任意のディレクトリにすることができます)と一緒に配置し、キャッシュの問題を解決したいだけです。
私は何かが足りないのですか?
任意の提案をいただければ幸いです。

更新

ところで、ファビコンやその他の静的ファイルの場所を変更したい理由は次のとおりです。今のところ、それは主に開発環境の問題です。

シングルページWebアプリケーション(SPA)を構築しています。

ライブラリ/フレームワーク:

  • サーバーサイドにはSpringを使用しています。(もちろん)
  • クライアント(Webブラウザ)側では、AngularJSを使用しています。

ツール:

  • サーバーサイドには、Spring ToolSuiteを使用しています。
  • クライアント側にはWebStormを使用しています。

メインディレクトリ構造:

ProjectRoot\
    src\
    bin\
    build\
    webapp\
    build.gradle
  • src:SpringJavaソースファイルが存在する場所。
  • bin:Spring ToolSuiteがビルド出力を配置する場所。
  • build: 'gradlebuild'がビルド出力を配置する場所。
  • webapp:クライアントソースファイル(.js、.css、.htm、ファビコン)が存在する場所。したがって、これはWebStormプロジェクトディレクトリです。(必要に応じてディレクトリ名を変更できます)

私が欲しいのは:

  • Springサーバーアプリケーションを再構築/再起動せずにクライアントコードを変更およびテストできるようにするため。したがって、クライアントコードをjarファイルに入れてはなりません。とにかく、Spring Tool Suiteはjarファイルをまったく構築しません(少なくとも現在の構成では)
  • Springサーバーアプリケーションをクライアントコードでテストできるようにするには、Spring ToolSuiteの出力とgradleの出力を簡単に切り替えます。したがって、クライアントコードは、buildサブディレクトリ内のサーバーアプリケーション(実際にはbuild\libs)とディレクトリ内のサーバーアプリケーションの両方からアクセスできる必要がありますbin
  • クライアントコードを変更すると、Webブラウザですぐに利用できるようになる必要があります。したがって、ブラウザはそれを無期限にキャッシュしてはならず、常にサーバーに更新を要求する必要があります。
  • デプロイするとき、クライアントコードは、サーバーアプリケーションを再構築/再起動せずに変更可能である必要があります。したがって、クライアントコードをjarファイルに入れてはなりません。

キャッシュの問題について:

addResourceHandlers()にsetCachePeriod(0)がないと、Google Chromeはサーバーに更新を要求せずに、ファイルを無期限にキャッシュします。サーバーにも接続しません。(Googleのエンジニアは、動作は正しいと言っています。)したがって、私にできることは、ブラウザーのキャッシュを手動でクリアすることだけです。開発環境ではイライラし、本番環境では受け入れられません。

ところで、Node.jsのexpress.jsモジュールは、Google Chromeがサーバーに更新を要求するように、適切なデフォルトのHTTPヘッダーを提供します。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()

これで、キャッシュの問題がないファビコンハンドラーができ、ファビコンファイルを好きな場所に配置できます。
ありがとう。


1
あなたの方法は大丈夫そうです。ただし、デフォルトのSpring MVCリソースハンドラーに置き換わるものではありません(classpath:/staticたとえば、静的リソースはこれ以上提供されません)。(これが、Bootでのファビコンサポートが独自のHandlerMappingにある理由です。)
Dave Syer 2013

@DaveSyer今、私はそれが大丈夫ではないことに気づきました。私は上記の3番目の更新を書きました。多分別々HandlerMappingが必要です。
zeodtr 2013

@DaveSyer上記の4番目の更新を参照してください。他に方法はありますか?たとえば、自分で登録できHandlerMappingますか?
zeodtr 2013

はい、追加できますHandlerMapping(Bootからコピーして優先度を高くするだけです)。なぜ場所を気にするのかよくfavicon.ico fileわかりませんが、必要に応じて構成可能にすることができます。すべてのブラウザがそれをキャッシュするので、キャッシュ設定が重要であるとは思えませんが、間違っていることが証明されてうれしいです。
Dave Syer 2013

@DaveSyer静的ファイルを別の場所に配置したい理由については、更新された質問を参照してください。また、キャッシュの問題。
zeodtr 2013

回答:


53

クラスパスのルートまたは静的リソースの場所(例classpath:/static)に独自のfavicon.icoを配置するだけです。単一のフラグでファビコンの解決を完全に無効にすることもできspring.mvc.favicon.enabled=falseます。

または、完全に制御するには、HandlerMappingを追加します(ブートからコピーして優先度を高くするだけです)。

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

ありがとうございました。すでに試したと思っていたのですが、思いついたので@Configurationアノテーションを逃してしまいました。ところで、質問の別の場所に静的ファイルを配置したい理由を書きました。
zeodtr 2013

ところで、ドキュメントルート(右?)にファイルを取得するにはResourceLoader.gerResource( "/")を使用する必要があるため、@ AutowireApplicationContextを使用する必要があります。アプリケーションコンテキストをDIしても大丈夫ですか?悪いことだと言う人もいます。
zeodtr 2013

私はあなたの提案を試みています。注意すべき1つのこと:私のBean名は 'faviconHandlerMapping'であってはなりません。これは、Bean名がSpringBootのfaviconHandlerMappingBeanと衝突する原因となるためです。org.springframework.web.servlet.initHandlerMappings()によって再び呼び出されるorg.springframework.beans.factory.BeanFactoryUtils.beansOfTypeInclusiveAncestor‌ s()によって呼び出されるメソッドによって、2つのBeanのうちの1つだけが選択されます。私のBeanは以前にロードされてから、名前の衝突によってオーバーライドされたようです。
zeodtr 2013

次のように登録されHandlerMapping豆の名前は次のとおりです。{ faviconHandlerMappingrequestMappingHandlerMappingviewControllerHandlerMappingbeanNameHandlerMappingresourceHandlerMappingdefaultServletHandlerMappingendpointHandlerMapping}私はそれらの名前を避けなければならないので。
zeodtr 2013

2
更新された回答とユーザーガイドを読む必要があります。アイコンを変更するだけなら、それほど難しい変更ではありませんでした。OPがなぜそんなに困ったのかわかりません。
Dave Syer 2016

75

これは私には必要ありませんでした。

デフォルトよりも優先される生成されたJARにリソースをバンドルできるのに、なぜデフォルトをオーバーライドするのか。

カスタムfavicon.icoファイルを作成するsrc/main/resourcesために、アプリケーション用のディレクトリを作成し、favicon.icoそこにファイルをコピーしました。このresourcesディレクトリ内のファイルはコンパイルされたJARのルートに移動favicon.icoされるため、Springが提供する前にカスタムが見つかります。

上記を実行すると、上記の更新されたソリューションと同じ効果が得られました。

v1.2.0以降、ファイルをに配置することもできることに注意してくださいsrc/main/resources/static


6
理由は簡単です。ファビコンファイルをJARに入れたくありません。
zeodtr 2014年

@zeodtrはなぜか興味があります。これは私にとって最も自然なことのようです。しかし、私はそれが入っていると思っていたでしょうsrc/main/resources/static/images
btiernay 2014

1
@btiernayこれは、WebサーバーがWebクライアントとは別のエンティティであるためです。そして、ファビコンはクライアントに属しています。Webサーバーのwarファイルには、ユーザーの必要に応じてはるかに頻繁に変更できるクライアントに属するファイルを含める理由はありません。
zeodtr 2014

ちょうどFYI、解決することが可能になりましたfavicon.icoからstaticgithub.com/spring-projects/spring-boot/commit/...
btiernay

1
src / main / resources / staticpathはうまく機能します。これは、最も簡単で通常の方法です。
pdem 2015

29

Springbootは全体的にスマートなソリューションでいっぱいなので、私は本当に好きですが、ファビコンを提供するためにアプリケーションBeanを登録することは、それが単なる愚かであるため拒否します。

自分のファビコンリンクをHTMLページのヘッドにそのように追加しました。

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

次に、ファビコンの名前を変更して、

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

これで、SpringとJavaを使用せずに、ChromeとFirefoxのブラウザタブとSafariアドレスバーにアイコンが表示されます。このような些細な機能のために、新しいバージョンでSpringbootへの変更を追跡する必要はありません。


4
ハンドラーマッピングをいじくり回す必要はもうありません(静的リソースにfavicon.icoを配置するだけです)。
Dave Syer 2014

とても簡単です!ありがとう。フラグメントに追加します。
Lay Leangsros 2016年


@ParamvirSinghKarwalサービスしかない場合、なぜファビコンが必要なのですか?
jeremyjjbrown

ブラウザのアドレスから直接APIをヒットすると、緑の葉のようなSpringアプリケーションのデフォルトのファビコンが表示されます。ブランドのファビコンにしたいと思います。私はそれをすることができました。
Paramvir SinghKarwal19年

13

Spring Boot 1.2.2および1.1.11以降、spring.mvc.favicon.enabled = falseプロパティを使用してデフォルトのファビコンを簡単に無効にできます。

詳細については、以下をご覧ください。

更新:spring.mvc.favicon.enabledSpring Boot 2.2.x以降、プロパティはなくなりました


spring.mvc.favicon.enabledがSpringBoot2.2から削除されました。何に置き換えられるか知っていますか?
シラン

1
@Shilanデフォルトのファビコンがなくなったため、何にも置き換えられませんでした。必要な場合は、独自のファビコンのマッピングを構成する必要があります。
Trynkiewicz Mariusz

1
ええ、最後に、代わりにこれを行う必要があることがわかりました。@ Override public void addResourceHandlers(ResourceHandlerRegistry Registry){registry.addResourceHandler( "/ favicon.ico")。addResourceLocations( "classpath:/ static /"); }
シラン

2

新しいバージョンのBoot(確かに1.2ですが、おそらく1.1.8)を使用すると、静的リソースにfavicon.icoを配置するだけで済みます。


2

私は多くのオプション/バリアントを試しましたが、これだけが機能しました。(Spring Boot 2.2.7)

/ resources / staticに配置されたFavicon.icoファイルとrobots.txt

@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/");
  }
}

それが役立つなら、それを好きにしてください;)


1

Registry.addResourceHandler( "/ robots.txt")。addResourceLocations( "/");

Registry.addResourceHandler( "/ favicon.ico")。addResourceLocations( "/");

robots.txt、favicon.icoファイルの場所:/ src / main / resources

スプリングブーツ1.2.1を使用しました

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.