web-dev-qa-db-ja.com

サーブレットマッピングURLパターンの/と/ *の違い

おなじみのコード:

<servlet-mapping>
    <servlet-name>main</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>main</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

私の理解では、/*http://Host:port/context/*にマップされます。

/はどうですか?確かに、http://Host:port/contextルートのみにマップされません。実際、http://Host:port/context/helloは受け入れますが、http://Host:port/context/hello.jspは拒否します。

http://Host:port/context/helloがどのようにマップされるかを説明できますか?

168
Candy Chiu

<url-pattern>/*</url-pattern>

サーブレットの/*は、デフォルトサーブレットやJSPサーブレットなど、サーブレットコンテナが提供するすべてのサーブレットを含む、他のすべてのサーブレットをオーバーライドします。どのようなリクエストを発行しても、そのサーブレットで終了します。したがって、これはサーブレットの不適切なURLパターンです。通常、 Filter でのみ/*を使用します。 FilterChain#doFilter() を呼び出すことにより、より具体的なURLパターンをリッスンしているサーブレットのいずれかにリクエストを継続させることができます。

<url-pattern>/</url-pattern>

/は、他のサーブレットをオーバーライドしません。他の登録済みサーブレットと一致しないすべてのリクエストに対して、servletcontainerの組み込みのデフォルトサーブレットのみを置き換えます。これは通常、静的リソース(CSS/JS/image/etc)およびディレクトリリストでのみ呼び出されます。 servletcontainerの組み込みのデフォルトサーブレットは、HTTPキャッシュリクエスト、メディア(オーディオ/ビデオ)ストリーミング、およびファイルダウンロードの再開も処理できます。通常、すべてのタスクを処理する必要があるため、デフォルトのサーブレットをオーバーライドする必要はありません。これは、決して簡単ではありません(JSFユーティリティライブラリ OmniFaces には オープンソース )。したがって、これは、サーブレットの不適切なURLパターンでもあります。 JSPページがこのサーブレットにヒットしない理由は、サーブレットコンテナの組み込みJSPサーブレットが呼び出されるためです。これは、デフォルトで、より具体的なURLパターン*.jspにすでにマップされています。

<url-pattern></url-pattern>

次に、空の文字列URLパターンもあります。これは、コンテキストルートが要求されたときに呼び出されます。これは、サブフォルダーが要求されたときに呼び出されない <welcome-file> アプローチとは異なります。これは、 " home page servlet "が必要な場合に実際に探しているURLパターンです。空の文字列URLパターンとスラッシュURLパターン/が逆の方法で正確に定義されることを直感的に期待していることを認めるだけなので、多くのスターターがこれについて混乱していることを理解できます。しかし、それはそれです。

フロントコントローラー

実際にフロントコントローラーサーブレットを使用する場合は、*.html*.do/pages/*などのより具体的なURLパターンにマッピングするのが最適です。 /app/*など。フロントコントローラーのURLパターンを非表示にし、サーブレットフィルターの助けを借りて、/resources/*/static/*などの一般的なURLパターンの静的リソースをカバーできます。 / *にマップされているフロントコントローラーサーブレットによって静的リソースが処理されるのを防ぐ方法 も参照してください。 Spring MVCには静的リソースサーブレットが組み込まれているため、Springで静的リソースの共通URLパターンを構成する場合は、そのフロントコントローラーを/にマップできることに注意してください。 Spring MVCで静的コンテンツを処理する方法 も参照してください。

251
BalusC

BalusCの答えをマッピングルールと例で補足したいと思います。

サーブレット2.5仕様のマッピングルール:

  1. 正確なURLをマップ
  2. ワイルドカードパスをマップする
  3. 地図表示オプション
  4. デフォルトのサーブレットにマップする

この例では、3つのサーブレットがあります。 /は、当社がインストールするデフォルトのサーブレットです。 Tomcatは、jspとjspxにサービスを提供する2つのサーブレットをインストールします。したがって、http://Host:port/context/helloをマップするには

  1. 次に、正確なURLサーブレットがインストールされていません。
  2. 次に、ワイルドカードパスサーブレットがインストールされていません。
  3. 次に、どの拡張子とも一致しません。
  4. デフォルトのサーブレットにマップして、戻ります。

http://Host:port/context/hello.jspをマップするには

  1. 次に、正確なURLサーブレットがインストールされていません。
  2. 次に、ワイルドカードパスサーブレットがインストールされていません。
  3. 拡張サーブレットが見つかりました。戻ります。
42
Candy Chiu

404に何時間も苦しんでいたので、おそらくURLもどのようにマッピングされるかを知る必要があります。リクエストを処理するハンドラには2種類あります。 BeanNameUrlHandlerMappingおよびSimpleUrlHandlerMappingservlet-mappingを定義したとき、SimpleUrlHandlerMappingを使用しています。知っておく必要があることの1つは、これら2つのハンドラーがalwaysUseFullPathと呼ばれる共通のプロパティを共有していることで、デフォルトではfalseです。

ここでfalseは、SpringがURLをコントローラーにマッピングするために絶対パスを使用しないことを意味します。どういう意味ですか? servlet-mappingを定義するとき:

<servlet-mapping>
    <servlet-name>viewServlet</servlet-name>
    <url-pattern>/perfix/*</url-pattern>
</servlet-mapping>

ハンドラーは実際に*部分を使用してコントローラーを見つけます。たとえば、次のコントローラーは、404を使用して要求すると、/perfix/api/feature/doSomethingエラーに直面します。

@Controller()
@RequestMapping("/perfix/api/feature")
public class MyController {
    @RequestMapping(value = "/doSomething", method = RequestMethod.GET) 
    @ResponseBody
    public String doSomething(HttpServletRequest request) {
        ....
    }
}

完璧にマッチしていますよね?しかし、なぜ404。前述のように、alwaysUseFullPathのデフォルト値はfalseです。つまり、リクエストでは/api/feature/doSomethingのみが対応するコントローラーを見つけるために使用されますが、コントローラーはそのパスを気にしません。 URLを/perfix/perfix/api/feature/doSomethingに変更するか、MyControllerベース@RequestingMappingからperfixを削除する必要があります。

22
hakunami

キャンディの答えはほとんど正しいと思います。そうでないと思う小さな部分が一つあります。

Host:port/context/hello.jspをマップするには

  1. 次に、正確なURLサーブレットがインストールされていません。
  2. ワイルドカードパスサーブレットが見つかりました、戻ります。

「/ *」がHost:port/context/helloと一致しない理由は、「/ hello」をファイルではなくパスとして扱うためです(拡張子がないため)。

8
hehe

/*/の本質的な違いは、/*のマッピングを持つサーブレットが拡張マッピング(*.htmlなど)のあるサーブレットの前に選択されるのに対し、/のマッピングを持つサーブレットは拡張マッピングが考慮された後にのみ選択されることです(そして、他の何にも一致しないリクエスト---それは「デフォルトサーブレット」です)。

特に、/*マッピングの前に、/マッピングが常に選択されます。いずれかを使用すると、リクエストがコンテナのデフォルトのサーブレットに到達しなくなります。

どちらかは、完全に一致するサーブレットマッピング(/foo/barなど)と、/*よりも長いパスマッピング(/foo/*など)の後にのみ選択されます。空の文字列マッピングは、コンテキストルート(http://Host:port/context/)と完全に一致することに注意してください。

http://download.Oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/indexのバージョン3.1で利用可能なJavaサーブレット仕様の第12章を参照してください。 html