web-dev-qa-db-ja.com

静的コンテンツを提供しないSpring Boot

Spring-bootプロジェクトで静的コンテンツを提供することができません。

src/main/resourcesの下にstaticという名前のフォルダーを配置しました。その中にimagesという名前のフォルダーがあります。アプリをパッケージして実行すると、そのフォルダーに置いた画像が見つかりません。

静的ファイルをpublicresources、およびMETA-INF/resourcesに配置しようとしましたが、何も機能しません。

-tvf app.jarをjarすると、ファイルが正しいフォルダーのjar内にあることがわかります。たとえば、/static/images/head.pngですが、http://localhost:8080/images/head.pngを呼び出すと、404だけが取得されます

Spring-Bootがこれを見つけられない理由はありますか? (1.1.4 BTWを使用しています)

140

1年以上経っても死者を増やすことはしないでください。ただし、これまでのすべての回答でいくつかの重要な点を見逃しています。

  1. クラスの@EnableWebMvcorg.springframework.boot.autoconfigure.web.WebMvcAutoConfigurationを無効にします。完全な制御が必要な場合はそれで問題ありませんが、それ以外の場合は問題です。
  2. すでに提供されているものに加えて、静的リソース用に別の場所を追加するためのコードを書く必要はありません。 v1.3.0.RELEASEのorg.springframework.boot.autoconfigure.web.ResourcePropertiesを見ると、application.propertiesで設定できるフィールドstaticLocationsが見えます。これは、ソースからの抜粋です。

    /**
     * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
     * /resources/, /static/, /public/] plus context:/ (the root of the servlet context).
     */
    private String[] staticLocations = RESOURCE_LOCATIONS;
    
  3. 前述のように、リクエストURLはこれらの場所に対して相対解決されます。したがって、リクエストURLがsrc/main/resources/static/index.htmlの場合は/index.htmlが提供されます。パスの解決を担当するクラスは、Spring 4.1以降ではorg.springframework.web.servlet.resource.PathResourceResolverです。

  4. 接尾辞パターンマッチングはデフォルトで有効になっています。つまり、リクエストURL /index.htmlに対して、Springは/index.htmlに対応するハンドラを探します。意図が静的コンテンツを提供することである場合、これは問題です。これを無効にするには、WebMvcConfigurerAdapterを拡張し(ただし@EnableWebMvcは使用しないでください)、次に示すようにconfigurePathMatchをオーバーライドします。

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        super.configurePathMatch(configurer);
    
        configurer.setUseSuffixPatternMatch(false);
    }
    

私見、あなたのコードでより少ないバグを持つ唯一の方法は可能な限りコードを書くことではありません。すでに提供されているものを使用してください。たとえそれがいくらかの調査を必要とするとしても、その見返りは価値があります。

145
Abhijit Sarkar

Spring-bootが述べているのとは違って、私のspring-boot jarがコンテンツを提供するようにするために:私はこのconfigクラスを通して私のsrc/main/resources/staticコンテンツを特別に登録しなければなりません:

@Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {

    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
            "classpath:/META-INF/resources/", "classpath:/resources/",
            "classpath:/static/", "classpath:/public/" };

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
            .addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
    }
}
64
Francois

私は同じような問題を抱えていました、そして、単純な解決策は私の設定クラスがWebMvcAutoConfigurationを拡張することであることがわかった:

@Configuration
@EnableWebMvc
@ComponentScan
public class ServerConfiguration extends WebMvcAutoConfiguration{
}

静的コンテンツを提供するために他のコードは必要ありませんでしたが、src/main/webappの下にpublicというディレクトリを置き、リソースディレクトリとしてsrc/main/webappを指すようにmavenを構成しました。これは、publictarget/classesにコピーされるため、実行時にspring-boot/Tomcatが見つけることができるクラスパス上にあることを意味します。

47

「/」にマップされているか、パスがマップされていないコントローラを探します。

私はこのような問題を抱えていました、405のエラーを得て、そして数日間私の頭を激しく打ちました。問題は、私が@RestControllerアノテーションを付けることを忘れていた@RequestMappingアノテーションを付けられたコントローラーであることがわかりました。このマッピングパスはデフォルトで "/"に設定されており、静的コンテンツリソースマッピングはブロックされていると思います。

22
Johannes

構成は次のようにすることができます。

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcAutoConfigurationAdapter {

// specific project configuration

}

ここで重要なのは、WebMvcConfigmayaddResourceHandlersメソッドをオーバーライドすることです。したがって、明示的にsuper.addResourceHandlers(registry)を呼び出す必要があります(デフォルトのリソースの場所に問題がなければ、メソッドをオーバーライドする必要はありません)。

