標準のSpringMVCアプリケーションはDispatcherServlet
、サーブレットコンテナに登録したを介してすべてのリクエストを処理します。
をDispatcherServlet
見て、ApplicationContext
可能な場合ApplicationContext
はContextLoaderListener
、特別なBeanに登録されており、要求処理ロジックをセットアップする必要があります。これらのBeanについては、ドキュメントで説明されています。
おそらく最も重要な、タイプHandlerMapping
マップのBean
ハンドラーへの着信要求と、HandlerMapping
実装によって詳細が異なるいくつかの基準に基づくプリプロセッサーとポストプロセッサー(ハンドラーインターセプター)のリスト。最も一般的な実装は注釈付きコントローラーをサポートしますが、他の実装も存在します。
のjavadocは、HandlerMapping
実装がどのように動作する必要があるかをさらに説明しています。
DispatcherServlet
このタイプのすべてのBeanを検索し、いくつかの順序でそれらを登録する(カスタマイズすることができます)。リクエストを処理している間、DispatcherServlet
これらのHandlerMapping
オブジェクトをループし、それぞれをテストしgetHandler
て、標準として表される着信リクエストを処理できるオブジェクトを見つけますHttpServletRequest
。4.3.xのとおり、それはいずれも見つからない場合、それは警告ログに記録し、あなたが見ていることを
SomeNameという名前のURI[/some/path]
をDispatcherServlet
持つHTTPリクエストのマッピングが見つかりません
そしてどちらか投げるNoHandlerFoundException
か、すぐに404が見つかりませんでしたステータスコードでレスポンスをコミットします。
リクエストを処理できるがDispatcherServlet
見つからなかったのはなぜHandlerMapping
ですか?
最も一般的なHandlerMapping
実装はですRequestMappingHandlerMapping
。これは、@Controller
Beanをハンドラー(実際には@RequestMapping
アノテーション付きメソッド)として登録することを処理します。このタイプのBeanを(@Bean
または<bean>
または他のメカニズムを使用して)自分で宣言するか、組み込みオプションを使用することができます。これらは:
@Configuration
クラスに@EnableWebMvc
。で注釈を付けます。
<mvc:annotation-driven />
XML構成でメンバーを宣言します。
上記のリンクで説明されているように、これらは両方ともRequestMappingHandlerMapping
Bean(および他の多くのもの)を登録します。ただし、aHandlerMapping
はハンドラーなしではあまり役に立ちません。RequestMappingHandlerMapping
一部の@Controller
Beanを想定しているため@Bean
、Java構成のメソッド<bean>
、XML構成の宣言、または@Controller
いずれかの注釈付きクラスのコンポーネントスキャンを通じて、それらも宣言する必要があります。これらのBeanが存在することを確認してください。
警告メッセージと404が表示され、上記のすべてを正しく構成した場合は、検出された@RequestMapping
アノテーション付きハンドラーメソッドによって処理されない間違ったURIにリクエストを送信しています。
spring-webmvc
内蔵された他のライブラリの提供HandlerMapping
の実装。たとえば、BeanNameUrlHandlerMapping
地図
URLからスラッシュ( "/")で始まる名前のBeanへ
そして、あなたはいつでもあなた自身を書くことができます。明らかに、送信するリクエストが、登録されたHandlerMapping
オブジェクトのハンドラーの少なくとも1つと一致することを確認する必要があります。
あなたが暗黙的または明示的に登録していない場合はHandlerMapping
豆(または場合detectAllHandlerMappings
であるがtrue
)、DispatcherServlet
いくつかのレジスタのデフォルトを。これらはDispatcherServlet.properties
、DispatcherServlet
クラスと同じパッケージで定義されています。それらはBeanNameUrlHandlerMapping
andですDefaultAnnotationHandlerMapping
(これは類似してRequestMappingHandlerMapping
いますが非推奨です)。
デバッグ
Spring MVCは、を介して登録されたハンドラーをログに記録しますRequestMappingHandlerMapping
。例えば、@Controller
のような
@Controller
public class ExampleController {
@RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom")
public String example() {
return "example-view-name";
}
}
INFOレベルで以下をログに記録します
Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()
登録されているマッピングについて説明します。ハンドラーが見つからなかったという警告が表示されたら、メッセージ内のURIをここにリストされているマッピングと比較します。@RequestMapping
Spring MVCがハンドラーを選択するには、で指定されたすべての制限が一致する必要があります。
他のHandlerMapping
実装は、マッピングと対応するハンドラーを示唆する独自のステートメントをログに記録します。
同様に、DEBUGレベルでSpringロギングを有効にして、Springが登録するBeanを確認します。検出した注釈付きクラス、スキャンするパッケージ、および初期化するBeanを報告する必要があります。期待したものが存在しない場合は、ApplicationContext
構成を確認してください。
その他のよくある間違い
ADispatcherServlet
は典型的なJavaEEServlet
です。あなたの典型的なとあなたはそれを登録<web.xml>
<servlet-class>
し、<servlet-mapping>
宣言、または直接通じServletContext#addServlet
でWebApplicationInitializer
、または任意のメカニズム春ブーツ用途に。そのため、サーブレット仕様で指定されているURLマッピングロジックに依存する必要があります。第12章を参照してください。
そのことを念頭に置いて、よくある間違いはDispatcherServlet
、のURLマッピングを登録/*
し、@RequestMapping
ハンドラーメソッドからビュー名を返し、JSPがレンダリングされることを期待することです。たとえば、次のようなハンドラメソッドについて考えてみます。
@RequestMapping(path = "/example", method = RequestMethod.GET)
public String example() {
return "example-view-name";
}
と InternalResourceViewResolver
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
リクエストがパスのJSPリソースに転送されることを期待するかもしれません/WEB-INF/jsps/example-view-name.jsp
。これは起こりません。代わりに、のコンテキスト名を想定しExample
、DisaptcherServlet
報告します
'dispatcher'という名前のURI[/Example/WEB-INF/jsps/example-view-name.jsp]
をDispatcherServlet
持つHTTPリクエストのマッピングが見つかりません
ためDispatcherServlet
にマッピングされる/*
と/*
(より高い優先度を有する完全一致、除く)すべて一致、DispatcherServlet
処理するために選択されるであろうforward
からJstlView
(によって返されますInternalResourceViewResolver
)。ほとんどの場合、はDispatcherServlet
そのような要求を処理するように構成されていません。
代わりに、この単純なケースでは、DispatcherServlet
toを登録して/
、デフォルトのサーブレットとしてマークする必要があります。デフォルトのサーブレットは、リクエストの最後の一致です。これにより、通常のサーブレットコンテナは、デフォルトのサーブレットを試す前に、にマップされた内部サーブレット実装を選択して*.jsp
、JSPリソース(たとえば、Tomcatが持っているJspServlet
)を処理できるようになります。
それはあなたがあなたの例で見ているものです。