web-dev-qa-db-ja.com

/ *でグローバルフロントコントローラーサーブレットをマッピングするときに静的リソースにアクセスする方法

Spring MVCディスパッチャーを/*のグローバルフロントコントローラーサーブレットとしてマップしました。

<servlet>       
  <servlet-name>home</servlet-name>         
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>     
</servlet>  
<servlet-mapping>       
  <servlet-name>home</servlet-name>         
  <url-pattern>/*</url-pattern>     
</servlet-mapping>

ただし、このマッピングは、すべて/res/フォルダーにあるCSS、JS、画像などの静的ファイルへのアクセスを停止します。

とにかくそれらにアクセスするにはどうすればよいですか?

58
Rahul Garg

私もこれに遭遇しましたが、優れた解決策は見つかりませんでした。私はサーブレットをURL階層の1つ上のレベルにマッピングしました。

<servlet-mapping>       
  <servlet-name>home</servlet-name>             
  <url-pattern>/app/*</url-pattern>     
</servlet-mapping>

これで、ベースコンテキスト(および/ resディレクトリ)にあるすべてのものがコンテナによって提供されます。

12
Gandalf

_url-pattern_のような特定の_/pages/*_にコントローラーサーブレットをマップし、/static_のような特定のフォルダーに静的コンテンツを配置し、_/*_をリッスンするFilterを作成します。静的コンテンツのチェーンを透過的に継続し、他のコンテンツのリクエストをコントローラサーブレットにディスパッチします。

一言で言えば:

_<filter>
    <filter-name>filter</filter-name>
    <filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
    <filter-name>filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
    <servlet-name>controller</servlet-name>
    <servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>controller</servlet-name>
    <url-pattern>/pages/*</url-pattern>
</servlet-mapping>
_

フィルターのdoFilter()に以下を含む:

_HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());

if (path.startsWith("/static")) {
    chain.doFilter(request, response); // Goes to default servlet.
} else {
    request.getRequestDispatcher("/pages" + path).forward(request, response);
}
_

いいえ、これはブラウザのアドレスバーに_/pages_で終わるわけではありません。それは完全に透明です。必要に応じて、フィルターの_"/static"_および/または_"/pages"_を_init-param_にすることができます。

71
BalusC

Spring 3.0.4.RELEASE以上で使用できます

<mvc:resources mapping="/resources/**" location="/public-resources/"/>

Spring Reference で見られるように。

43

Web.xmlにウェルカムファイルを追加します

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
</welcome-file-list>

そして、これをサーブレットマッピングに追加して、誰かがアプリケーションのルートに移動すると、内部でindex.htmlに送信され、マッピングがマッピング先のサーブレットに内部的に送信されるようにします

<servlet-mapping>
    <servlet-name>MainActions</servlet-name>
    <url-pattern>/main</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>MainActions</servlet-name>
    <url-pattern>/index.html</url-pattern>
</servlet-mapping>

最終結果:/ Applicationにアクセスしますが、他のルート要求を中断することなく/ Application/MainActionsサーブレットが表示されます。

それを得る?したがって、アプリは引き続きサブURLに配置されますが、ユーザーがサイトのルートに移動すると自動的に表示されます。これにより、/ images/bob.imgを通常の場所に移動させることができますが、アプリは「/」です。

19
casey

Tomcatを使用する場合、リソースをデフォルトサーブレットにマップできます。

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/static/*</url-pattern>
</servlet-mapping>

url http:// {context path}/static/res/...でリソースにアクセスします.

また、他のサーブレットコンテナについてはわかりませんが、Jettyでも動作します。

17
user112483

複数のサーブレットマッピング定義で適切な接尾辞を持つ静的コンテンツを提供することで、投稿された回答の1つにあるコメントの1つで言及されているセキュリティの問題を解決しました。以下に引用:

これはTomcatのセキュリティホールであり(WEB-INFおよびMETA-INFのコンテンツにはこの方法でアクセスできます)、7.0.4で修正されています(さらに5.xおよび6.xに移植されます)。 – BalusC 10年11月2日22:44

とても助かりました。そして、ここに私がそれを解決した方法があります:

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.html</url-pattern>
</servlet-mapping>
16
GO'

3.0.4の時点で、これを達成するために、春のドキュメントで説明されているように、mvc:resourcesと組み合わせてmvc:default-servlet-handlerを使用できるはずです。

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-static-resources

9
digitaljoel

衝突の理由は、デフォルトでは、コンテキストルート「/」がorg.Apache.catalina.servlets.DefaultServletによって処理されるためだと思われます。このサーブレットは、静的リソースの要求を処理することを目的としています。

動的リクエストを処理する目的で、独自のサーブレットで邪魔にならないようにする場合、その最上位サーブレットは、catalinaの元の「DefaultServlet」ハンドラーによって実行されるタスクも実行する必要があります。

Tomcatのドキュメントを読むと、静的コンテンツの処理に関してTrue Apache(httpd)の方がApache Tomcatよりも優れていると言及されています。私の推測では、Tomcatはデフォルトでorg.Apache.catalina.servlets.DefaultServletを使用して静的リクエストを処理するためです。すべてがJVMにラップされており、TomcatはServlet/JSPコンテナとして意図されているため、おそらく、そのクラスを超最適化された静的コンテンツハンドラとして記述していません。それはそこにある。それは仕事を終わらせます。十分です.

しかし、それは静的コンテンツを処理するものであり、「/」に存在します。したがって、他に何かを配置し、そのリクエストが静的なリクエスト(WHOOPS)を処理しない場合、静的なリソースが使用されます。

私は同じ答えを求めて高いところと低いところを探してきましたが、私がどこでも得ている答えは「あなたがそれをしたくないなら、それをしないでください」です。

要するに、あなたの構成は、デフォルトの静的リソースハンドラを、静的リソースハンドラではないものに置き換えています。探している結果を得るには、別の構成を試す必要があります(私もそうです)。

5
Bill

App Engineの「静的」ファイルには、アプリから直接アクセスできません。静的ハンドラーを使用するのではなく、2回アップロードするか、静的ファイルを自分で提供する必要があります。

3
Nick Johnson

これを処理する最善の方法は、何らかのURL書き換えを使用することです。このようにして、abc.com/welcome/resister.htmlとは対照的にabc.com/welcom/registerのような拡張子のない、きれいで安らかなURLを使用できます。

Tuckey URL を使用しますが、これはかなりクールです。

Webアプリのセットアップ方法についての説明があります。SpringMVC Webアプリでセットアップしました。もちろん、ドメインオブジェクトに@Email@NullなどのSpring 3検証用のアノテーションを使用するまで、すべてが順調でした。

Spring mvcディレクティブを追加すると:

< mvc:annotation-driven  /> 
< mvc:default-servlet-handler />

..旧式のTuckeyコードを壊します。どうやら、< mvc:default-servlet-handler />はTuckeyに取って代わり、私はまだ解決しようとしています。

2
logixplayer

サーブレット処理をトリガーしないフォルダーを、appengine-web.xmlファイルの<static-files>セクションに追加します。

私はちょうどこれをやったし、物事がうまく動作し始めているように見えます。これが私の構造です:

/

/pages/<.jsp files>

/ css

「/ pages/**」と「/ css/**」を<static-files>セクションに追加し、サーブレットdoGet内から無限ループを引き起こすことなく.jspファイルに転送できるようになりました。

1
MStodd

私はそれを使用して見つけた

<mvc:default-servlet-handler />

春のMVCサーブレットBean定義ファイルでは私のために機能します。登録されたMVCコントローラーによって処理されない要求は、コンテナーの元のデフォルトハンドラーに渡されます。このハンドラーは、静的コンテンツとして提供する必要があります。すべてを処理するコントローラーが登録されていないことを確認してください。正常に機能するはずです。 @logixplayerがURLの書き換えを提案する理由がわかりません。 Spring MVCのみを使用して、彼が探している効果を適切に達成できます。

1
Jules

フィルターアプローチを成功せずに試行した後(何らかの理由でdoFilter()関数を入力しなかった)、セットアップを少し変更し、ルートサービングの問題に対する非常に簡単な解決策を見つけました。

メインサーブレットで「/ *」を提供する代わりに、専用の言語プレフィックス「EN」、「EN/*」、「DE」、「DE/*」のみをリッスンするようになりました

静的コンテンツはデフォルトのサーブレットによって提供され、空のルートリクエストはindex.jspに送られ、デフォルトの言語でメインサーブレットが呼び出されます。

<jsp:include page = "/ EN /" />(インデックスページには他のコンテンツはありません。)

1
sebut

可能な限り、デフォルトのサーブレットの代わりにフィルターを使用することをお勧めします。

他の2つの可能性:

自分でFileServletを作成します。多くの例があります。URLでファイルを開き、その内容を出力ストリームに書き込むだけです。次に、それを使用して静的ファイル要求を処理します。

Google App Engineが使用するFileServletクラスをインスタンス化し、特定のURLで静的ファイルを提供する必要がある場合、そのFileServletでservice(request、response)を呼び出します。

/ res/*をYourFileServletまたはDispatcherServletの処理から除外するものにマッピングするか、DispatcherServletから直接呼び出すことができます。

そして、Springのドキュメントはこの衝突について何と言っているのでしょうか?私は一度も使ったことがない。

0
alamar

Tomcatに関しては、特定のバージョンに大きく依存します。バグ修正がありました https://bz.Apache.org/bugzilla/show_bug.cgi?id=50026 これは、デフォルトサーブレットのサーブレットマッピング(「/」以外)が動作することを意味しますTomcat 6.0.29(およびそれ以前)では、それ以降のバージョンと比較して異なります。

0
Mike Beaumont

Embedded Jettyでは、web.xmlの「css」ディレクトリのマッピングを追加することで、同様のことを達成できました。 DefaultServletを使用するよう明示的に指示します。

<servlet>
  <servlet-name>DefaultServlet</servlet-name>
  <servlet-class>org.Eclipse.jetty.servlet.DefaultServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>DefaultServlet</servlet-name>
  <url-pattern>/css/*</url-pattern>
</servlet-mapping>
0
QaZ

ダミーのインデックスファイルを使用したより簡単なソリューションを見つけました。

「/index.html」にマッピングするサーブレットを作成します(または「/」に応答するサーブレットを使用します) 「index.html」という名前の静的コンテンツのルートにある(空の)ファイル

私はJettyを使用していましたが、ディレクトリをリストする代わりにサーバーがファイルを認識しましたが、リソースを要求されたときに、サーブレットが代わりに制御を取得しました。他のすべての静的コンテンツは影響を受けませんでした。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:default-servlet-handler/>
</beans>

注釈ベースの構成を使用する場合は、以下のコードを使用します

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