結論
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)
が付与されている。
DelegatingWebFluxConfiguration
はWebFluxConfigurationSupport
の実装にあたるので、
Spring Bootが用意しているWebFluxAutoConfiguration
はConditionalOnMissingBean
によって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-type
にREACTIVE
を指定して
WebFluxでアプリケーションを構成することが出来るようだ。
spring.main.web-application-type
の設定状態の判定は、
WebFluxAutoConfiguration
に付与されている@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
アノテーションで行われている。
Spring MVCが使いたければspring.main.web-application-type
にSERVLET
を指定する。