私は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'
/WEB-INF/jsps/index.jsp
にJSPリソースがあります。Spring MVCはリクエストを処理してJSPに転送するために私のコントローラを使用すると思っていましたが、なぜ404で応答するのでしょうか。
これは、この警告メッセージに関する質問の正規の投稿です。
標準のSpring MVCアプリケーションは、サーブレットコンテナに登録した DispatcherServlet
を介してすべてのリクエストを処理します。
DispatcherServlet
は、そのApplicationContext
を調べ、使用可能な場合は、要求処理ロジックをセットアップするために必要な特別なBeanのApplicationContext
に登録されているContextLoaderListener
を調べます。 これらのBeanはドキュメントに記載されています 。
おそらく最も重要な、タイプ HandlerMapping
のBean
ハンドラーへの着信要求、および
HandlerMapping
実装によって詳細が異なるいくつかの基準に基づくプリプロセッサーとポストプロセッサー(ハンドラーインターセプター)のリスト。最も一般的な実装は注釈付きコントローラをサポートしていますが、他の実装も存在します。
HandlerMapping
のjavadoc は、実装の動作方法をさらに説明しています。
DispatcherServlet
は、このタイプのすべてのBeanを検出し、それらを何らかの順序で登録します(カスタマイズ可能)。リクエストの処理中、DispatcherServlet
はこれらのHandlerMapping
オブジェクトをループし、それぞれを getHandler
でテストして、標準のHttpServletRequest
として表される着信リクエストを処理できるオブジェクトを見つけます。 4.3.x現在、見つからない場合、それは 警告をログに記録
SomeNameという名前の
DispatcherServlet
のURI[/some/path]
のHTTP要求のマッピングが見つかりません
および either は NoHandlerFoundException
をスローするか、404 Not Foundステータスコードで応答を直ちにコミットします。
DispatcherServlet
がリクエストを処理できるHandlerMapping
を見つけられなかったのはなぜですか?最も一般的なHandlerMapping
実装は RequestMappingHandlerMapping
で、これは@Controller
Beanをハンドラーとして登録します(実際には@RequestMapping
アノテーション付きメソッド)。この型のBeanは(@Bean
または<bean>
または他のメカニズムを使用して)自分で宣言するか、または 組み込みオプション を使用できます。これらは:
@Configuration
クラスに@EnableWebMvc
アノテーションを付けます。<mvc:annotation-driven />
メンバーを宣言します。上記のリンクで説明されているように、これらは両方ともRequestMappingHandlerMapping
Bean(およびその他の多くのBean)を登録します。ただし、HandlerMapping
はハンドラーなしではあまり役に立ちません。 RequestMappingHandlerMapping
はいくつかの@Controller
Beanを想定しているため、Java構成の@Bean
メソッド、XML構成の<bean>
宣言、またはいずれかの@Controller
注釈付きクラスのコンポーネントスキャンを介して、これらも宣言する必要があります。 これらのBeanが存在することを確認してください。
警告メッセージと404を受け取っていて、上記のすべてを正しく構成している場合、リクエストを間違ったURIに送信している、検出されたものによって処理されないもの@RequestMapping
アノテーション付きハンドラーメソッド。
spring-webmvc
ライブラリは、他の組み込みHandlerMapping
実装を提供します。たとえば、 BeanNameUrlHandlerMapping
maps
uRLから、スラッシュ(「/」)で始まる名前のBeanへ
いつでも自分で書くことができます。明らかに、送信するリクエストが登録済みのHandlerMapping
オブジェクトのハンドラーの少なくとも1つと一致することを確認する必要があります。
HandlerMapping
Beanを暗黙的または明示的に登録しない場合(または detectAllHandlerMappings
がtrue
の場合)、DispatcherServlet
はいくつかの デフォルト を登録します。これらは、DispatcherServlet
クラスと同じパッケージの DispatcherServlet.properties
で定義されています。それらは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
設定を確認してください。
DispatcherServlet
は、典型的なJava EE Servlet
です。通常の<web.xml>
<servlet-class>
および<servlet-mapping>
宣言、または ServletContext#addServlet
で直接 WebApplicationInitializer
に登録するか、Springブートが使用するメカニズムで登録します。そのため、 サーブレット仕様 で指定されたurl mappingロジックに依存する必要があります。第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;
}
パス/WEB-INF/jsps/example-view-name.jsp
のJSPリソースへのリクエストは forwarded であると期待するかもしれません。これは起こりません。代わりに、Example
のコンテキスト名を仮定すると、DisaptcherServlet
は
名前が「dispatcher」の
DispatcherServlet
のURI[/Example/WEB-INF/jsps/example-view-name.jsp]
のHTTP要求のマッピングが見つかりません
DispatcherServlet
は/*
にマップされ、/*
はすべてに一致するため(優先順位がより高い完全一致を除く)、- DispatcherServlet
(forward
によって返される)からJstlView
を処理するためにInternalResourceViewResolver
が選択されます。 ほとんどの場合、DispatcherServlet
はそのような要求を処理するように構成されません。
代わりに、この単純なケースでは、DispatcherServlet
を/
に登録して、デフォルトのサーブレットとしてマークする必要があります。デフォルトのサーブレットは、リクエストの最後の一致です。これにより、通常のサーブレットコンテナは、*.jsp
にマッピングされた内部サーブレット実装を選択して、デフォルトサーブレットを試す前に、JSPリソース(たとえば、Tomcatに JspServlet
)を処理できます。
それはあなたの例で見ているものです。
前述したことに加えて、私は自分の問題を解決しました: `
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
added Tomcat-embed-jasper:
<dependency>
<groupId>org.Apache.Tomcat.embed</groupId>
<artifactId>Tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
私の場合は、 バージョン5.1.2用のInterceptors Springのドキュメント (Spring Boot v2.0.4を使用しています。RELEASEWebConfig
クラスはアノテーション@EnableWebMvc
を持っていました。それは私の静的アセットが正しく解決されるのを妨げていた(つまりCSSまたはJSファイルがクライアントに返されていない)私のアプリケーションの他の何かと衝突しているようです。
いろいろなことを試した後、私は@EnableWebMvc
を削除してみましたが、うまくいきました!
編集: これは参考ドキュメントです つまり@EnableWebMvc
アノテーションを削除するべきです
少なくとも私の場合では、私はすでにSpringアプリケーションを設定しています(web.xml
や他の静的ファイルを使用しているわけではありませんが、それは間違いなくプログラム的なものです)。
私は同じエラーの別の理由に出会いました。これはまた、controller.Javaファイル用に生成されていないクラスファイルが原因である可能性もあります。その結果、web.xmlに記載されているディスパッチャサーブレットはコントローラクラスの適切なメソッドにそれをマッピングすることができません。
@Controller
Class Controller{
@RequestMapping(value="/abc.html")//abc is the requesting page
public void method()
{.....}
}
Eclipseで、プロジェクト - >クリーンの選択 - >プロジェクトのビルドを選択します。クラスファイルが、ワークスペースのビルド中のコントローラファイルに対して生成されているかどうかを確認します。
私にとっては、私のターゲットクラスはsourceと同じではないフォルダパターンで生成されていることがわかりました。これはおそらくEclipseで私は私のコントローラを格納するためのフォルダを追加し、パッケージとして追加するのではありません。だから私は春の設定で間違ったパスを定義することになった。
私のターゲットクラスはappの下でクラスを生成していました、そして私はcom.happy.appを参照していました
<context:annotation-config />
<context:component-scan
base-package="com.happy.app"></context:component-scan>
私はcom.happy.appのパッケージ(フォルダではない)を追加し、ファイルをフォルダからEclipseのパッケージに移動し、問題を解決しました。