[解決済み] Spring MVCが404で応答し、「No mapping found for HTTP request with URI [...] in DispatcherServlet」と報告されるのはなぜですか?
質問
Tomcat上に配置されたSpring MVCアプリケーションを書いています。以下を参照してください。 最小限の、完全で、検証可能な例
public class Application extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { };
}
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { SpringServletConfig.class };
}
protected String[] getServletMappings() {
return new String[] { "/*" };
}
}
ここで
SpringServletConfig
は
@Configuration
@ComponentScan("com.example.controllers")
@EnableWebMvc
public class SpringServletConfig {
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
}
最後に
@Controller
をパッケージ内で
com.example.controllers
@Controller
public class ExampleController {
@RequestMapping(path = "/home", method = RequestMethod.GET)
public String example() {
return "index";
}
}
私のアプリケーションのコンテキスト名は
Example
. にリクエストを送ると
http://localhost:8080/Example/home
の場合、アプリケーションはHTTPステータス404で応答し、次のようにログに記録されます。
WARN o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI `[/Example/WEB-INF/jsps/index.jsp]` in `DispatcherServlet` with name 'dispatcher'
JSPリソースを
/WEB-INF/jsps/index.jsp
Spring MVCが私のコントローラを使用してリクエストを処理し、JSPに転送することを期待していたのですが、なぜ404で応答するのでしょうか?
これは、この警告メッセージに関する質問の正規の投稿であることを意図しています。
どのように解決するのですか?
標準的なSpring MVCアプリケーションでは、すべてのリクエストは
DispatcherServlet
を通してすべてのリクエストを処理します。
は
DispatcherServlet
は、その
ApplicationContext
であり、利用可能であれば
ApplicationContext
に登録されている
ContextLoaderListener
に登録され、 リクエストサービングロジックを設定するために必要な特別な Bean のために使われます。
これらのビーンについては、ドキュメントで説明されている
.
おそらく最も重要なのは、ビーンタイプの
HandlerMapping
マップ
ハンドラへのリクエストとプリポストプロセッサー(ハンドラインターセプター)のリストを (ハンドラインターセプタ) のリストです。 によって異なります。
HandlerMapping
の実装によって異なります。最も一般的な実装は はアノテートコントローラをサポートしていますが、他の実装も存在します。 もあります。
この
の javadoc を参照してください。
HandlerMapping
は、実装がどのように振舞わなければならないかをさらに記述しています。
は
DispatcherServlet
は、このタイプのすべてのビーンを見つけ、 ある順序で登録します (カスタマイズ可能)。リクエストに応答している間
DispatcherServlet
はこれらの
HandlerMapping
オブジェクトをループし、それぞれのオブジェクトを
getHandler
を使用して、標準的な
HttpServletRequest
. 4.3.x の時点では
が見つからなければ
が見つからない場合、それは
は警告を記録します。
が表示されます。
URI を持つ HTTP リクエストに対するマッピングが見つかりません
[/some/path]
で
DispatcherServlet
で、名前 SomeName
と
のどちらかを
は
NoHandlerFoundException
を投げるか、404 Not Found ステータスコードでレスポンスを即座にコミットします。
はなぜ
DispatcherServlet
を見つけたのでしょうか?
HandlerMapping
を見つけることができますか?
最も一般的な
HandlerMapping
の実装は
RequestMappingHandlerMapping
の登録を処理します。
@Controller
ビーンをハンドラとして登録します (実際にはその
@RequestMapping
アノテーションされたメソッド)。このタイプのビーンを自分で宣言することもできます (
@Bean
または
<bean>
または他のメカニズム)を使用するか、または
内蔵のオプション
. これらは
-
をアノテートします。
@Configuration
クラスには@EnableWebMvc
. -
を宣言します。
<mvc:annotation-driven />
メンバを XML 設定で宣言します。
上のリンクで説明されているように、これらはどちらも
RequestMappingHandlerMapping
ビーン(および他の多くのもの)を登録します。しかし
HandlerMapping
はハンドラ無しではあまり役に立ちません。
RequestMappingHandlerMapping
が期待するのは、いくつかの
@Controller
ビーンを期待しますので、それらも
@Bean
メソッドで宣言する必要があります。
<bean>
の宣言や、 コンポーネントスキャンによる
@Controller
でアノテーションされたクラスのコンポーネントスキャンによって行われます。
これらのビーンが存在することを確認します。
警告メッセージと404が表示され、上記のすべてが正しく構成されている場合。
であれば、間違ったURIにリクエストを送信していることになります。
によって処理されないもの、検出された
@RequestMapping
アノテーションされたハンドラメソッドによって処理されないものです。
は
spring-webmvc
ライブラリは、他の組み込みの
HandlerMapping
の実装を提供しています。例えば
BeanNameUrlHandlerMapping
地図
URLからスラッシュ("/")で始まる名前のビーンへ。
であり、いつでも自分で書くことができます。明らかに
の少なくとも一つにマッチすることを確認する必要があります。
HandlerMapping
オブジェクトのハンドラの少なくとも一つに一致することを確認しなければなりません。
もし、暗黙的あるいは明示的に任意の
HandlerMapping
ビーンを登録しない場合 (あるいは
detectAllHandlerMappings
が
true
を含む)、その
DispatcherServlet
はいくつかの
のデフォルトを登録します。
. これらは
DispatcherServlet.properties
と同じパッケージで
DispatcherServlet
クラスと同じパッケージ内にあります。それらは
BeanNameUrlHandlerMapping
と
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
の設定を見直してください。
その他のよくある間違い
A
DispatcherServlet
は、単に典型的な Java EE
Servlet
. これを登録すると、典型的な
<web.xml>
<servlet-class>
と
<servlet-mapping>
宣言、あるいは直接
ServletContext#addServlet
の中で
WebApplicationInitializer
で、あるいは Spring boot が使うどんなメカニズムでも構いません。このように、あなたは
urlマッピング
ロジックに依存しなければなりません。
サーブレット仕様
で指定されたロジックは、12章を参照してください。また
この点を考慮すると、よくある間違いは、ServletのURLを登録する際に
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
は報告します。
URI を持つ HTTP リクエストのマッピングが見つかりませんでした
[/Example/WEB-INF/jsps/example-view-name.jsp]
で
DispatcherServlet
を名前 'dispatcher' とする
なぜなら
DispatcherServlet
にマップされるからです。
/*
と
/*
はすべてにマッチしますが(より優先順位の高い完全一致を除く)、このうち
DispatcherServlet
を処理するために選ばれるでしょう。
forward
から
JstlView
(が返す)。
InternalResourceViewResolver
).
ほとんどすべての場合において
DispatcherServlet
はそのようなリクエストを処理するように設定されていないでしょう。
.
その代わりに、この単純なケースでは
DispatcherServlet
を
/
に変更し、デフォルトサーブレットとしてマークします。デフォルトのサーブレットはリクエストに最後にマッチします。これにより、典型的なサーブレットコンテナは内部のサーブレット実装を選択することができ、その実装は
*.jsp
にマップされた内部のサーブレット実装を選び、 JSP リソースを処理することができます (例えば、Tomcat は
JspServlet
というように)、デフォルトのサーブレットで試す前に、JSPリソースを処理します。
あなたの例で見ているのはこれです。
関連
-
Springの設定でxsdファイルのバージョン番号を設定しない方が良い理由
-
StringBuilderが投げるArrayIndexOutOfBoundsExceptionの探索
-
SpringBoot 起動エラー java.nio.charset.MalformedInputException: 入力長 = 2 解決
-
X11 DISPLAY変数が設定されていない」問題の解決方法
-
maven レポート エラー 解決不可能な親POM
-
Javaがリソースリークに遭遇した:'input'が閉じない 解決方法
-
Server Tomcat v9.0 Server at localhost の起動に失敗しました。
-
eclipse 実行 Java、エラー: 選択を起動できず、レシーバーもありません。
-
org.xml.sax.SAXParseExceptionのエラー解決方法
-
[解決済み] Spring MVCの@ResponseBodyメソッドがStringを返すときにHTTP 400エラーで応答するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】DispatcherServletの名前[duplicate]でURI...を持つHTTPリクエストのマッピングが見つからない。]
-
javaの非静的メソッドを静的に参照することができない
-
Git Pull Failed マージされていないファイルがあるため、Pull できません。
-
JAVA_HOME環境変数が正しく定義されていない問題を解決する
-
Junitのユニットテストはjava.lang.Testを報告します。
-
Server Tomcat v9.0 Server at localhost の起動に失敗しました。
-
Web Project JavaでPropertiesファイルを読み込むと、「指定されたファイルがシステムで見つかりません」というソリューションが表示されます。
-
switch case文のcaseの後の列挙定数は列挙型なし
-
htmlとwordの相互変換の実装(画像あり)
-
ApiModel と @ApiModelProperty の使用法