3
0

More than 3 years have passed since last update.

Spring Boot で @EnableWebFlux 付与していたら WebFlux から静的リソースを配布できなかった

Posted at

結論

Spring Boot 2.3.4.RELEASE時点でSpring WebFluxを使用する場合、
@EnableWebFluxアノテーションを使用すると静的リソースを配布できなくなります。

あらまし

数年ぶりにWEBサーバーを開発することになった。
JavaもWEBサーバーの開発も久しぶりなので情報が多いSpinrg Bootを使用することにした。

暫くJavaを使用していなかった間にSpring FrameworkにはSpring WebFluxが追加されていたので、
せっかくなのでWebFluxを使用することにした。

初めて使用するSpring WebFluxのドキュメントを軽く読んだ後、
Spring Bootでアプリケーションを自動構成した。

この時点ではWebFluxの利用に大きな問題はなかったが、後から静的リソースを配布する必要が出てきた。

Spring BootでWebFluxが構成されていればSpring MVCと同様に静的リソースを配布できるらしい。
classpath:/static/にリソースを配置し、WEBブラウザでアクセスをすればサーバーからレスポンスが返ってくると思っていたが、404 Not Foundが返ってくる。

何かを間違えているのかと思いSpring Bootのドキュメントを閲覧するが、出来ると書かれている

ドキュメントでは可能と書かれている静的リソースが配布されない。
理由がいまいちわからなかったため、Spring BootのWebFlux関係のauto-configurationを確認する。

WebFluxで静的リソースを配布するための構成を探してWebFluxAutoConfigurationを発見した。

WebFluxConfig#addResourceHandlers(ResourceHandlerRegistry)で静的リソースのマッピングを追加しているようなので、
WebFluxConfig#addResourceHandlers(ResourceHandlerRegistry)WebFluxコンストラクタの2か所にブレークポイントを追加し、
デバッガーをアタッチしてアプリケーションを起動する。
しかし、アプリケーションが起動し終わってもブレークポイントがヒットしなかった。

Spring Bootのauto-configurationが呼び出されないときは、大抵は@Beanの不足やライブラリの不足でauto-configurationが実行される条件が満たされない状態が発生している。

何か自分が見落としているんだろうと思いながら改めてSpring Bootのドキュメントを眺めていると、
ドキュメントに原因がはっきりと書かれていることに気が付いた。

原因

Spring BootはWebFluxの構成をWebFluxAutoConfigurationで実施している。
このクラスには@ConditionalOnMissingBean({ WebFluxConfigurationSupport.class })が付与されているため、
他にWebFluxConfigurationSupportの実装が@Bean登録されているとこのauto-configurationは実行されなくなってしまう。

@EnableWebFlux定義を確認すると
@Import(DelegatingWebFluxConfiguration.class)が付与されている。
DelegatingWebFluxConfigurationWebFluxConfigurationSupportの実装にあたるので、
Spring Bootが用意しているWebFluxAutoConfigurationConditionalOnMissingBeanによってauto-configurationとして動作しなくなる。

最初に読んだSpring WebFluxのドキュメントで@Configurationクラスに@EnableWebFluxを付与していたので
WebFluxアプリケーションを実装するためには付与しないといけないと思い込んでいた。

しかし、Spring BootはWebFluxに機能を追加するために独自のWebFluxConfigurationSupportを提供しているため、
Spring BootでWebFluxを有効化するときは@EnableWebFluxを付与してはいけないというルールがあった。

このあたりの仕様はSpring Bootのドキュメントにしっかりと書かれていたのだが、
Spring WebFluxのドキュメント読んだ後だったので読み飛ばしてしまっていた。

余談

Spring Bootはクラスパスのライブラリを検出してSpring MVCとSpring WebFluxのどちらをWEBサーバーとして構成するか決定している。

では、Spring MVCとSpring WebFluxの両方のライブラリがクラスパスに存在するとき、
どうやって有効化するWEBサーバーをコントロールできるのか、
念のために調べたところSpring Bootのプロパティspring.main.web-application-typeREACTIVEを指定して
WebFluxでアプリケーションを構成することが出来るようだ

spring.main.web-application-typeの設定状態の判定は、
WebFluxAutoConfigurationに付与されている@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)アノテーションで行われている。

Spring MVCが使いたければspring.main.web-application-typeSERVLETを指定する。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0