Spring MVCが404で応答し、「DispatcherServletでURI […]を使用したHTTPリクエストのマッピングが見つかりません」と報告するのはなぜですか?


91

TomcatにデプロイされたSpringMVCアプリケーションを作成しています。次の最小限の完全で検証可能な例を参照してください

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.jspSpring MVCがコントローラーを使用してリクエストを処理してJSPに転送することを期待していたのに、JSPリソースがありますが、なぜ404で応答するのですか?


これは、この警告メッセージに関する質問の正規の投稿となることを目的としています。

回答:


100

標準のSpringMVCアプリケーションはDispatcherServlet、サーブレットコンテナに登録したを介してすべてのリクエストを処理します。

DispatcherServlet見て、ApplicationContext可能な場合ApplicationContextContextLoaderListener、特別な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。これは、@ControllerBeanをハンドラー(実際には@RequestMappingアノテーション付きメソッド)として登録することを処理します。このタイプのBeanを(@Beanまたは<bean>または他のメカニズムを使用し)自分で宣言するか、組み込みオプションを使用することができます。これらは:

  1. @Configurationクラスに@EnableWebMvc。で注釈を付けます。
  2. <mvc:annotation-driven />XML構成でメンバーを宣言します。

上記のリンクで説明されているように、これらは両方ともRequestMappingHandlerMappingBean(および他の多くのもの)を登録します。ただし、aHandlerMappingはハンドラーなしではあまり役に立ちません。RequestMappingHandlerMapping一部の@ControllerBeanを想定しているため@Bean、Java構成のメソッド<bean>、XML構成の宣言、または@Controllerいずれかの注釈付きクラスのコンポーネントスキャンを通じて、それらも宣言する必要があります。これらのBeanが存在することを確認してください。

警告メッセージと404が表示され、上記のすべてを正しく構成した場合は、検出された@RequestMappingアノテーション付きハンドラーメソッドによって処理されない間違ったURIにリクエストを送信しています

spring-webmvc内蔵された他のライブラリの提供HandlerMappingの実装。たとえば、BeanNameUrlHandlerMapping地図

URLからスラッシュ( "/")で始まる名前のBeanへ

そして、あなたはいつでもあなた自身を書くことができます。明らかに、送信するリクエストが、登録されたHandlerMappingオブジェクトのハンドラーの少なくとも1つと一致することを確認する必要があります。

あなたが暗黙的または明示的に登録していない場合はHandlerMapping豆(または場合detectAllHandlerMappingsであるがtrue)、DispatcherServletいくつかのレジスタのデフォルトを。これらはDispatcherServlet.propertiesDispatcherServletクラスと同じパッケージで定義されています。それらはBeanNameUrlHandlerMappingandです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をここにリストされているマッピングと比較します。@RequestMappingSpring MVCがハンドラーを選択するには、で指定されたすべての制限が一致する必要があります。

他のHandlerMapping実装は、マッピングと対応するハンドラーを示唆する独自のステートメントをログに記録します。

同様に、DEBUGレベルでSpringロギングを有効にして、Springが登録するBeanを確認します。検出した注釈付きクラス、スキャンするパッケージ、および初期化するBeanを報告する必要があります。期待したものが存在しない場合は、ApplicationContext構成を確認してください。

その他のよくある間違い

ADispatcherServletは典型的なJavaEEServletです。あなたの典型的なとあなたはそれを登録<web.xml> <servlet-class>し、<servlet-mapping>宣言、または直接通じServletContext#addServletWebApplicationInitializer、または任意のメカニズム春ブーツ用途に。そのため、サーブレット仕様で指定されている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。これは起こりません。代わりに、のコンテキスト名を想定しExampleDisaptcherServlet報告します

'dispatcher'という名前のURI[/Example/WEB-INF/jsps/example-view-name.jsp]DispatcherServlet持つHTTPリクエストのマッピングが見つかりません

