Spring Boot no sirve contenido estático

Estoy golpeando mi cabeza contra la pared por un par de horas. Mi proyecto está casi terminado, pero no puedo obtener contenido estático.

He colocado una carpeta llamada static en src/main/resources . Dentro de él tengo una carpeta llamada images . Cuando empaco la aplicación y la ejecuto, no puede encontrar las imágenes que he puesto en esa carpeta.

Intenté poner los archivos estáticos en public , resources y resources META-INF/resources pero nada funciona.

Si jar -tvf app.jar puedo ver que los archivos están dentro del /static/images/head.png en la carpeta derecha: /static/images/head.png por ejemplo, pero llamando a: http://localhost:8080/images/head.png , todo lo que obtengo es un 404

¿Alguna idea de por qué Spring-Boot no está encontrando esto? (Estoy usando 1.1.4 por cierto)

No para resucitar a los muertos después de más de un año, pero todas las respuestas anteriores omiten algunos puntos cruciales:

  1. @EnableWebMvc en su clase desactivará org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration . Eso está bien si quieres un control total, pero de lo contrario, es un problema.
  2. No es necesario escribir ningún código para agregar otra ubicación para recursos estáticos además de lo que ya está provisto. Mirando org.springframework.boot.autoconfigure.web.ResourceProperties desde v1.3.0.RELEASE, veo un campo staticLocations que se puede configurar en application.properties . Aquí hay un fragmento de la fuente:

     /** * 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. Como se mencionó anteriormente, la URL de solicitud se resolverá en relación con estas ubicaciones. Por lo tanto src/main/resources/static/index.html se servirá cuando la URL de solicitud sea /index.html . La clase que se encarga de resolver la ruta, a partir de Spring 4.1, es org.springframework.web.servlet.resource.PathResourceResolver .

  4. La coincidencia de patrón de sufijo está habilitada de manera predeterminada, lo que significa que para una URL de solicitud /index.html , Spring buscará los controladores correspondientes a /index.html . Este es un problema si la intención es servir contenido estático. Para desactivar eso, extienda WebMvcConfigurerAdapter (pero no use @EnableWebMvc ) y anule configurePathMatch como se muestra a continuación:

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

En mi humilde opinión, la única manera de tener menos errores en su código es no escribir código siempre que sea posible. Usa lo que ya está provisto, incluso si eso requiere un poco de investigación, el rendimiento vale la pena.

A diferencia de lo que dice la bota de resorte, para que mi contenedor de arranque de spring sirva al contenido: tuve que agregar registrar específicamente mi contenido src / main / resources / static a través de esta clase de configuración:

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

Tuve un problema similar, y resultó que la solución simple era hacer que mi clase de configuración ampliara WebMvcAutoConfiguration :

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

No necesitaba ningún otro código para permitir que se sirviera mi contenido estático, sin embargo, puse un directorio llamado public bajo src/main/webapp y lo configuré para apuntar a src/main/webapp como un directorio de recursos. Esto significa que public se copia en target/classes y, por lo tanto, está en el classpath en tiempo de ejecución para que spring-boot / tomcat lo encuentre.

Busque controladores asignados a “/” o sin ruta mapeada.

Tuve un problema como este, obtuve 405 errores y me golpeé la cabeza por días. El problema resultó ser un controlador anotado @RestController que olvidé anotar con una anotación @RequestMapping . Supongo que esta ruta mapeada dejó de forma predeterminada “/” y bloqueó la asignación de recursos de contenido estático.

La configuración se puede hacer de la siguiente manera:

 @Configuration @EnableWebMvc public class WebMvcConfig extends WebMvcAutoConfigurationAdapter { // specific project configuration } 

Importante aquí es que su WebMvcConfig puede anular el método addResourceHandlers y, por lo tanto, debe invocar explícitamente super.addResourceHandlers(registry) (es cierto que si está satisfecho con las ubicaciones de recursos predeterminadas, no es necesario que anule ningún método).

Otra cosa que debe comentarse aquí es que esas ubicaciones de recursos predeterminadas ( /static , /public , /resources y /META-INF/resources ) se registrarán solo si no hay un manejador de recursos mapeado en /** .

A partir de este momento, si tiene una imagen en src/main/resources/static/images llamada image.jpg por ejemplo, puede acceder a ella usando la siguiente URL: http://localhost:8080/images/image.jpg ( siendo el servidor iniciado en el puerto 8080 y la aplicación desplegada en el contexto raíz).

¿Revisaste los documentos de referencia de Spring Boot ?

Por defecto Spring Boot servirá contenido estático desde una carpeta llamada /static (o /public o /resources o /META-INF/resources ) en classpath o desde la raíz de ServletContext.

También puede comparar su proyecto con la guía Servicio de contenido web con Spring MVC , o consulte el código fuente del proyecto spring-boot-sample-web-ui .

Esta solución funciona para mí:

Primero, coloque una carpeta de recursos bajo webapp / WEB-INF, como sigue la estructura

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

En segundo lugar, en el archivo de configuración de spring

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

Luego, puede acceder a su contenido de recursos, como http: // localhost: 8080 / resource / image / yourimage.jpg

Estaba teniendo este problema exacto, luego me di cuenta de que lo había definido en mi application.properties:

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

Que estaba anulando todo lo demás que había intentado. En mi caso, quería conservar ambos, así que solo guardé la propiedad y agregué:

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

Que sirvió archivos desde src / main / resources / static como localhost: {port} /file.html.

Ninguno de los anteriores funcionó para mí porque nadie mencionó esta pequeña propiedad que podría haberse copiado fácilmente en línea para cumplir un propósito diferente;)

¡Espero eso ayude! Supuse que encajaría bien en este largo post de respuestas para las personas con este problema.

Creo que las respuestas anteriores abordan el tema muy bien. Sin embargo, agregaría que en un caso cuando tiene Spring Security habilitado en su aplicación, es posible que tenga que decirle específicamente a Spring que permita solicitudes a otros directorios de recursos estáticos como, por ejemplo, “/ static / fonts” .

En mi caso, tenía “/ static / css”, “/ static / js”, “/ static / images” permitido por defecto, pero / static / fonts / ** fue bloqueado por la implementación de Spring Security.

A continuación se muestra un ejemplo de cómo arreglé esto.

 @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 } ..... } 

Hay dos cosas a considerar (Spring Boot v1.5.2.RELEASE) – 1) Compruebe todas las clases de Controller para la anotación @EnableWebMvc, elimínelas si hay alguna 2) Compruebe las clases de Controller para las cuales se usa la anotación – @RestController o @Controller . No mezcle el comportamiento Rest API y MVC en una clase. Para MVC use @Controller y para API REST use @RestController

Hacer más de 2 cosas resolvió mi problema. Ahora mi arranque de spring está cargando recursos estáticos sin ningún problema. @Controller => load index.html => carga archivos estáticos.

 @Controller public class WelcomeController { // inject via application.properties @Value("${welcome.message:Hello}") private String message = "Hello World"; @RequestMapping("/") public String home(Map model) { model.put("message", this.message); return "index"; } } index.html < !DOCTYPE html>   index            

En caso de que surja un problema al iniciar la aplicación desde un IDE (es decir, desde Eclipse o IntelliJ Idea) y utilizando Maven, la clave de la solución se encuentra en la documentación de inicio de Spring-boot :

Si está utilizando Maven, ejecute:

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

La parte importante de esto es agregar el objective del package para que se ejecute antes de que realmente se inicie la aplicación. (Idea: menú Run , Edit Configrations... , Add , y seleccione Run Maven Goal y especifique el objective del package en el campo)

Solo para agregar otra respuesta a una vieja pregunta … Las personas han mencionado que @EnableWebMvc evitará que se WebMvcAutoConfiguration , que es el código responsable de crear los manejadores de recursos estáticos. Hay otras condiciones que evitarán que WebMvcAutoConfiguration cargue. La manera más clara de ver esto es mirar la fuente:

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

En mi caso, WebMvcConfigurationSupport una biblioteca que tenía una clase que se extendía desde WebMvcConfigurationSupport que es una condición que impedirá la configuración automática:

 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) 

Es importante que nunca se extienda desde WebMvcConfigurationSupport . En cambio, extienda desde WebMvcConfigurerAdapter .

Tuve el mismo problema, usando gradle y eclipse y pasé horas intentando descubrirlo.

No se requiere encoding, el truco es que debe usar la opción de menú Nuevo-> Carpeta de origen (NO nueva -> Carpeta) para crear la carpeta estática en src / main / resources. No sé por qué funciona esto, pero hice una nueva -> carpeta de origen y luego nombré la carpeta como estática (luego el cuadro de diálogo de la carpeta de origen arroja un error que debe verificar: actualice los filtros de exclusión en otras carpetas de origen para solucionar el anidamiento). Mi nueva carpeta estática agregué index.html y ahora funciona.

Estoy usando 1.3.5 y alojo un montón de servicios REST a través de la implementación de Jersey. Eso funcionó bien hasta que decidí agregar un par de archivos HTMLs + js. Ninguna de las respuestas dadas en este foro me ayudó. Sin embargo, cuando agregué la siguiente dependencia en mi pom.xml, todo el contenido en src / main / resources / static finalmente se mostraba a través del navegador:

  org.springframework.boot spring-boot-starter-web  

Parece spring-web / spring-webmvc es la importante dependencia transitiva que hace que las configuraciones automáticas de arranque de spring se enciendan.

Bueno, a veces vale la pena comprobar si anulaste las asignaciones globales mediante algún controlador de reposo. Error simple de ejemplo (kotlin):

 @RestController("/foo") class TrainingController { @PostMapping fun bazz(@RequestBody newBody: CommandDto): CommandDto = return commandDto } 

En el caso anterior, obtendrá cuando solicite recursos estáticos:

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

La razón de esto podría ser que quería asignar @PostMapping a /foo pero olvidarse de la anotación @RequestMapping en el nivel @RestController . En este caso, todas las solicitudes se asignan a POST y no recibirá contenido estático en este caso.

Por defecto Spring Boot sirve recursos estáticos definidos en las siguientes rutas:

  • / META-INF / recursos /
  • / recursos /
  • /estático/
  • /público/

Para cambiar las rutas predeterminadas de recursos estáticos, puede definir el atributo “spring.resources.static-locations” en application.properties como se muestra a continuación:

 spring.resources.static-locations=/html/,/js/,/css/ 

En su caso, está utilizando las rutas predeterminadas leídas por Spring Boot, no debería obtener 404 al acceder / images / a menos que definiera explícitamente una ruta de contexto diferente para su aplicación o habilitó @EnableWebMvc que anula la configuración predeterminada de Spring Boot .

Para obtener más información sobre cómo servir y cargar recursos estáticos en Spring Boot, verifique esto: Sirva recursos estáticos con Spring Boot.

Estoy en la misma situación donde mi aplicación angular de inicio de spring (integración) no está sirviendo contenido de la carpeta estática para mostrar UI en localhost: 8080. Frontend se desarrolla en angular4, por lo que se usa ng build que generó archivos en la ruta de salida dir src / main / resources / static pero no muestra ningún contenido. Hice un controlador específicamente para servir index.html, pero parece que algo está desactivado para que spring-boot pueda comprender el enrutamiento angular y localhost: 8080 solo muestra la cadena devuelta desde mi método de control “index.html” en la página web. A continuación está index.html (Cambié la etiqueta de selector predeterminada en el cuerpo para que el componente de inicio de sesión sea el que he creado y mi componente angular principal para la interfaz de usuario, pero todavía no funciona si la raíz de la aplicación o esta):

 < !doctype html>    Hello Test App         

Código del controlador:

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

No estoy seguro si es importante, pero este es un proyecto basado en gradle desarrollado en IntellijIdea y la versión de arranque de spring es – org.springframework.boot:spring-boot-starter-web:2.0.2.RELEASE .

Como se dijo anteriormente, el archivo debe estar en $ClassPath/static/images/name.png , (/ static o / public o / resources o / META-INF / resources). Este $ ClassPath significa main/resources o main/java dir.

Si sus archivos no están en directorios estándar, puede agregar la siguiente configuración:

 @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/lib/**"); // like this } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // ... etc. } ... 

}