1. ホーム
  2. spring-mvc

[解決済み] スプリングブート faviconのオーバーライド

2023-05-11 15:49:59

質問

Spring Bootのfaviconをオーバーライドするにはどうすればよいですか?

ノート : ここに私の別の質問は、任意のコーディングを伴わない別のソリューションを提供しています。 Spring Boot。ファットジャーで任意のディレクトリにある外部application.propertiesファイルを使用することは可能ですか? application.propertiesのためですが、faviconにも適用できます。実は今、faviconのオーバーライドにその方法を使っています。

EnableWebMvcを持つクラスを実装すると、Spring BootのWebMvcAutoConfigurationクラスがロードされず、静的コンテンツのルートディレクトリに配置することで自作のファビコンを提供することができる。

そうしないと、WebMvcAutoConfigurationはfaviconRequestHandlerというビーンを登録します(ソース参照)。 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に設定したいです。(次のコードのように、ファイルを変更したらできるだけ早くクライアント側で更新しなければならない「静的」Webアプリケーションコンテンツとスクリプトファイルに対して使用しています).

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

そのため、Spring BootのfaviconRequestHandlerのhonorsが持つfavicon.icoファイルの保存場所を見つけるだけでは不十分な場合があります。

UPDATE

src/main/resourcesディレクトリにfaviconファイルを置くことで、デフォルトのものを上書きできることはわかりました。しかし、キャッシュ期間の問題はまだ残っています。

また、ファビコン ファイルはリソース ディレクトリではなく、静的な Web ファイルが配置されるディレクトリに配置することが望ましいとされています。

UPDATE

OK、デフォルトのものを上書きすることに成功しました。 私がやったことは以下の通りです。

@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) を持つので、(FaviconConfiguration クラスの https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java のFaviconConfigurationクラスを参照)私のハンドラの勝ちです。

これでいいのでしょうか? 他の方法(私がしたことよりも優しいもの)がありますか?

アップデイト

OKではありません。 私が registry.setOrder(Integer.MIN_VALUE) を呼び出すと、実はすべてのリソースハンドラの優先度が上がってしまうのです。そこで、次のコードを別の WebMvcConfigurerAdapter に追加すると、効果的にすべての http リクエストがそのリソースハンドラに向けられ、Java コードによる動的な処理を防ぐことができます。

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

別の解決策が必要です。

アップデイト

今のところ、Spring Bootが提供するfavicon機能をオーバーライドする方法は見つかりませんでした。

もしかしたら、独自の HandlerMapping ビーンを追加する方法があるかもしれませんが、私はそれを行う方法を知りません。

これで、次のオプションのいずれかを選択できるようになりました。

  1. を持つクラスがある。 @EnableWebMvc というように、Spring Bootを無効化する WebMvcAutoConfiguration クラスで使用することができます。(のコードをコピーすることができます)。 WebMvcAutoConfiguration クラスのコードをコピーして、ファビコン機能を削除することができます)
  2. ファビコンファイルを任意の場所に配置する自由はあきらめ、Spring Bootのファビコン機能が要求するリソースディレクトリに配置します。キャッシュの問題は無視する。

しかし、どちらの選択肢も満足のいくものではありません。

私はただ、ファビコンファイルを静的なWebファイル(ドキュメントルートを変更できるので、任意のディレクトリにすることができます)と一緒に配置し、キャッシュの問題を解決したいだけなのです。

何か見落としているのでしょうか?

何かご指摘がありましたら、よろしくお願いします。

アップデイト

ちなみに、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 Tool Suiteの出力とgradleの出力を簡単に切り替えて、クライアントコードでSpringサーバーアプリケーションをテストできるようにすること。そのため、クライアントコードは、サーバーアプリケーションから build サブディレクトリ(実際には build\libs ) に、サーバーアプリケーションは bin ディレクトリにあります。
  • クライアントコードを修正したら、すぐにウェブブラウザから利用できるようにしなければなりません。そのため、ブラウザは無期限にキャッシュしてはならず、常に更新のためにサーバーに問い合わせなければなりません。
  • デプロイされたとき、クライアントコードはサーバーアプリケーションを再構築/再起動することなく変更可能でなければなりません。そのため、クライアントコードは jar ファイルに格納されてはいけません。

キャッシュの問題に関して。

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

ところで、Node.js 上の express.js モジュールは、Google Chrome がサーバーに更新を要求するように、妥当なデフォルト HTTP ヘッダーを提供します。Fiddlerを使ってSpringとexpress.jsが生成する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;
    }
}

ビーン名に注目してください。名前の衝突を避けるために'my'を追加しています。

アプリケーションコンテキストの自動配線は厄介に思えますが、これは org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration.addResourceLocations() .

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

ありがとうございます。

どのように解決するのですか?

クラスパスのルートまたは静的リソースの場所(たとえば classpath:/static ). また、一つのフラグでファビコンの解決を完全に無効にすることができます。 spring.mvc.favicon.enabled=false .

または、完全に制御するために、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;
}
}