ここでコメントする必要があるもう1つのことは、それらのデフォルトリソースロケーション(/static/public/resources、および/META-INF/resources)は、/**にマップされたリソースハンドラがまだない場合にのみ登録されるということです。

これ以降、たとえばsrc/main/resources/static/imagesという名前でimage.jpgという名前のイメージがある場合は、次のURLを使用してアクセスできます。http://localhost:8080/images/image.jpg(サーバーはポート8080で起動され、アプリケーションはルートコンテキストにデプロイされています)。

18

Spring Bootのリファレンスドキュメント をチェックしましたか?

デフォルトでは、Spring Bootはクラスパス内の/static(または/publicまたは/resourcesまたは/META-INF/resources)という名前のフォルダーまたはServletContextのルートから静的コンテンツを提供します。

プロジェクトとガイドを比較することもできます Spring MVCを使用したWebコンテンツの提供 、または spring-boot-sample-web-ui プロジェクトのソースコードをチェックすることもできます。

11
matsev

私はこの正確な問題を抱えていました、それから私は私のapplication.propertiesで定義したことに気づきました:

spring.resources.static-locations=file:/var/www/static

これは私が試した他のすべてを無効にしていました。私の場合は、両方を保持したいので、プロパティを保持して追加しました。

spring.resources.static-locations=file:/var/www/static,classpath:static

これはsrc/main/resources/staticからlocalhost:{port} /file.htmlとしてファイルを提供します。

別の目的を果たすためにオンラインから簡単にコピーされる可能性のあるこの小さなプロパティについては、誰も言及していなかったため、上記のどれも私には役に立ちませんでした。

それが役に立てば幸い!この問題を抱える人々のためのこの長い回答の投稿にうまく適合するだろうと考えました。

6
S. Jacob Powell

私は前の答えがそのトピックに非常によく取り組んでいると思います。ただし、アプリケーションでSpring Securityが有効になっている場合は、たとえば"/ static/fonts"のように、他の静的リソースディレクトリへの要求を許可するようにSpringに明確に指示する必要があるかもしれません。 =。

私の場合、デフォルトで "/ static/css"、 "/ static/js"、 "/ static/images"が許可されていましたが、/ static/fonts/**はSpring Securityの実装によってブロックされていました。

以下は私がこれをどのように修正したかの例です。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.....
    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/", "/fonts/**").permitAll().
        //other security configuration rules
    }
.....
}
5
RemusS

@EnableWebMvcは静的リソースハンドラを作成するコードであるWebMvcAutoConfigurationがロードされないようにすると人々は言っています。 WebMvcAutoConfigurationがロードされないようにする条件が他にもあります。これを確認する最も明確な方法は、ソースを見ることです。

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/Java/org/springframework/boot/autoconfigure/ web/servlet/WebMvcAutoConfiguration.Java#L139-L141

私の場合は、自動設定を妨げる条件であるWebMvcConfigurationSupportから拡張されたクラスを持つライブラリを含めていました。

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

WebMvcConfigurationSupportから拡張しないことが重要です。代わりにWebMvcConfigurerAdapterから拡張してください。

3
Bal

この解決策は私のために働く:

まず、次のようにwebapp/WEB-INFの下にresourcesフォルダを置きます。

-- src
  -- main
    -- webapp
      -- WEB-INF
        -- resources
          -- css
          -- image
          -- js
          -- ...

第二に、春の設定ファイルで

@Configuration
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter{

    @Bean
    public ViewResolver getViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".html");
        return resolver;
    }

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

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resource/**").addResourceLocations("WEB-INF/resources/");
    }
}

そうすれば、 http:// localhost:8080/resource/image/yourimage.jpg のように、リソースのコンテンツにアクセスできます。

3
ldeng

IDE内から(つまりEclipseまたはIntelliJ Ideaから始めて)アプリケーションを起動し、Mavenを使用しているときに問題が表面化する場合、解決策の鍵は Spring-にあります。 bootはじめに ドキュメント:

Mavenを使用している場合は、次のコマンドを実行してください。

mvn package && Java -jar target/gs-spring-boot-0.1.0.jar

その重要な部分は、packageという目標を追加して、アプリケーションを実際に起動する前に実行することです。 (アイデア:Runメニュー、Edit Configrations...Add、そしてそこからRun Maven Goalを選択し、フィールドにpackageの目標を指定します)

2
ppeterka

考慮すべきことが2つあります(Spring Boot v1.5.2.RELEASE) - 1)すべてのControllerクラスで@EnableWebMvcアノテーションがないか確認し、存在する場合は削除します2)アノテーションが使用されているControllerクラスをチェックします - @RestControllerまたは@Controller 。 1つのクラスにRest APIとMVCの動作を混在させないでください。 MVCには@Controllerを使い、REST AP​​Iには@RestControllerを使います。

2つ以上のことをすることで私の問題は解決しました。今私の春のブートは何の問題もなく静的なリソースをロードしています。 @Controller => load index.html =>静的ファイルをロードします。

@Controller
public class WelcomeController {

    // inject via application.properties
    @Value("${welcome.message:Hello}")
    private String message = "Hello World";

    @RequestMapping("/")
    public String home(Map<String, Object> model) {
        model.put("message", this.message);
        return "index";
    }

}

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>index</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />


    <link rel="stylesheet/less" th:href="@{/webapp/assets/theme.siberia.less}"/>

    <!-- The app's logic -->
    <script type="text/javascript" data-main="/webapp/app" th:src="@{/webapp/libs/require.js}"></script>
    <script type="text/javascript">
        require.config({
            paths: { text:"/webapp/libs/text" }
        });
    </script>



   <!-- Development only -->
     <script type="text/javascript" th:src="@{/webapp/libs/less.min.js}"></script>


</head>
<body>

</body>
</html>
2
gjp

私はリソースが404を見つけられなかったと言って私は春のブート2.1.3で同じ問題に直面していました。私はapplicatiion.propertiesから以下を削除しました。

#spring.resources.add-mappings=true
#spring.resources.static-locations=classpath:static
#spring.mvc.static-path-pattern=/**,

@ enableWebMVC を削除し、オーバーライドしているWebMvcConfigurerを削除しました

// @ EnableWebMvc

また、設定に @ EnableAutoConfiguration があることを確認してください。

そして、すべての静的リソースを src/main/resources/static に入れると、ついには魔法のように動作しました。

1
Debadatta

私は1.3.5を使用しており、Jerseyの実装を介して多数のRESTサービスをホストしています。私はいくつかのHTML + jsファイルを追加することを決心するまでそれはうまくいきました。このフォーラムで与えられた答えのどれも私を助けませんでした。しかし、私のpom.xmlに以下の依存関係を追加すると、src/main/resources/staticの内容はすべてブラウザ経由で表示されていました。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<dependency>

Spring-web/spring-webmvcはspring boot auto configを有効にする重要な推移的依存関係のようです。

0
LilleElefant

私のSpring-Boot Angularアプリ(統合)がlocalhost:8080でUIを表示するために静的フォルダの内容を提供していないのと同じ状況にあります。フロントエンドはangular4で開発されているので、ng buildを使用して、出力パスdir src/main/resources/staticにファイルを生成しますが、内容は表示されません。私はindex.htmlを提供するために特別にコントローラを作りましたが、角度付きのものとlocalhostを理解するために何かが起動していないようです:8080は私のコントローラメソッド "index.html"から返された文字列をウェブページに表示するだけです。以下はindex.htmlです(私はログインコンポーネントが私が作成したものであり、UI用の私の主要なコンポーネントであるが、それでもapp-rootであろうとこれであろうと動作しません)。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Hello Test App</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-login></app-login>
<script type="text/javascript" src="runtime.js"></script><script type="text/javascript" src="polyfills.js"></script><script type="text/javascript" src="styles.js"></script><script type="text/javascript" src="vendor.js"></script><script type="text/javascript" src="main.js"></script></body>
</html>

コントローラコード:

@RequestMapping("/")
public String userInterface() {
    return "index.html";
}

それが問題であるかどうかわからないが、これはIntellijIdeaで開発されたgradleベースのプロジェクトであり、春のブートバージョンは-org.springframework.boot:spring-boot-starter-web:2.0.2.RELEASEです。

@Vizcaino - 簡単なトリックがあるとおっしゃったように - Intellijideaは同様にソースディレクトリ/フォルダを作成するための同様のオプションを提供しますか?右クリックメニュー - >新規作成 - >ディレクトリから作成しました。しかし、それが私の問題の原因であろうかどうか疑問に思う、それが同じことかどうかわからない?

0
user6087439

グローバルコントローラを他のコントローラで上書きしたかどうかをチェックする価値があることもあります。簡単な例の間違い(kotlin):

@RestController("/foo")
class TrainingController {

    @PostMapping
    fun bazz(@RequestBody newBody: CommandDto): CommandDto = return commandDto

}

上記の場合、静的リソースを要求したときに取得します。

{
    title: "Method Not Allowed",
    status: 405,
    detail: "Request method 'GET' not supported",
    path: "/index.html"
}

その理由は、@PostMapping/fooにマッピングしたいが、@RequestMappingレベルでの@RestControllerアノテーションを忘れていたことかもしれません。この場合、すべてのリクエストはPOSTにマップされ、この場合は静的コンテンツを受け取ることはできません。

0
Przemek Nowak

FYI:私は完璧に機能するSpring Bootのアプリをめちゃくちゃにして静的フォルダのコンテンツを提供できないようにすることもできます。

 @RestController
public class BadController {
    @RequestMapping(method= RequestMethod.POST)
    public String someMethod(@RequestParam(value="date", required=false)String dateString, Model model){
        return "foo";
    }
}

この例では、プロジェクトに不適切なコントローラを追加した後、ブラウザが静的フォルダにあるファイルを要求すると、エラー応答は 'になります。405 Method Not Allowed '。

注意コントローラパスの例では、パスがマッピングされていません。

0
Ganesh

GradleとEclipseを使用して同じ問題を抱えていて、それを把握するために何時間も費やしました。

コーディングは必要ありません。トリックは、メニューオプション[新規作成] - > [ソースフォルダ]([新規] - > [フォルダ])を使用して、src/main/resourcesの下に静的フォルダを作成する必要があることです。なぜこれが機能するのかわからないが、新しい - >ソースフォルダをしてから静的フォルダにした(それからソースフォルダダイアログでチェックしなければならないエラーが表示される)私が新しく追加したstaticフォルダにindex.htmlを追加しましたが、これで動作します。

0
Vizcaino