web-dev-qa-db-fra.com

Le projet Spring Boot au contenu statique génère 404 lors de l'exécution de jar

Le récent article de blog ( https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot ) de Spring concernant l'utilisation de contenu Web statique à Spring Les projets de démarrage indiquent que plusieurs répertoires de ressources peuvent être utilisés:

  • / META-INF/ressources /
  • /Ressources/
  • /statique/
  • /Publique/

Cela est dû à la classe WebMvcAutoConfiguration qui ajoute automatiquement ces répertoires au classpath. Tout cela semble bien et semble fonctionner lorsque vous utilisez l'objectif spring-boot-maven-plugin _ ​​spring-boot: run, tout votre contenu statique fonctionne (par exemple:/index.html).

Lorsque vous empaquetez votre projet Spring Boot et permettez à spring-boot-maven-plugin de créer le fichier JAR amélioré, puis tentez d'exécuter votre projet à l'aide de Java -jar my-spring-boot-project.jar, vous constatez que votre contenu statique renvoie désormais une erreur 404.

22
Robert Hunt

Il se trouve que bien que Spring Boot soit habile à ajouter les divers répertoires de ressources au classpath, Maven ne l’est pas et c’est à vous de gérer cette partie. Par défaut, seul src/main/resources sera inclus dans votre fichier JAR. Si vous créez un dossier appelé /static à la racine de votre projet (comme l’implique la publication du blog), il fonctionnera correctement si vous utilisez l’objectifspring-boot: runMaven, mais pas une fois que vous avez créé un fichier. POT.

La solution la plus simple consiste à créer votre dossier /static dans /src/main/resources, puis Maven l'inclura dans le fichier JAR. Vous pouvez également ajouter des emplacements de ressources supplémentaires à votre projet Maven:

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

J'espère que cela sera utile à quelqu'un. Il est assez évident de prendre du recul pour observer le fonctionnement de Maven, mais cela risque d'empêcher quelques personnes d'utiliser Spring Boot, car il est conçu pour être quasiment sans configuration.

36
Robert Hunt

Je me cogne la tête contre le mur pour essayer de comprendre comment faire cela avec Gradle. Des conseils?

EDIT: Je l'ai fait fonctionner en l'ajoutant à mon build.gradle:

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

Je parcourais quelques pages pour comprendre comment servir du contenu statique dans un environnement d'initialisation Spring. La plupart du temps, nous avons conseillé de placer les fichiers statiques dans/static/resources/src/main/webapp, etc. Penser à partager l'approche ci-dessous.

  1. Autoriser l'amorçage printanier à configurer automatiquement Dispatcher Servlet - Assurez-vous que DispatcherServletAutoConfiguration n'est pas dans l'exclusion pour la configuration automatique.

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

  2. Injectez votre répertoire externe pour le routage de contenu statique

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

3.Override WebMvcAutoConfiguration en utilisant WebMvcConfigurerAdapter pour conseiller au printemps de ne pas utiliser l'emplacement de ressource par défaut, mais d'utiliser ce que nous lui indiquons. 

@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);
                }
            }
        };
    }

Si C:/myprj/static a index.html, alors http: // localhost: portno/index.html devrait fonctionner. J'espère que cela pourra aider.

3
Sriram

Spring Boot utilisera WebMvcAutoConfiguration pour configurer le contenu statique, cette classe ne prendra effet que si vous n'avez pas de bean WebMvcConfigurationSupport personnalisé et, dans mon cas, j'en ai un.

@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 {

}

donc je vais devoir le configurer moi-même, voici ma solution:

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

Il y a 2 choses à considérer (Spring Boot v1.5.2.RELEASE) - 

1) Vérifiez l’annotation @EnableWebMvc dans toutes les classes de contrôleur, supprimez il s'il y en a

2) Vérifiez les classes de contrôleur pour lesquelles l'annotation est utilisée - @RestController ou @Controller.

Ne mélangez pas les comportements Rest API et MVC dans une classe. Pour MVC, utilisez @Controller et pour REST API, utilisez @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

J'ai un dossier de ressources dans un répertoire statique et j'autorise dans SpringConfig l'extension WebSecurityConfigurerAdapter.

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