web-dev-qa-db-ja.com

Spring MVCで静的コンテンツを処理する方法は?

私はSpring MVC 3を使用してwebappを開発しており、DispatcherServletが '/'へのすべてのリクエストをキャッチしています(web.xml):

  <servlet>
    <servlet-name>app</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>

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

これは広告どおりに機能しますが、静的コンテンツをどのように処理できますか?以前は、RESTful URLを使用する前に、たとえばすべての* .htmlをキャッチし、それをDispatcherServletに送信していましたが、現在は別のボールゲームです。

/ styles /、/ js /、/ images /などを含む/ static /フォルダーがあり、DispatcherServletから/ static/*を除外したいと思います。

これで、静的リソースが機能するようになりました。

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

しかし、www.domain.com/app /であるランディングページではなく、Nice URL(Spring MVC 3を使用する私のポイント)が必要です。

また、Tomcatや他のサーブレットコンテナに結合されたソリューションも必要ありません。これは(比較的)トラフィックが少ないため、Webサーバー(Apache httpdなど)は必要ありません。

これにきれいな解決策はありますか?

192
hamo

私はこの問題に多くの時間を費やしていたので、自分の解決策を共有すると思いました。春3.0.4以降、<mvc:resources/>と呼ばれる設定パラメーターがあります(詳細については 参照ドキュメントWebサイト )。これは、サイトのルートでDispatchServletを使用しながら静的リソースを提供するために使用できます。

これを使用するには、次のようなディレクトリ構造を使用します。

src/
 springmvc/
  web/
   MyController.Java
WebContent/
  resources/
   img/
    image.jpg
  WEB-INF/
    jsp/
      index.jsp
    web.xml
    springmvc-servlet.xml

ファイルの内容は次のようになります。

src/springmvc/web/HelloWorldController.Java:

package springmvc.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloWorldController {

 @RequestMapping(value="/")
 public String index() {
  return "index";
 }
}

WebContent/WEB-INF/web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://Java.Sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://Java.Sun.com/xml/ns/j2ee 
         http://Java.Sun.com/xml/ns/j2ee/web-app_2_4.xsd">

 <servlet>
  <servlet-name>springmvc</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>springmvc</servlet-name>
  <url-pattern>/</url-pattern>
 </servlet-mapping>
</web-app>

WebContent/WEB-INF/springmvc-servlet.xml:

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

    <!-- not strictly necessary for this example, but still useful, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-controller for more information -->
 <context:component-scan base-package="springmvc.web" />

    <!-- the mvc resources tag does the magic -->
 <mvc:resources mapping="/resources/**" location="/resources/" />

    <!-- also add the following beans to get rid of some exceptions -->
 <bean      class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
 <bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
 </bean>

    <!-- JSTL resolver -->
 <bean id="viewResolver"
  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass"
   value="org.springframework.web.servlet.view.JstlView" />
  <property name="prefix" value="/WEB-INF/jsp/" />
  <property name="suffix" value=".jsp" />
 </bean>

</beans>

WebContent/jsp/index.jsp:

<%@ taglib prefix="c" uri="http://Java.Sun.com/jsp/jstl/core" %>
<h1>Page with image</h1>
<!-- use c:url to get the correct absolute path -->
<img src="<c:url value="/resources/img/image.jpg" />" />

お役に立てれば :-)

259
Joris

この問題は、Springディスパッチャ設定ファイルで<mvc:resources mapping="..." location="..."/>設定要素を使用できるspring 3.0.4.RELEASEで解決されます。

チェック 春のドキュメント

47
rozky

Spring 3.0.xで、servlet-config.xmlに次を追加します(web.xmlでcontextConfigLocationとして設定されているファイル。mvc名前空間も追加する必要がありますが、方法がわからない場合はそのためにgoogleするだけです) !;)

それは私のために働く

<mvc:default-servlet-handler/>

よろしく

アユブ・マリク

38
Ayub Malik

あなたの問題を正しく理解していれば、あなたの問題の解決策を見つけたと思います。

Cssスタイル、javascripts、jqueryファイルが見つからずに生の出力が表示されるという同じ問題がありました。

「デフォルト」サーブレットにマッピングを追加しました。 web.xmlファイルに次が追加されました。

 <servlet-mapping>
  <servlet-name>default</servlet-name>
  <url-pattern>*.css</url-pattern>
 </servlet-mapping>

 <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
 </servlet-mapping>

これにより、DispatcherRequestオブジェクトからのjavascriptおよびcssファイルリクエストが除外されます。

繰り返しますが、これがあなたが望んでいるものかどうかはわかりませんが、私にとってはうまくいきました。 「デフォルト」はJBoss内のデフォルトサーブレットの名前だと思います。それが他のサーバーにとって何であるかはあまりわかりません。

19
user243397

excellent solution を持つ別のスタックオーバーフローポストがあります。

Tomcat固有ではないようで、シンプルで、うまく機能します。この投稿でいくつかのソリューションをspring mvc 3.1で試しましたが、動的コンテンツを配信するのに問題がありました。

簡単に言うと、次のようなサーブレットマッピングを追加します。

<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/images/*</url-pattern>
</servlet-mapping>
15
user1788698

私はSpring MVC 3.0でこの問題に取り組んでおり、最初にUrlRewriteFilterオプションを使用しました。しかし、このソリューションが「気分が悪い」という理由で不満でした(私だけではありません。「ハック」という言葉が何度か現れるSpringフォーラムへのリンクを参照してください)。

そこで、上記の「Unknown(Google)」と同様のソリューションを思い付きましたが、すべての静的コンテンツを/ static /(Pet StoreアプリのSpring Rooバージョンから取得)から提供するという考えを取り入れました。 「デフォルト」サーブレットは機能しませんでしたが、Spring Webflow ResourceServletは機能しました(Spring Rooが生成したアプリからも取得しました)。

Web.xml:

<servlet>
    <servlet-name>mainDispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>

<servlet>
    <servlet-name>Resource Servlet</servlet-name>
    <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

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

<servlet-mapping>
    <servlet-name>Resource Servlet</servlet-name>
    <url-pattern>/static/*</url-pattern>
</servlet-mapping>

JSPに対して行った唯一の変更は、CSS、JS、および画像のURLに/ static /パスを追加することでした。例えば。 「$ {pageContext.request.contextPath} /static/css/screen.css」。

mavenユーザーの場合、「org.springframework.js.resource.ResourceServlet」の依存関係は次のとおりです。

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>org.springframework.js</artifactId>
    <version>2.0.8.RELEASE</version>
</dependency>
12
nickdos

Tuckeyのurlrewritefilterを使用してそれを回避する方法を見つけました。回答がある場合は、お気軽にお問い合わせください!

Web.xmlで:

<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

  <servlet>
    <servlet-name>app</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>

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

Urlrewrite.xmlで:

<urlrewrite default-match-type="wildcard">
<rule>
    <from>/</from>
    <to>/app/</to>
</rule>
<rule match-type="regex">
    <from>^([^\.]+)$</from>
    <to>/app/$1</to>
</rule>
<outbound-rule>
    <from>/app/**</from>
    <to>/$1</to>
</outbound-rule>    

これは、「。」が付いたURIを意味します。その中(たとえばstyle.cssなど)は書き換えられません。

11
hamo

この問題に関する私自身の経験は次のとおりです。ほとんどのSpring関連のWebページと本は、最も適切な構文は次のとおりであることを示唆しているようです。

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

上記の構文は、静的リソース(CSS、JavaScript、画像)をアプリケーションのルート(「/ webapp/resources /」)の「resources」という名前のフォルダーに配置できることを示しています。

ただし、私の経験では(EclipseとTomcatプラグインを使用しています)、リソースフォルダーinside WEB_INF(またはMETA-INF)を配置する場合にのみ機能します。したがって、推奨する構文は次のとおりです。

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

JSP(または同様の)で、次のようにリソースを参照します。

<script type="text/javascript"
        src="resources/my-javascript.js">
</script>

言うまでもなく、Springディスパッチャーサーブレット(フロントコントローラー)がすべて、つまり動的なものすべてをインターセプトするようにしたかったため、質問全体が発生しました。そのため、web.xmlに次のものがあります。

<servlet>
    <servlet-name>front-controller</servlet-name>
    <servlet-class>
                org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
    <!-- spring automatically discovers /WEB-INF/<servlet-name>-servlet.xml -->
</servlet>

<servlet-mapping>
    <servlet-name>front-controller</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

最後に、現在のベストプラクティスを使用しているため、フロントコントローラーサーブレットxmlに次のものがあります(上記を参照)。

<mvc:annotation-driven/>

また、実際のコントローラーの実装には、すべての着信要求を処理するデフォルトのメソッドがあることを確認するために次のものがあります。

@RequestMapping("/")

これがお役に立てば幸いです。

8
Puneet Lamba

私は同じ問題を抱えており、Jorisの答えは非常に役に立ちました。しかし、さらに追加する必要があります

<mvc:annotation-driven /> 

サーブレット構成ファイルに。これがないと、リソースマッピングは機能せず、すべてのハンドラーが機能しなくなります。これが誰かを助けることを願っています。

私はこのように解決しました:

<servlet-mapping>
    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
    <url-pattern>/</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>*.png</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.gif</url-pattern>
</servlet-mapping>
<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>

これはTomcatおよびもちろんJbossで動作します。しかし、最終的には、はるかに移植性の高いソリューション Spring提供 (rozkyによると)を使用することにしました。

2
Chepech

Spring 3以降、すべてのリソースを異なる方法でマッピングする必要があります。タグを使用して、リソースの場所を指定する必要があります。

例:

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

このようにすることで、静的コンテンツを探すためにディレクトリリソースを調べるようディスパッチャサーブレットに指示します。

URLRewriteは、「ハック」のようなものです。要するに、あなたは車輪を再発明しています。既存のソリューションがあるため。覚えておくべきもう1つのことは、Httpサーバー=静的コンテンツ&アプリサーバー=動的コンテンツです(これが設計された方法です)。各サーバーに適切な責任を委任することにより、効率を最大限に高めることができます...しかし、今日ではこれはおそらくパフォーマンスが重要な環境での懸念事項であり、Tomcatのようなものはほとんどの場合、両方の役割でうまく機能します;しかし、それでもなお心に留めておくべきものです。

2
Stoney

この問題を解決する私の方法は、「web」や「service」などの特定のプレフィックスを持つすべてのアクションを配置し、そのプレフィックスを持つすべてのURLがDispatcherServletによってインターセプトされるように構成することです。

1
Teja Kantamneni

Spring mvc 3.0.xに基づいたurlrewriteとアノテーションの両方の方法を使用し、アノテーションベースのアプローチが最も適していることがわかりました

<annotation-driven />

<resources mapping="/resources/**" location="/resources/" />

Urlrewriteの場合は、多くのルールを定義する必要があります。また、UrlRewriteFilterの依存関係が既に提供されているため、クラスが見つからない例外も取得する必要があります。私はそれが推移的な依存関係の存在のために起こっていることを発見したので、再び1つのステップが増加し、その依存関係をpom.xmlから除外する必要があります

<exclusion></exclusion> tags.

したがって、注釈ベースのアプローチが大いに役立ちます。

1
Ruju

この問題を解決するために、Tuckeyのurlrewritefilter(urlrewrite.xml)に春のデフォルトルール(/ **)の前に3つのルールを追加するだけです。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN" "http://tuckey.org/res/dtds/urlrewrite3.0.dtd">
    <urlrewrite default-match-type="wildcard">
     <rule>
      <from>/</from>
      <to>/app/welcome</to>
     </rule>
     <rule>
      <from>/scripts/**</from>
      <to>/scripts/$1</to>
     </rule>
     <rule>
      <from>/styles/**</from>
      <to>/styles/$1</to>
     </rule>
     <rule>
      <from>/images/**</from>
      <to>/images/$1</to>
     </rule>
     <rule>
      <from>/**</from>
      <to>/app/$1</to>
     </rule>
     <outbound-rule>
      <from>/app/**</from>
      <to>/$1</to>
     </outbound-rule> 
    </urlrewrite>
1
Pablo Cantero

Javaベースのスプリング構成の場合、次を使用できます。

ResourceHandlerRegistry を使用すると、静的リソースを提供するためのリソースハンドラーの登録が保存されます。

詳細@ WebMvcConfigurerAdapter これは、@ EnableWebMvcを介して有効化されたSpring MVCのJavaベースの構成をカスタマイズするコールバックメソッドを定義します。

@EnableWebMvc
@Configurable
@ComponentScan("package.to.scan")
public class WebConfigurer extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static_resource_path/*.jpg").addResourceLocations("server_destination_path");

    }
1
Vipul Panth

これは私の場合本当の仕事をしました

web.xmlで:

...
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/images/*</url-pattern>
    <url-pattern>/css/*</url-pattern>
    <url-pattern>/javascripts/*</url-pattern>
</servlet-mapping>


<servlet-mapping>
    <servlet-name>spring-mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

...

1
Jorge Sanchez

静的コンテンツを使用するための構成がいくつかあることは知っていますが、私の解決策は、Tomcat内に一括Webアプリケーションフォルダーを作成するだけです。この「バルクwebapp」は、アプリを提供せずにすべての静的コンテンツのみを提供しています。これは、実際のSpring Webアプリに静的コンテンツを提供するための簡単で簡単なソリューションです。

たとえば、Tomcatで2つのwebappフォルダーを使用しています。

  1. springapp:img、js、cssなどの静的コンテンツなしで、Spring Webアプリケーションのみを実行しています。 (春のアプリ専用)
  2. リソース:JSP、サーブレット、またはJava Webアプリケーションを使用せずに静的コンテンツのみを提供しています。 (静的コンテンツ専用)

Javascriptを使用する場合は、javascriptファイルのURIを追加するだけです。

EX> / resources/path/to/js/myjavascript.js

静止画像の場合、同じ方法を使用しています。

EX> / resources/path/to/img/myimg.jpg

最後に、Tomcatに「security-constraint」を追加して、実際のディレクトリへのアクセスをブロックします。静的コンテンツパスにアクセスしようとしたときにページが「403禁止エラー」を生成するように、「nobody」ユーザーロールを制約に設定しました。

これまでのところ、私にとって非常にうまく機能しています。また、Amazon、Twitter、Facebookなどの多くの人気Webサイトでは、静的コンテンツの提供に異なるURIを使用していることに気付きました。これを確認するには、静的コンテンツを右クリックして、URIを確認します。

1
0DayHack

これは、少なくとも3つの方法で実現できます。

ソリューション

  • htmlをリソースファイルとして公開する
  • * .htmlリクエストも処理するようにJspServletに指示します
  • 独自のサーブレットを作成します(または別の既存のサーブレットリクエストを* .htmlに渡します)。

これを達成する方法の完全なコード例については、別の投稿の私の回答を参照してください: Spring MVCでHTMLファイルにリクエストをマッピングする方法は?

0
walkeros

問題はURLPatternにあります

サーブレットマッピングのURLパターンを「/」から「/ *」に変更します

0
asif malek

ここで説明したのと同じ意思決定プロセスに遭遇し、それを経て、ResourceServletの提案を採用することにしました。

Mavenビルドプロセスでwebflowを使用する方法の詳細については、ここで入手できることに注意してください。 http://static.springsource.org/spring-webflow/docs/2.0.x/reference/html/ch01s05.html

標準のMavenセントラルリポジトリを使用する場合、アーティファクトは(上記で参照したspringsourceバンドルとは異なります):

<dependency>
    <groupId>org.springframework.webflow</groupId>
    <artifactId>spring-js</artifactId>
    <version>2.0.9.RELEASE</version>
</dependency> 
0
ngeek

次のパスにcss、jsなどの静的コンテンツを配置します

resources 
        ->static
               ->css
               ->js
(or) 
resources 
        ->public
               ->css
               ->js
<?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