ためDispatcherServletにマッピングされる/*/*(より高い優先度を有する完全一致、除く)すべて一致、DispatcherServlet処理するために選択されるであろうforwardからJstlView(によって返されますInternalResourceViewResolver)。ほとんどの場合、はDispatcherServletそのような要求を処理するように構成されていません

代わりに、この単純なケースでは、DispatcherServlettoを登録して/、デフォルトのサーブレットとしてマークする必要があります。デフォルトのサーブレットは、リクエストの最後の一致です。これにより、通常のサーブレットコンテナは、デフォルトのサーブレットを試す前に、にマップされた内部サーブレット実装を選択して*.jsp、JSPリソース(たとえば、Tomcatが持っているJspServlet)を処理できるようになります。

それはあなたがあなたの例で見ているものです。


@EnableWebMvcを使用すると、dispatcherServletはすでに/に登録されています。「リクエストがパス/WEB-INF/jsps/example-view-name.jspのJSPリソースに転送されることを期待するかもしれません。これは起こりません。」そのパスでJSPリソースに転送するように、どのように機能させますか?それは基本的に尋ねられた質問です。
Tor

@Torそれ自体で@EnableWebMvcは、@Configurationアノテーション付きクラスではそれを行いません。いくつかのデフォルトのSpringMVCハンドラー/アダプターBeanをアプリケーションコンテキストに追加するだけです。DispatcherServlet提供するサービスの登録/は、その他のよくある間違いのセクションで説明するいくつかの方法で行われる完全に別個のプロセスです。私はあなたが引用したものの下の2つの段落で尋ねられた質問に答えます。
SotiriosDelimanolis18年

5

前に説明したことに加えて、問題を解決しました: `

@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>

`from:Spring BootWebアプリケーションでJSPファイルがレンダリングされない


2

私の場合、バージョン5.1.2のInterceptors Springドキュメントに従って(Spring Boot v2.0.4.RELEASEを使用している間)、WebConfigクラスにアノテーション@EnableWebMvcがありました。これは、静的を妨げていたアプリケーション内の他の何かと競合しているようです。アセットが正しく解決されない(つまり、CSSまたはJSファイルがクライアントに返されていなかった)。

いろいろ試してみた後、削除@EnableWebMvcてみたらうまくいきました!

編集:注釈を削除する必要があると記載されているリファレンスドキュメントは次のとおりです@EnableWebMvc

どうやら少なくとも私の場合、私はすでにSpringアプリケーションを構成しているので(web.xml他の静的ファイルを使用するのではなく、間違いなくプログラムで)、そこで競合が発生しました。


1

設定ファイルを次のように変更して、コードを修正してみてください。の代わりにJava構成が使用されますapplication.propertiesconfigureDefaultServletHandlingメソッドで構成を有効にすることを忘れないでください。

WebMvcConfigurerAdapterクラスは非推奨であるため、WebMvcConfigurerインターフェイスを使用します。

@Configuration
@EnableWebMvc
@ComponentScan
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

私はgradleを使用していますが、次の依存関係があるはずですpom.xml

dependencies {

    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.3.0.RELEASE'
    compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '9.0.35'
}

0

同じエラーの別の理由に出くわしました。これは、controller.javaファイル用に生成されていないクラスファイルが原因である可能性もあります。その結果、web.xmlに記載されているディスパッチャーサーブレットは、コントローラークラスの適切なメソッドにマップできません。

@Controller
Class Controller{
@RequestMapping(value="/abc.html")//abc is the requesting page
public void method()
{.....}
}

Eclipseの[プロジェクト]-> [クリーン]-> [ビルドプロジェクト]を選択します。ワークスペースのビルドでコントローラーファイルのクラスファイルが生成されているかどうかを確認してください。


0

私の場合、ターゲットクラスがソースとは異なるフォルダーパターンで生成されていることがわかりました。これはおそらくEclipseにあり、コントローラーを格納するためのフォルダーを追加し、パッケージとして追加しません。だから私は春の設定で間違ったパスを定義することになりました。

私のターゲットクラスはアプリの下でクラスを生成していて、com.happy.appを参照していました

<context:annotation-config />
<context:component-scan
    base-package="com.happy.app"></context:component-scan> 

com.happy.appのパッケージ(フォルダーではない)を追加し、ファイルをフォルダーからEclipseのパッケージに移動したところ、問題が解決しました。


0

サーバーをクリーンアップします。たぶん、サーバーを削除し、プロジェクトをもう一度追加して実行します。

  1. Tomcatサーバーを停止します

  2. サーバーを右クリックして「クリーン」を選択します

  3. サーバーをもう一度右クリックし、「Tomcat作業ディレクトリのクリーンアップ」を選択します


0

私の場合、セカンダリJava設定ファイルをメインJava設定ファイルにインポートして遊んでいました。セカンダリ構成ファイルの作成中に、メイン構成クラスの名前を変更しましたが、web.xmlの名前を更新できませんでした。そのため、Tomcatサーバーを再起動するたびに、Eclipse IDEコンソールにマッピングハンドラーが表示されませんでした。ホームページに移動しようとすると、次のエラーが表示されました。

2019年11月1日23:00:01org.springframework.web.servlet.PageNotFound noHandlerFound警告:「dispatcher」という名前のDispatcherServletにURI [/ webapp / home / index]のHTTPリクエストのマッピングが見つかりません

修正は、古い名前「WebConfig」が代わりに「MainConfig」になるようにweb.xmlファイルを更新し、メインのJava構成ファイルの最新の名前を反映するように名前を変更することでした(「MainConfig」は任意で、「ここで使用されている「Web」と「Main」は構文要件ではありません)。MainConfigは重要でした。これは、Webリクエストを処理するSpringMVCコントローラークラスである「WebController」のコンポーネントスキャンを実行したファイルであるためです。

@ComponentScan(basePackageClasses={WebController.class})

web.xmlにはこれがありました:

<init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        com.lionheart.fourthed.config.WebConfig
    </param-value>
</init-param>

web.xmlファイルには次のものがあります。

<init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        com.lionheart.fourthed.config.MainConfig
    </param-value>
</init-param>

これで、コンソールウィンドウにマッピングが表示されます。

情報:「{[/ home / index]、methods = [GET]}」をpublicorg.springframework.web.servlet.ModelAndView com.lionheart.fourthed.controller.WebController.gotoIndex()にマップしました

そして、私のWebページが再び読み込まれています。


-1

私はと同じ問題を抱えていました **No mapping found for HTTP request with URI [/some/path] in DispatcherServlet with name SomeName**

2〜4日間分析した後、根本的な原因を突き止めました。プロジェクトを実行した後、クラスファイルが生成されませんでした。プロジェクトタブをクリックしました。

プロジェクト-> CloseProject-> OpenProject-> Clean->ビルドプロジェクト

ソースコードのクラスファイルが生成されました。それは私の問題を解決しました。クラスファイルが生成されているかどうかを確認するには、プロジェクトフォルダのビルドフォルダを確認してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.