it-swarm.com.de

Ein Spring Boot-Projekt mit statischem Inhalt generiert 404, wenn jar ausgeführt wird

Der aktuelle Blogbeitrag ( https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot ) von Spring zur Verwendung statischer Webinhalte in Spring Bootprojekte zeigen an, dass mehrere Ressourcenverzeichnisse verwendet werden können:

  • / META-INF/Ressourcen /
  • /Ressourcen/
  • /statisch/
  • /Öffentlichkeit/

Dies ist der WebMvcAutoConfiguration-Klasse zu verdanken, die diese Verzeichnisse automatisch zum Klassenpfad hinzufügt. Das alles scheint in Ordnung zu sein und scheint zu funktionieren, wenn das Ziel spring-boot-maven-plugin _ ​​spring-boot: run verwendet wird. Der gesamte statische Inhalt funktioniert (zB:/index.html).

Wenn Sie Ihr Spring Boot-Projekt packen und das spring-boot-maven-plugin zur Erstellung der erweiterten JAR zulassen, dann versuchen, Ihr Projekt mit Java -jar my-spring-boot-project.jar auszuführen, stellen Sie fest, dass Ihr statischer Inhalt jetzt einen 404-Fehler zurückgibt.

22
Robert Hunt

Es hat sich herausgestellt, dass Spring Boot zwar geschickt die verschiedenen Ressourcenverzeichnisse zum Klassenpfad hinzufügt, Maven jedoch nicht und es liegt an Ihnen, sich mit diesem Teil auseinanderzusetzen. Standardmäßig wird nur src/main/resources in Ihr JAR aufgenommen. Wenn Sie im Stammverzeichnis Ihres Projekts einen Ordner mit dem Namen /static erstellen (wie im Blogbeitrag impliziert), funktioniert es gut, wenn Sie dasspring-boot: runMaven-Ziel verwenden KRUG.

Die einfachste Lösung ist, Ihren /static-Ordner in /src/main/resources zu erstellen, und Maven fügt ihn in die JAR ein. Alternativ können Sie Ihrem Maven-Projekt weitere Ressourcenorte hinzufügen:

<resources>
    <resource>
        <directory>src/main/resources</directory>
    </resource>
    <resource>
        <directory>static</directory>
        <targetPath>static</targetPath>
    </resource>
</resources>

Ich hoffe, dass dies für jemanden nützlich ist. Es ist ziemlich offensichtlich, wenn Sie einen Schritt zurücktreten und sich ansehen, wie Maven funktioniert. Es könnte jedoch ein paar Leute stumpfen, die Spring Boot verwenden, da sie ziemlich konfigurationsfrei sind.

36
Robert Hunt

Ich pralle mit dem Kopf gegen die Wand und versuche herauszufinden, wie man das mit Gradle macht. Irgendwelche Tipps?

EDIT: Ich habe es zum funktionieren gebracht, indem ich dies zu meinem build.gradle hinzugefügt habe:

// Copy resources into the jar as static content, where Spring expects it.
jar.into('static') {
    from('src/main/webapp')
}
7
kgreenek

Ich habe ein paar Seiten durchgegangen, um zu verstehen, wie man statische Inhalte in der Spring-Boot-Umgebung bereitstellt. In den meisten Fällen wurde empfohlen, die statischen Dateien mit in/static/resources/src/main/webapp usw. abzulegen.

  1. Lassen Sie den Spring Boot automatisch das Dispatcher Servlet konfigurieren - Stellen Sie sicher, dass sich DispatcherServletAutoConfiguration nicht für die AutoConfiguration ausschließt.

    @EnableAutoConfiguration (exclude = { //DispatcherServletAutoConfiguration.class,})

  2. Injizieren Sie Ihr externes Verzeichnis für das statische Weiterleiten von Inhalten

    @Value ("$ {static-content.locations: file: C:/myprj/static /") Private String [] staticContentLocations;

3. Überschreiben Sie WebMvcAutoConfiguration mit Hilfe von WebMvcConfigurerAdapter, um den Frühling anzuweisen, die Standardressource Location nicht zu verwenden, sondern die Anweisungen, die wir anweisen 

@Bean
    public WebMvcConfigurerAdapter webMvcConfigurerAdapter()
    {
        return new WebMvcConfigurerAdapter()
        {
            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry)
            {
                if (!registry.hasMappingForPattern("/**"))
                {
                    // if this is executed spring won't add default resource
                    // locations - add them to the staticContentLocations if
                    // you want to keep them
                    // default locations:
                    // WebMvcAutoConfiguration.RESOURCE_LOCATIONS
                    registry.addResourceHandler("/**").addResourceLocations(
                            staticContentLocations);
                }
            }
        };
    }

Wenn C:/myprj/static index.html hat, sollte http: // localhost: portno/index.html funktionieren. Hoffentlich hilft das.

3
Sriram

Spring Boot verwendet WebMvcAutoConfiguration zum Konfigurieren statischer Inhalte. Diese Klasse wird nur dann wirksam, wenn Sie keine benutzerdefinierte WebMvcConfigurationSupport-Bean haben.

@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class,
        WebMvcConfigurerAdapter.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
        ValidationAutoConfiguration.class })
    public class WebMvcAutoConfiguration {

}

ich muss es also nur selbst konfigurieren, hier ist meine Lösung:

@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/static-file/**").addResourceLocations("classpath:/static/");
}
2
acoder2013

Es gibt zwei Dinge, die zu beachten sind (Spring Boot v1.5.2.RELEASE) - 

1) Überprüfen Sie alle Controller-Klassen auf die Annotation @EnableWebMvc. Entfernen Sie wenn es welche gibt

2) Überprüfen Sie die Controller-Klassen, für die Annotation -.__ verwendet wird. @RestController oder @Controller.

Mischen Sie das Rest-API- und MVC-Verhalten nicht in einer Klasse. Verwenden Sie für MVC @Controller und für die REST - API @RestController

Doing above 2 things resolved my issue. Now my spring boot is loading static resources with out any issues.
@Controller => load index.html => loads static files.

@Controller
public class WelcomeController {

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

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

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

}

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello</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

Ich habe einen Assets-Ordner im statischen Verzeichnis, der in SpringConfig erlaubt, was WebSecurityConfigurerAdapter erweitert.

http.authorizeRequests().antMatchers("/", "/login", "/assets/**")
            .permitAll()
0
Venkat